2014-11-03

特殊キー (ホーム、最近使ったアプリ、通知バーを開く) の実装 (オマケに "戻る" も。)

Android アプリ開発をしていて、特殊キーを実装したくなったので調べて、まとめてみた。

■ ホームボタン (Home Button)

最初の画面に戻れるアレ。
/**
 * publishHomeButtonEvent --- ホームを開く
 */
private void publishHomeButtonEvent() {
  Intent intent = new Intent(Intent.ACTION_MAIN);
  intent.addCategory(Intent.CATEGORY_HOME);
  intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
  startActivity(intent);
}


■ 最近使ったアプリ (Recent Apps)

起動中のアプリ一覧が出てくるアレ。Android 4.0 以降対応。
/**
 * publishOpenRecentAppsEvent --- 「最近使ったアプリ」を開く
 *  - 参考: http://stackoverflow.com/questions/14267482/android-programmatically-open-recent-apps-dialog
 */
private void publishOpenRecentAppsEvent() {
  try {
    Class<?> serviceManagerClass = Class.forName("android.os.ServiceManager");
    Method getService = serviceManagerClass.getMethod("getService", String.class);
    IBinder retbinder = (IBinder) getService.invoke(serviceManagerClass, "statusbar");
    Class<?> statusBarClass = Class.forName(retbinder.getInterfaceDescriptor());
    Object statusBarObject = statusBarClass.getClasses()[0].getMethod("asInterface", IBinder.class).invoke(null, new Object[] { retbinder });
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
      Method preloadRecentApps = statusBarClass.getMethod("preloadRecentApps");  // 初期化 (しないとアニメーションがおかしくなる)
      preloadRecentApps.setAccessible(true);
      preloadRecentApps.invoke(statusBarObject);
    }
    Method toggleRecentApps = statusBarClass.getMethod("toggleRecentApps");
    toggleRecentApps.setAccessible(true);
    toggleRecentApps.invoke(statusBarObject);
  } catch (Exception e) {
    e.printStackTrace();
  }
}


■ 通知領域を開く (Notifications)

画面の上端を下向きにスライドすると出てくるアレ。
/**
 * publishExpandNotificationsEvent --- 通知領域を開く
 *  - AndroidManifest.xml に要追加: <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
 */
private void publishExpandNotificationsEvent() {
  try {
    Object sbservice = getSystemService("statusbar");
    Class<?> statusbarManager = Class.forName("android.app.StatusBarManager");
    Method expand;
    if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {  // API Level 16 (Android 4.1, 4.1.1) or lower
      expand = statusbarManager.getMethod("expand");
    } else {  // API Level 17 (Android 4.2, 4.2.2) or higher
      expand = statusbarManager.getMethod("expandNotificationsPanel");
    }
    expand.invoke(sbservice);
  } catch (Exception e) {
    e.printStackTrace();
  }
}

使う機会があるのか謎ですが、閉じる場合。(未検証)
/**
 * publishCollapseNotificationsEvent --- 通知領域を閉じる
 *  - AndroidManifest.xml に要追加: <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
 */
private void publishCollapseNotificationsEvent() {
  try {
    Object sbservice = getSystemService("statusbar");
    Class<?> statusbarManager = Class.forName("android.app.StatusBarManager");
    Method collapse;
    if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {  // API Level 16 (Android 4.1, 4.1.1) or lower
      collapse = statusbarManager.getMethod("collapse");
    } else {  // API Level 17 (Android 4.2, 4.2.2) or higher
      collapse = statusbarManager.getMethod("collapsePanels");
    }
    collapse.invoke(sbservice);
  } catch (Exception e) {
    e.printStackTrace();
  }
}


■ 戻るボタン (Back Key)

AccessibilityService を継承し、下の関数を呼べば OK。ただし、Android 4.1 以降のみ。
詳しく AccessibilityService について知りたい方は、ググってください。(Bind できないので、なかなか思い通りに動かすのは大変かも。)
performGlobalAction(GLOBAL_ACTION_BACK);

0 件のコメント :

コメントを投稿