Calling Native Method Twice of Third Party Library in an Activity Causes the Android Application to Close Down

Call native library method in independent native library

Its kind of unclear what you want the function to do, but If I understand, you want your Java-callable library to be like the following (assuming "C" not C++)

#include "zoom_Main_VideoPlayer.h"
#include <dlfcn.h>
void *handle;
typedef void (*func)(); // define function prototype
func myFunctionName; // some name for the function
JNIEXPORT void JNICALL Java_zoom_render_RenderView_naClose(JNIEnv *pEnv, jobject pObj) {

handle = dlopen("path to nativelibrary1.so", RTLD_LAZY);
myFunctionName = (func)dlsym(handle, "Close");
myFunctionName(); // passing parameters if needed in the call
dlclose(handle);
return;
}

And your other library will be:

// native method in nativelibrary1
void Close() {
if (!is) {
do_exit(is);
}
else {
do_exit(NULL);
}
LOGI(0, "Clean-up done");
}

Because your Close() does not have any arguments. You may also make your Java method static so that the spurious pObj isn't added to the native method signature.

If you described what the methods should do, I could make a better suggestion.

Load native library twice

OK, I found found a way to do it :) Maybe it is not a beautiful one, but it works fine:

  1. Create a service:

    import android.app.Service;
    import android.content.Intent;
    import android.os.AsyncTask;
    import android.os.IBinder;

    public class rtmpdumpService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
    return null;
    }

    @Override
    public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);
    config = this;
    String extras = "";
    if(intent != null){

    //Get needed information
    extras = intent.getExtras().getString("rtmp");
    }
    else {
    this.stopSelf();
    }
    doWork(extras);
    }

    @Override
    public void onDestroy() {
    super.onDestroy();
    }

    public void doWork(String rtmp){
    //Do work here: for example rtmpdump
    Rtmpdump dump = new Rtmpdump();
    dump.parseString(params[0]);
    System.exit(0);
    this.stopSelf();
    }
    }
  2. Register in AndroidManifest as service with these attributes

    android:name=".rtmpdumpService"
    android:exported="false"
    android:process=":rtmp"
  3. Start service:

    Intent rtmpdumpIntent = new Intent(getApplicationContext(), rtmpdumpService.class);
    eSendIntent.putExtra("rtmp", "RTMP CODE");
    startService(rtmpdumpIntent);

Sometimes you have to wait until it finishes:

After the Service is started (startService(rtmpdumpIntent):

do {
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
//Log
}
} while( isServiceRunning(rtmpdumpService.class) == true);

isServiceRunning function:

    private boolean isServiceRunning(Class cl) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (cl.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}

Remove the instance of native library from app using dlclose(Android NDK)

try moving the position of the 'ReleaseString...'

it should be after the 'dlopen'

it should be before the call into the other shared lib...

(*env)->GetStringUTFChars
dlopen
(*env)->ReleaseStringUTFChars
make the main call
dlclose

Loading JNI library in another JNI library crashes

After using dlerror() to diagnose the problem, I actually found that dlopen was failing.
Turns the path was wrong. It should be:

handle = dlopen("/data/data/my.package/lib/myLibrary.so", RTLD_LAZY);

Android Studio error: Manifest merger failed: Apps targeting Android 12

You need to specify android:exported="false" or android:exported="true"

Manifest:

<activity
android:name=".MainActivity"
android:exported="true"
android:theme="@style/Theme.MyApplication.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

as mentioned in the document:

If your app targets Android 12 and contains activities, services, or
broadcast receivers that use intent filters, you must explicitly
declare the android: exported attribute for these app components.

Warning: If an activity, service, or broadcast receiver uses intent
filters and doesn't have an explicitly-declared value for
android:exported, your app can't be installed on a device that runs
Android 12.

Also check when to use true/false for the 'android:exported' value.



Related Topics



Leave a reply



Submit