How to deal with deprecated gradle features were used in this build, making it incompatible with gradle 8.0

How to deal with deprecated gradle features were used in this build, making it incompatible with gradle 8.0

  1. FAILURE
  2. Sometime when you try to build the app you may encounter this FAILURE.
    ..."Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0."
    

  3. Most common Solution
  4. Run the Gradle build with a command line argument --warning-mode=all to see what exactly the deprecated features are.

    It will give you a detailed description of found issues with links to the Gradle docs for instructions how to fix your build.

    Adding --stacktrace to that, you will also be able to pinpoint where the warning comes from, if it's triggered by outdated code in one of the plugins and not your build script.

  5. Solution 2
  6. if the abouve Solution dont work Try this one

    cd android && ./gradlew clean && ./gradlew :app:bundleRelease
    

  7. Solution 3
  8. The process below worked in many case- First check Gradle Version:

    cd android
    ./gradlew -v
    

    In my case it was 6.5

    Go to https://developer.android.com/studio/releases/gradle-plugin and you'll get the plugin version for your gradle version. For gradle version 6.5, the plugin version is 4.1.0

    Then go to app/build.gradle and change classpath 'com.android.tools.build:gradle:<plugin_version>

  9. Solution 4
  10. if your project is incompatible with Gradle 8.0 .Here's what worked for you: First write this line of code in the Android Studio terminal:

    ./gradlew build --warning-mode all
    

    When you do that, you will be shown in the logcat what is found to be deprecated or an issue in your project, for me it was the jcenter() repository that needed to be removed in my settings.gradle file and also I needed to update classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21" to classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.30" in my build.gradle project file.

    Once I did these things, my project built perfectly and installed on my emulator

Kyle Elkins 2022-08-09
Show entire bottom sheet with EditText above Keyboard

Show entire bottom sheet with EditText above Keyboard

  1. FAILURE
  2. implementing a UI where a bottom sheet will appear above the keyboard with an EditText for the user to enter a value. The problem is the View is being partially overlapped by the keyboard, covering up the bottom of the bottom sheet.

  3. Most common Solution
  4. Just reposting @jblejder from this question Keyboard hides BottomSheetDialogFragment since it worked for me, to make it easier for others to find:

    The most convenient way that I found to change this is by creating style:

    <style name="DialogStyle" parent="Theme.Design.Light.BottomSheetDialog">
        <item name="android:windowIsFloating">false</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:windowSoftInputMode">adjustResize</item>
    </style>
    

    And set this in onCreate method of your BottomSheetDialogFragment:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setStyle(DialogFragment.STYLE_NORMAL, R.style.DialogStyle)
    }
    

    This is how it looks on my device:

    enter image description here

    ==== UPDATE ====

    As already mentioned in the Comments a few times, you might also need to set the state of the BottomSheetDialog to STATE_EXPANDED like in Nordknight's answer below

    dialog = new BottomSheetDialog(getContext(), R.style.BottomSheetDialog);  
    dialog.setOnShowListener(new DialogInterface.OnShowListener() {
    @Override
    public void onShow(DialogInterface dialog) {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        BottomSheetDialog d = (BottomSheetDialog) dialog;
                        FrameLayout bottomSheet = d.findViewById(R.id.design_bottom_sheet);
                        BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
                        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                    }
                },0);
            }
        });
    

  5. Solution 2
  6. This might be a redundant answer. Although just pointing out the issue. If you're using BottomSheetDialogFragment, the only way is to enable the attribute android:windowIsFloating to true. This will enable the whole window to be on top of whatever is trying to take the space behind it.

    <style name="BottomSheetDialogThemeNoFloating" parent="Theme.Design.Light.BottomSheetDialog">
            <item name="android:windowIsFloating">false</item>
            <item name="android:windowSoftInputMode">adjustResize|stateVisible</item>
    </style>
    

    Then in your onCreate() of your dialog, set this style.

    override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            // set the window no floating style
            setStyle(DialogFragment.STYLE_NORMAL, R.style.AppRoundedBottomSheetDialogThemeNoFloating)
    }
    

    This is handy for those who frequently use bottom sheets and may want to deal with EditText and soft keyboard overlapping each other.

    Note: The class KeyboardUtil by mikepenz has an issue in which on certain phones, the content view with input field is automatically pushed above keyboard despite giving bottom padding to the whole content view supplied.

  7. Solution 3
  8. dialog = new BottomSheetDialog(getContext(), R.style.BottomSheetDialog);  
    dialog.setOnShowListener(new DialogInterface.OnShowListener() {
    @Override
    public void onShow(DialogInterface dialog) {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        BottomSheetDialog d = (BottomSheetDialog) dialog;
                        FrameLayout bottomSheet = d.findViewById(R.id.design_bottom_sheet);
                        BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
                        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                    }
                },0);
            }
        });
    

    This code works fine at Fragment's onCreateView method (thanks for ADM)

  9. Solution 4
  10. Some answers seem to do the trick better than others but will need modification when using the new material design components instead of the older support libraries while also using kotlin

    Hope this will help someone.

    BottomSheetDialog(this, R.style.DialogStyle).apply {
        setContentView(layoutInflater.inflate(R.layout.bottom_sheet, null))
        window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
        findViewById<EditText>(R.id.time_et)?.requestFocus()
    
        show()
    }
    

    layout/bottom_sheet.xml

    <?xml version="1.0" encoding="utf-8"?>
    <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#ffffff"
            android:padding="16dp">
    
        <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">
    
    
            <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">
    
                <View
                        android:layout_width="0dp"
                        android:layout_height="match_parent"
                        android:layout_weight="1" />
    
                <LinearLayout
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="5"
                        android:orientation="vertical">
    
                    <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:text="Time"
                            android:textColor="#000000"
                            android:textSize="24sp"
                            android:textStyle="bold" />
    
                    <LinearLayout
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_marginTop="8dp"
                            android:orientation="horizontal">
    
                        <EditText
                                android:id="@+id/time_et"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:inputType="numberSigned"
                                android:minWidth="50dp"
                                android:text="15" />
    
                        <TextView
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:layout_marginLeft="8dp"
                                android:text="min" />
    
                    </LinearLayout>
    
    
                </LinearLayout>
    
            </LinearLayout>
    
    
            <Button
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="16dp"
                    android:background="#000"
                    android:text="Save"
                    android:textColor="#fff" />
    
        </LinearLayout>
    
    </ScrollView>
    

    styes.xml (Split for v-21 for using statusBarColor)

        <style name="DialogStyle" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
            <item name="android:windowIsFloating">false</item>
            <item name="android:statusBarColor">@android:color/transparent</item>
            <item name="android:windowSoftInputMode">adjustResize</item>
        </style>
    
