あるAPKで動的登録BroadcastReceiverが使用する、LauncherでこのAPKを動的にロードするjavaが現れる.lang.SecurityException異常の解決方法
あるAPKでは、次の方法でBroadcastReceiverが動的に登録されています.コードリファレンスは次のとおりです.
LauncherはこのAPKを動的にロードする(APKを動的にロードする目的と実現構想、私のこの文章を参照:Launcherの中で他のAPKの中でActivityの問題解決構想を動的にロードする
),
次のような異常が発生しました.
検索してみると、多くの人がこのような問題に遭遇したことがあるが、解決策を提案していないので、自分で解決するしかないようだ.
ダイナミックロードはできませんAndroidManifestですxmlはBroadcastReceiverを静的にロードしてみてもいいですか?
他のBroadcastRecevierの場合はOKであることが確認されましたがandroid.content.Intent.ACTION_TIME_TICKというダメなのは、Androidのコメントで明確に説明されています.
本当に解決策がないのだろうか.
手元にAndroidソースがあり、「Given caller package」と「is not running in process Process Record」の2つのキーワードの全文検索に基づいて、
この異常なコードがどこで作られたのか見てみたいです.cpp,*.c*,*.JAvaで検索しても見つからないので、まずこの方法を放棄しましょう.
後でこの異常を分析します
サードパーティAPKに登録されているBroadcastReceiverです.このAPKはAndroidManifestにあります.xmlで宣言されたパケット名はちょうど「com.zhao 3546.time」であり、最終的にはLauncherと同じプロセスで実行され、このプロセスに対応するパケット名は「com.zhao 3546.launcher」であり、Launcherが先に実行され、APKが動的にロードされるためである.
それは私がBroadcastReceiver対応のパッケージ名を登録すれば「com.zhao 3546.launcher」であれば、問題を解決できるのではないでしょうか.
Launcherでは、LauncherとサードパーティAPKのAndroidManifestを動的にロードする問題の解決策について説明しています.xmlでandroid:sharedUserIdプロパティ宣言が一致しました.
だからLauncherとサードパーティのAPKは実際に同じプロセスで実行されています.それはLauncherのcontextオブジェクトをこのAPKに渡すだけで、このAPKはLauncherのcontextを使ってBroadcastReceiverを登録すれば、問題を解決することができますか?
サードパーティAPKのcom.zhao3546.timeパッケージには、次のクラスが追加され、public static void setContext(Context context)という静的メソッドが実装されています.
Launcherコードでは、launcherのcontextオブジェクトを反射機構により動的にcomに伝達する.zhao3546.time.ContextHolderでは、
以前にBroadcastReceiverを登録していた場所を変更し、ContextHolder()でBroadcastReceiverを登録し、APKを再配置して検証し、問題を解決します.
解決できないように見える問題は、実は別の方法を試してみる必要がある場合があり、予想外の効果を得る可能性があります.
@Override
protected void onAttachedToWindow()
{
super.onAttachedToWindow();
/* monitor time ticks, time changed, timezone */
if (mIntentReceiver == null)
{
mIntentReceiver = new TimeChangedReceiver(this);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
getContext().registerReceiver(mIntentReceiver, filter);
LauncherはこのAPKを動的にロードする(APKを動的にロードする目的と実現構想、私のこの文章を参照:Launcherの中で他のAPKの中でActivityの問題解決構想を動的にロードする
),
次のような異常が発生しました.
09-05 19:05:55.033: E/AndroidRuntime(28637): java.lang.SecurityException: Given caller package com.zhao3546.time is not running in process ProcessRecord{41e74e50 28637:com.zhao3546.launcher/u0a10142}
検索してみると、多くの人がこのような問題に遭遇したことがあるが、解決策を提案していないので、自分で解決するしかないようだ.
ダイナミックロードはできませんAndroidManifestですxmlはBroadcastReceiverを静的にロードしてみてもいいですか?
他のBroadcastRecevierの場合はOKであることが確認されましたがandroid.content.Intent.ACTION_TIME_TICKというダメなのは、Androidのコメントで明確に説明されています.
String android.content.Intent.ACTION_TIME_TICK = "android.intent.action.TIME_TICK"
Broadcast Action: The current time has changed. Sent every minute. You can not receive this through components declared in manifests, only by exlicitly registering for it with Context.registerReceiver().
This is a protected intent that can only be sent by the system.
本当に解決策がないのだろうか.
手元にAndroidソースがあり、「Given caller package」と「is not running in process Process Record」の2つのキーワードの全文検索に基づいて、
この異常なコードがどこで作られたのか見てみたいです.cpp,*.c*,*.JAvaで検索しても見つからないので、まずこの方法を放棄しましょう.
後でこの異常を分析します
09-05 19:05:55.033: E/AndroidRuntime(28637): java.lang.SecurityException: Given caller package com.zhao3546.time is not running in process ProcessRecord{41e74e50 28637:com.zhao3546.launcher/u0a10142}
サードパーティAPKに登録されているBroadcastReceiverです.このAPKはAndroidManifestにあります.xmlで宣言されたパケット名はちょうど「com.zhao 3546.time」であり、最終的にはLauncherと同じプロセスで実行され、このプロセスに対応するパケット名は「com.zhao 3546.launcher」であり、Launcherが先に実行され、APKが動的にロードされるためである.
それは私がBroadcastReceiver対応のパッケージ名を登録すれば「com.zhao 3546.launcher」であれば、問題を解決できるのではないでしょうか.
Launcherでは、LauncherとサードパーティAPKのAndroidManifestを動的にロードする問題の解決策について説明しています.xmlでandroid:sharedUserIdプロパティ宣言が一致しました.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zhao3546.time"
android:sharedUserId="zhao3546.launcher"
だからLauncherとサードパーティのAPKは実際に同じプロセスで実行されています.それはLauncherのcontextオブジェクトをこのAPKに渡すだけで、このAPKはLauncherのcontextを使ってBroadcastReceiverを登録すれば、問題を解決することができますか?
サードパーティAPKのcom.zhao3546.timeパッケージには、次のクラスが追加され、public static void setContext(Context context)という静的メソッドが実装されています.
package com.zhao3546.time;
import android.content.Context;
public class ContextHolder
{
private static Context context = null;
public static void setContext(Context context)
{
System.out.println("com.zhao3546.time.ContextHolder setContext");
ContextHolder.context = context;
}
public static Context getContext()
{
System.out.println("com.zhao3546.time.ContextHolder getContext() context="
+ context);
return context;
}
}
Launcherコードでは、launcherのcontextオブジェクトを反射機構により動的にcomに伝達する.zhao3546.time.ContextHolderでは、
private void setContext2Plugin(ClassLoader pluginClassLoader,
String pluginPackageName, Context launcherContext)
{
String className = pluginPackageName + ".ContextHolder";
try
{
Method m = pluginClassLoader.loadClass(className)
.getMethod("setContext", Context.class);
m.invoke(null, launcherContext);
}
catch (Exception e)
{
Log.w(TAG, "Fail to loadClass " + className + ", skip it", e);
}
}
以前にBroadcastReceiverを登録していた場所を変更し、ContextHolder()でBroadcastReceiverを登録し、APKを再配置して検証し、問題を解決します.
解決できないように見える問題は、実は別の方法を試してみる必要がある場合があり、予想外の効果を得る可能性があります.