My app has an embedded APK, I need to register a BroadcastReceiver
in the inner APK from my main APK.
The inner APK is not to be installed on the system; I must load it dynamically. So, I'm using reflection to call a method in the inner APK which has code to register the BroadcastReceiver
. This receiver of inner APK should invoke for related broadcast.
I'm getting an error while trying to register the BroadcastReceiver
. Is it even possible for a BroadcastReceiver
to be registered in this way, and be fully functional? Exception and code are given below
Error related log:
08-24 08:31:26.915: D/MainApp(1957): invoke method
08-24 08:31:26.955: D/InnerApp(1957): Register receiver
08-24 08:31:26.955: W/System.err(1957): java.lang.reflect.InvocationTargetException
08-24 08:31:26.965: W/System.err(1957): at java.lang.reflect.Method.invokeNative(Native Method)
08-24 08:31:26.965: W/System.err(1957): at java.lang.reflect.Method.invoke(Method.java:515)
08-24 08:31:26.965: W/System.err(1957): at com.example.ea_mainapp.MainApp.invokeService(MainApp.java:105)
08-24 08:31:26.965: W/System.err(1957): at com.example.ea_mainapp.MainApp.onCreate(MainApp.java:40)
08-24 08:31:26.965: W/System.err(1957): at android.app.Activity.performCreate(Activity.java:5231)
08-24 08:31:26.975: W/System.err(1957): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
08-24 08:31:26.975: W/System.err(1957): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
08-24 08:31:26.975: W/System.err(1957): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
08-24 08:31:26.975: W/System.err(1957): at android.app.ActivityThread.access$800(ActivityThread.java:135)
08-24 08:31:26.975: W/System.err(1957): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
08-24 08:31:26.975: W/System.err(1957): at android.os.Handler.dispatchMessage(Handler.java:102)
08-24 08:31:26.975: W/System.err(1957): at android.os.Looper.loop(Looper.java:136)
08-24 08:31:26.975: W/System.err(1957): at android.app.ActivityThread.main(ActivityThread.java:5017)
08-24 08:31:26.975: W/System.err(1957): at java.lang.reflect.Method.invokeNative(Native Method)
08-24 08:31:26.975: W/System.err(1957): at java.lang.reflect.Method.invoke(Method.java:515)
08-24 08:31:26.975: W/System.err(1957): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
08-24 08:31:26.975: W/System.err(1957): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
08-24 08:31:26.975: W/System.err(1957): at dalvik.system.NativeStart.main(Native Method)
08-24 08:31:26.985: W/System.err(1957): Caused by: java.lang.NullPointerException
08-24 08:31:26.985: W/System.err(1957): at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:467)
08-24 08:31:26.985: W/System.err(1957): at com.example.ea_innerapp.InnerApp.register(InnerApp.java:50)
08-24 08:31:26.985: W/System.err(1957): ... 18 more`
Related code from Main app:
// invoke method
Log.d(TAG,"invoke method");
final String apkFile =TARGET_BASE_PATH+"EA_innerApp.apk";
String className = "com.example.ea_innerapp.InnerApp";
String methodToInvoke = "register";
final File optimizedDexOutputPath = getDir("outdex", 0);
DexClassLoader dLoader = new DexClassLoader(apkFile,optimizedDexOutputPath.getAbsolutePath(),
null,ClassLoader.getSystemClassLoader().getParent());
try {
Class<?> loadedClass = dLoader.loadClass(className);
Object obj = (Object)loadedClass.newInstance();
@SuppressWarnings("rawtypes")
Class noparams[] = {};
Method m = loadedClass.getMethod(methodToInvoke, noparams);
Object oNoparams[] = {};
m.invoke(obj, oNoparams);
} catch (ClassNotFoundException e) {....
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Code of invoked method, "com.example.ea_innerapp.InnerApp.register":
Log.d(TAG, "Register receiver");
IntentFilter filter=new IntentFilter();
filter.addAction("com.example.ea_mainapp.i");
registerReceiver(obj_InnerReceiver,filter);
I have fixed the issue.
Identification of issue:
Main section of exception staketrace was
08-24 08:31:26.985: W/System.err(1957): Caused by: java.lang.NullPointerException
08-24 08:31:26.985: W/System.err(1957): at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:467)
08-24 08:31:26.985: W/System.err(1957): at com.example.ea_innerapp.InnerApp.register(InnerApp.java:50)
I looked at code of "android.content.ContextWrapper.registerReceive" to find the main cause. Related code of class ContextWrapper is given below
464 @Override
465 public Intent registerReceiver(
466 BroadcastReceiver receiver, IntentFilter filter) {
467 return mBase.registerReceiver(receiver, filter);
468 }
Ref.: http://grepcode.com/file/repo1.maven.org/maven2/org.robolectric/android-all/4.4_r1-robolectric-1/android/content/ContextWrapper.java#ContextWrapper.0mBase
Error was at line 467, which is "return mBase.registerReceiver(receiver, filter);"
. Here, mBase is object of class "android.content.Context".
Value of Context was null in class "com.example.ea_innerapp.InnerApp", since it is class of embedded apk. This is why I was getting exception.
Solution:
I needed to provide a Context value. So, I passed Context of main apk as argument to "com.example.ea_innerapp.InnerApp.register".
"com.example.ea_innerapp.InnerApp.register" was calling "android.content.ContextWrapper.registerReceive", which does not receive Context as parameter. So, I directly called "android.content.Context.registerReceiver", using the Context provided by main apk. Modified "com.example.ea_innerapp.InnerApp.register" is
public void register(Context param_ctx){
......
param_ctx.registerReceiver(obj_InnerReceiver,filter);
}
Note that you'll have to save the value of param_ctx and use it while un registering receiver as well, otherwise you'll get error. To unregister receiver you'll call
ctx.unregisterReceiver(obj_InnerReceiver); // ctx is the value that was passed to "com.example.ea_innerapp.InnerApp.register"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With