Salvatrix Ngải 2022-08-11
build android apps from nodejs

build android apps from nodejs

If You Can Build A Website, You Can Build An Android App!
Android.js simple takes your node.js website and puts it into a WebView.

Yeah, i know that's a lot of disadvantages there but it also provides different APIs for you to interact with.

an android.js application isn't only a WebView like a front end of a site, it can also interact with the backend and interact with files and much more!

installation

npm install androidjs
Enter fullscreen mode Exit fullscreen mode

Install Android JS project generator and builder

npm install -g androidjs-builder
Enter fullscreen mode Exit fullscreen mode

initialize

mkdir AndroidApp
cd AndroidApp
androidjs g
npm install
Enter fullscreen mode Exit fullscreen mode

it will generate a sample project inside AndroidApp directory.

Which will look like:

AndroidApp
    |__ assets
    |       |__ ipc, css, js
    |
    |__ views
    |       |__ index.html
    |
    |__ main.js
    |__ package.json
Enter fullscreen mode Exit fullscreen mode
  • main.js is the main file or we can say it is back process of your app which execute all the code written in node, so you have to write all the node js code inside main.js
  • index.html is the first view which is render by app initially
  • package.json to keep track of all your node packages
  • assets to store all assets of your app

time to build

cd AndroidApp
androidjs b
Enter fullscreen mode Exit fullscreen mode

it will generate apk file inside dist folder

if this build command fails or generated any error, try to build with force command

androidjs b -f
Enter fullscreen mode Exit fullscreen mode

Why not to use it

Android.js isn't better than react-native
But, at least you can (somewhat) throw your existing code in it and generate an API to work on a device just like android application.
React native stays the best way to make Android applications with react (JavaScript).

other resources

docs - documentation for android.js

Sample apps - some sample apps to go with..

conclusion

Android.js is an amazing framework if you don't know react

But if you know react, react native comes in handy at the first place.

originally published here at my blog

