LoginSignup
1

More than 5 years have passed since last update.

Android: PackageManager: apkの壁を超えてclassの存在確認をする

Posted at

初稿2010/9

はじめに

apk内に閉じてclassの存在を確認するならClass.forName()でOKですが、他のapk内にあるclassの確認はできません
PackageManagerのgetActivityInfoを使います

  • apk内ならClass.forNameしてClassNotFoundExceptionを拾う
try {
 Class.forName("jp.co.na.Entry");
} catch (ClassNotFoundException e) {
 Log.d(TAG,  "class Not exists.");
}
  • 別のapkの場合はPackageManagerのgetActivityInfoしてNameNotFoundExceptionを拾う
PackageManager mManager = getPackageManager();
try {
  mManager.getActivityInfo(new ComponentName("jp.co.na", "jp.co.na.Entry"), 0);
} catch (NameNotFoundException e) {
  Log.d(TAG, "class Not exists.");
}

これを使って、Entryという名前のActivityが複数のapkに存在して、順番に存在確認をして一番最初に見つかったpackageに画面遷移するコードは以下のような感じ


//apkを跨ってclassを探すときは、PackageManagerさんに聞く
package jp.co.na.main;

public class mainAct extends Activity {
  static final String TAG = "mainAct";

  PackageManager mManager = null;
  String next_page = ".Entry";  // 遷移先Activityのクラス名

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
      Button b = (Button)findViewById(R.id.Button01);
      b.setOnClickListener(mButtonListener);

      mManager = getPackageManager();
  }

 private View.OnClickListener mButtonListener =
 new View.OnClickListener() {
    public void onClick(View v) {

    // 遷移先Activityがどの(apkを跨った)パッケージに含まれるか探す
    try {
      // apk1をチェック
      String package_name = "jp.co.na.a.b.c";
      String class_name = package_name + next_page;
      mManager.getActivityInfo(new ComponentName(package_name, class_name), 0);
    } catch (NameNotFoundException e) {
      Log.d(TAG, class_name + " Not exists.");
      try {
        // apk2をチェック
        String package_name = "jp.co.photo";
        String class_name = package_name + next_page;
        mManager.getActivityInfo(new ComponentName(package_name, class_name), 0);
        } catch (NameNotFoundException ee) {
          Log.d(TAG, class_name + " Not exists.");
          try {
            // apk3をチェック
            String package_name = "jp.co.zaku.model";
            String class_name = package_name + next_page;
            mManager.getActivityInfo(new ComponentName(package_name, class_name), 0);
          } catch (NameNotFoundException eee) {
            Log.d(TAG, class_name + " Not exists.");
            try {
              // 共通apkをチェック
              String package_name = "com.na.common";
              String class_name = package_name + next_page;
              mManager.getActivityInfo(new ComponentName(package_name, class_name), 0);
            } catch (NameNotFoundException eeee) {
              // どこにも無かったのでエラー
              Log.d(TAG, class_name + " Not exists.");
              eeee.printStackTrace();
            }
          }
        }
      }
      // 遷移先のActivityを指定して遷移
      Intent intent = new Intent();
      intent.setClassName(package_name, class_name);
      startActivity(intent);
    }
  };
}

実行ログ:どのpackageにもclassが無かった場合

D/a01     ( 1391): jp.co.na.a.b.c Not exists.       <--apk1をチェックして、無かった
D/a01     ( 1391): jp.co.photo Not exists.          <--apk2をチェックして、無かった
D/a01     ( 1391): jp.co.zaku.model Not exists.     <--apk3をチェックして、無かった
D/a01     ( 1391): com.na.common Not exists.        <--共通apkをチェックして、無かった
W/System.err( 1391): android.content.pm.PackageManager$NameNotFoundException: ComponentInfo{com.na.common/com.na.common.Entry}
W/System.err( 1391):    at android.app.ApplicationContext$ApplicationPackageManager.getActivityInfo(ApplicationContext.java:1619)
W/System.err( 1391):    at jp.co.na.main.mainAct$1.onClick(mainAct.java:54)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1