Make sure you're subscribed to the high dose javascript newsletter

of course I can't make you, but it take me a considerable amount of time to write these..

tweet this if you like it.
thanks!

Jožica Lidiya 2022-08-11
chain validation failed SSLHandshakeException 5 Solution

chain validation failed SSLHandshakeException 5 Solution

  1. FAILURE
  2. Sometime when you try to do a HTTPS POST request to your server. you get SSLHandshakeException - Chain chain validation failed, all the time. but when using POSTMAN you get a response from the server. What can be causing this error when I try to send the request from the application?

  3. Most common Solution
  4. In many case it was the wrong date on phone.

    Fixing date resolved an issue

  5. Solution 2
  6. if the abouve Solution dont work Try this one

    The problem may be that the certificate was expired.

  7. Solution 3
  8. If you're using an emulated device it may solve the problem if you just 'Cold Boot' it.

    Sometimes the date on those things can get stuck if you let them run for some time, which results in this expired-certificate-problem.

  9. Solution 4
  10. In my case, I fetch this issue on Android Emulator. When I clear emulator cache has resolved the issue.

    enter image description here

Pétur Gulnara 2022-08-09
Automate taking screenshots of Android app with Jetpack Compose

Automate taking screenshots of Android app with Jetpack Compose

In the article I'll show how to automate taking screenshots of the Android application written in Jetpack Compose.

1. Create test

Start with setting up instrumented test. This test will not check anything, it will only perform actions such clicking button and take screenshots of the application.

First, set up testing in app/build.gradle:

android {
    // other properties
    defaultConfig {
           // other properties
           testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // Add this line
    }
}
// ...

dependencies {
    // other dependencies
    androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" // Add this line
}
Enter fullscreen mode Exit fullscreen mode

Now, let's suppose this is the Activity we want to take screenshots of:

package com.example

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Scaffold {
                Column(
                    verticalArrangement = Arrangement.spacedBy(16.dp),
                    modifier = Modifier.padding(16.dp),
                ) {
                    var greetingVisible by remember { mutableStateOf(false) }
                    if (greetingVisible) {
                        Text("Hello!")
                    }
                    Button(onClick = { greetingVisible = true }) {
                        Text("Show greeting")
                    }
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Create the test in androidTest directory:

package com.example

import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class ScreenshotTest {

    @get:Rule
    val rule = createAndroidComposeRule<MainActivity>()

    @Test
    fun makeScreenshot() {
        // TODO: Take screenshot before clicking button
        rule
            .onNodeWithText("Show greeting")
            .performClick()
        // TODO: Take screenshot after clicking button
    }
}
Enter fullscreen mode Exit fullscreen mode

2. Take the screenshot

In order to take screenshot and save it as an image, use the following functions:

private fun ComposeContentTestRule.takeScreenshot(file: String) {
    onRoot()
        .captureToImage()
        .asAndroidBitmap()
        .save(file)
}

private fun Bitmap.save(file: String) {
    val path = InstrumentationRegistry.getInstrumentation().targetContext.filesDir.canonicalPath
    FileOutputStream("$path/$file").use { out ->
        compress(Bitmap.CompressFormat.PNG, 100, out)
    }
}
Enter fullscreen mode Exit fullscreen mode

Here is the full test which takes screenshots of the app:

package com.example

import android.graphics.Bitmap
import androidx.compose.ui.graphics.asAndroidBitmap
import androidx.compose.ui.test.captureToImage
import androidx.compose.ui.test.junit4.ComposeContentTestRule
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import java.io.FileOutputStream

@RunWith(AndroidJUnit4::class)
class ScreenshotTest {

    @get:Rule
    val rule = createAndroidComposeRule<MainActivity>()

    @Test
    fun makeScreenshot() {
        rule.takeScreenshot("before-click.png")
        rule
            .onNodeWithText("Show greeting")
            .performClick()
        rule.takeScreenshot("after-click.png")
    }
}


private fun ComposeContentTestRule.takeScreenshot(file: String) {
    onRoot()
        .captureToImage()
        .asAndroidBitmap()
        .save(file)
}

private fun Bitmap.save(file: String) {
    val path = InstrumentationRegistry.getInstrumentation().targetContext.filesDir.canonicalPath
    FileOutputStream("$path/$file").use { out ->
        compress(Bitmap.CompressFormat.PNG, 100, out)
    }
}
Enter fullscreen mode Exit fullscreen mode

3. Save screenshots on the host PC

All screenshots taken by the code are stored in the emulator or phone.

To fetch them manually you can use Device File Explorer, which is build in Android Studio. Screenshots can be found in the following directory:
/data/data/$applicationId/files/

This process can be automated by ADB command:

adb root
adb pull /data/data/com.example/files/ screenshots
Enter fullscreen mode Exit fullscreen mode

Extra information

Turn off animations

In some cases turning off animations is needed to run tests. To do it, use these commands:

adb shell settings put global window_animation_scale 0
adb shell settings put global animator_duration_scale 0
adb shell settings put global transition_animation_scale 0
Enter fullscreen mode Exit fullscreen mode

Some users have reported that their devices need to be reboot to apply these settings. If that's your case, you can use the following command:

adb shell "su 0 am start -a android.intent.action.REBOOT"
Enter fullscreen mode Exit fullscreen mode

Turn off keyboard

Soft keyboard can affect screenshots by cropping them. To disable it use the following commands:

# Show all keyboards (-a for all, -s for short summary).
adb shell ime list -s -a

# Disable keyboards:
adb shell ime disable <<keyboard id>>
# Example: adb shell ime disable com.android.inputmethod.latin
Enter fullscreen mode Exit fullscreen mode
Steve 2022-08-11
how to solve Could not find or load main class org.gradle.wrapper.GradleWrapperMain

how to solve Could not find or load main class org.gradle.wrapper.GradleWrapperMain

  1. FAILURE
  2. execution of the command ./gradlew leads to the following output:
    usr$ ./gradlew tasks
    Error: Could not find or load main class org.gradle.wrapper.GradleWrapperMain
    

  3. What is gradle wrapper
  4. gradlew is the gradle wrapper executable - batch script on windows and shell script elsewhere. The wrapper script when invoked, downloads the defined gradle version and executes it. By distributing the wrapper with your project, anyone can work with it without needing to install Gradle beforehand. Even better, users of the build are guaranteed to use the version of Gradle that the build was designed to work with.

  5. Restoring gradle wrapper
  6. It used to be that you needed to add a wrapper task to your build.gradle to restore gradle wrapper and all its dependencies. For instance:

    task wrapper(type: Wrapper) {
        gradleVersion = '4.1'
    }
    

    Newer versions of gradle do not require this. It is now a built-in task. Just run:

    gradle wrapper
    

    You can also supply additional flags to specify versions etc

    gradle wrapper --gradle-version 6.2 --distribution-type all
    

    When you run this task, a gradle wrapper script, and the required jar files are added to your source folders. Properties are stored in gradle/wrapper/gradle-wrapper.properties

    (You may need to install gradle locally to run this. brew install gradle on mac for instance. See more detailed instructions here)

  7. Why was it missing in the first place?
  8. OP seems to have deleted something that gradle wrapper depends on.

    But a common reason is that a .gitignore entry prevents wrapper jars from being checked into git. Note that the .gitignore in effect may be in the source folder, or a global one in your user home folder or git global configuration. It is common to have a *.jar entry in .gitignore.

    You can add an exception for gradlew's jar files in .gitignore

    *.jar
    !gradle/wrapper/gradle-wrapper.jar
    

    or force add the wrapper jar into git

    git add -f gradle/wrapper/gradle-wrapper.jar
    

    --
    Ref: Gradle Wrapper

  9. Other Solution
  10. What worked for me is to first run:

     gradle wrapper
    

    After successful build I was able to run

    ./gradlew assembleRelease
    

    Note: To be able run gradle wrapper first run brew install gradle. If installation successful run gradle wrapper from project root.

    Source and thanks: http://gradle.org/docs/current/userguide/gradle_wrapper.html and https://stackoverflow.com/users/745574/rage

    In my case it was a global .gitignore, as explained in @HankCa's answer.

    Instead of forcefully adding the jar, which you'll need to remember to do in each Gradle project, I added an override to re-include the wrapper jar in my global .gitignore:

    *.jar
    !gradle/wrapper/gradle-wrapper.jar
    

    This is useful to me as I have many projects that use Gradle; Git will now remind me to include the wrapper jar.

    This override will work so long as no directories above gradle-wrapper.jar (such as gradle and wrapper) are ignored -- git will not descend in to ignored directories for performance reasons.

Laxmi Queenie 2022-08-11
How to solve Error building Android library

How to solve Error building Android library

  1. FAILURE
  2. We are now seeing this error when building one of our library modules:
    $ ./gradlew library_module:assemble
    
    Execution failed for task ':library_module:bundleDebugAar'.
    > Direct local .aar file dependencies are not supported when building an AAR. 
    The resulting AAR would be broken because the classes and Android resources from any local .aar 
    file dependencies would not be packaged in the resulting AAR. Previous versions of the Android 
    Gradle Plugin produce broken AARs in this case too (despite not throwing this error). The 
    following direct local .aar file dependencies of the :library_module project caused this error: 
    ______.aar
    

  3. Most common Solution
  4. I recently encountered the same issue, the fix was to remove the library from libs/ and import it using File -> New -> New Module -> Import .JAR/.AAR Package, then referencing it in the library module build.gradle file:

    dependencies {
      implementation project(":imported_aar_module")
    }
    

    If you are on a newer Android Studio version (4.0.0+), this option is not available. Instead you have to do it manually.

    1. Create a new directory and put the following content into the build.gradle file withing the new directory:
    configurations.maybeCreate("default")
    artifacts.add("default", file('[nameOfTheAar].aar'))
    
    1. Place the aar into this new directoy. Next to the build.gradle file.
    2. Add the new created Gradle project to the settings.gradle file:
    include(":pathToTheCreatedDirectory")
    
    1. Include the project in your library where you want to use the aar:
    implementation project(":pathToTheCreatedDirectory", configuration = "default")
    

  5. Solution 2
  6. When building an Android library that depends on other Android libraries (i.e., aar files), you will get the following error message if you include the aar files as dependencies in the project:

    Direct local .aar file dependencies are not supported when building an AAR. The resulting AAR would be broken because the classes and Android resources from any local .aar file dependencies would not be packaged in the resulting AAR. Previous versions of the Android Gradle Plugin produce broken AARs in this case too (despite not throwing this error).

    As the above message states, when you build an Android library project, any aar it depends on is not packaged. If you built this way prior to AGP (Android Gradle Plugin) 4, you probably noticed that you had to include the aar dependencies on the project consuming your library.

    You can compile your Android library project by specifying that the aar dependencies are compileOnly. See this for more info on when to use compileOnly.

    So just add the following to your app build.gradle file:

    compileOnly files('libs/some-library.aar')
    

    Note that if you do this you will have to include the aar dependencies on the application project that consumes your library.

    Alternatively, you can create a module that imports your aar dependency as @Sandi mentioned in the answer above.

    Another way is to publish your aar dependencies to a maven repository and then add them to your library project like this:

    implementation 'mylibrarygroup:mylibraryartifact:version-x.y.z@aar'
    

  7. Solution 3
  8. I want to call out @StefMa's comment on this question which was incredible simple and solved this issue for me, but it's buried among many other comments on this thread and is easily missed.

    The 'correct' answer on this thread no longer works because it's not possible to import AARs in Android Studio anymore as referred to in that answer. But, the solution referred to in StefMa's comment linking to this GitHub post does, and it works perfectly.

    Long story short - put your AAR into a separate module.

    There's no need to muck around with creating lib directories, just follow these directions -

    1. Create a new directory in your project's root directory. The image below shows two of them - spotify-app-remote and spotify-auth, but one is sufficient. Within that, put your AAR in, and create a new build.gradle file.

      Folder structure

    2. Within the build.gradle file, add the following, replacing the aar filename with the name of your AAR file -

      configurations.maybeCreate("default")
      artifacts.add("default", file('spotify-app-remote-release-0.7.1.aar'))
      
    3. Add this to your settings.gradle file, substituting the name of the directory you created

      include ':spotify-app-remote'
      
    4. Include your new module in the module you wish to use the AAR. eg, if you want to use it within your app module, open app's build.gradle and add

      api project(':spotify-app-remote')
      

      within your dependencies { } block, obviously again substituting spotify-app-remote with whatever the name of your module is.

  9. Solution 4
  10. In my experience, when Gradle Plugin version is 4.2.2+ and Gradle version is 7.1+, as in @Luis's answer 'compileOnly' works.

    compileOnly files('libs/your_library_name.aar')
    

    It didn't work when the Gradle versions were lower.

Filibert Nosizwe 2022-08-11