2012-07-21
2012-07-05
ASSIT機能アプリケーションを作成する
android, memo, JB, frameworks
Goolge Nowのように、端末のASSIT機能として動作するアプリケーションを作成する方法です。
Google Now(= Intent.ACTION_ASSIST)の起動トリガーでも登場した、
Intent.ACTION_ASSISTを使用します。
http://developer.android.com/reference/android/content/Intent.html#ACTION_ASSIST
AndroidManifest.xmlのactivityタグに記載しておけば起動可能です。
<activity
android:name=".TestApp"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.ASSIST" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
こんな感じでResolverに選択候補として表示されました。
と、いうことでGoogle Nowの代わりに、
2012-07-04
Google Now(= Intent.ACTION_ASSIST)の起動トリガー
android, memo, JB, frameworks
以下の記事でNavigationBarからGoogle Nowを起動するトリガーを発見しました。
Android 4.1で追加されたNAVIGATION_BAR_PANEL_LAYERについて
http://d.hatena.ne.jp/baroqueworksdev/20120630/1341088267
今回はもう少し、調査してみます。
SearchPanelViewからGoogle Nowを起動する処理はこんな感じ。
<SDK>\sources\android-16\com\android\systemui\SearchPanelView.java
private void startAssistActivity() {
// Close Recent Apps if needed
mBar.animateCollapse(CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL);
// Launch Assist
Intent intent = SearchManager.getAssistIntent(mContext);
if (intent == null) return;
try {
ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
R.anim.search_launch_enter, R.anim.search_launch_exit,
getHandler(), this);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent, opts.toBundle());
} catch (ActivityNotFoundException e) {
Slog.w(TAG, "Activity not found for " + intent.getAction());
onAnimationStarted();
}
}
どうやら、Google Nowは「Assist」というカテゴリーに属しているようです。
SearchManager#getAssistIntent()というモジュールから、
SearchManagerのソースを確認。
<SDK>\sources\android-16\android\app\SearchManager.java
/**
* Gets an intent for launching installed assistant activity, or null if not available.
* @return The assist intent.
*
* @hide
*/
public static final Intent getAssistIntent(Context context) {
PackageManager pm = context.getPackageManager();
Intent intent = new Intent(Intent.ACTION_ASSIST);
ComponentName component = intent.resolveActivity(pm);
if (component != null) {
intent.setComponent(component);
return intent;
}
return null;
}
Intent.ACTION_ASSISTというアクションIntentを持つアプリを取得しています。
これはAPI 16で新たに追加されたアクションです。
SearchManager#getAssistIntent()のコール個所
ASSITアプリを起動するソースは以下の3か所でした。
com\android\internal\policy\impl\LockScreen.java → ロック画面から起動 com\android\systemui\SearchPanelView.java → NavigationBarのタップ処理から起動 com\android\internal\policy\impl\PhoneWindowManager.java → KeyEvent.KEYCODE_ASSISTが押下されたときに起動
KeyEventにKEYCODE_ASSISTが追加されています!!
KeyEvent.KEYCODE_ASSISTが押下されたときに処理はこちら。
com\android\internal\policy\impl\PhoneWindowManager.java
/** {@inheritDoc} */
@Override
public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
:
:
} else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
if (down) {
if (repeatCount == 0) {
mAssistKeyLongPressed = false;
} else if (repeatCount == 1) {
mAssistKeyLongPressed = true;
if (!keyguardOn) {
launchAssistLongPressAction();
}
}
} else {
if (mAssistKeyLongPressed) {
mAssistKeyLongPressed = false;
} else {
if (!keyguardOn) {
launchAssistAction();
}
}
}
return -1;
}
:
:
}
private void launchAssistLongPressAction() {
performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
// launch the search activity
Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
// TODO: This only stops the factory-installed search manager.
// Need to formalize an API to handle others
SearchManager searchManager = getSearchManager();
if (searchManager != null) {
searchManager.stopSearch();
}
mContext.startActivity(intent);
} catch (ActivityNotFoundException e) {
Slog.w(TAG, "No activity to handle assist long press action.", e);
}
}
private void launchAssistAction() {
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
Intent intent = SearchManager.getAssistIntent(mContext);
if (intent != null) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
mContext.startActivity(intent);
} catch (ActivityNotFoundException e) {
Slog.w(TAG, "No activity to handle assist action.", e);
}
}
}
KeyEvent.KEYCODE_ASSISの定義はこちら。
<SDK>\sources\android-16\android\view\KeyEvent.java
/** Key code constant: Assist key.
* Launches the global assist activity. Not delivered to applications. */
public static final int KEYCODE_ASSIST = 219;
PhoneWindowManager#interceptKeyBeforeDispatching()で return -1を行っていますし、
コメントにあるように、アプリケーションには配信されないキーコードです。
2012-06-30
PhoneモードとTabletモードの切り分け
android, memo, JB, frameworks
ICSから変更されています。
これは注目すべき変更点です。
Phone/Tabletの切り分け
PhoneWindowManagerService#setInitialDisplaySizeの処理を確認
// SystemUI (status bar) layout policy
int shortSizeDp = shortSize
* DisplayMetrics.DENSITY_DEFAULT
/ DisplayMetrics.DENSITY_DEVICE;
if (shortSizeDp < 600) {
// 0-599dp: "phone" UI with a separate status & navigation bar
mHasSystemNavBar = false;
mNavigationBarCanMove = true;
} else if (shortSizeDp < 720) {
// 600-719dp: "phone" UI with modifications for larger screens
mHasSystemNavBar = false;
mNavigationBarCanMove = false;
} else {
// 720dp: "tablet" UI with a single combined status & navigation bar
mHasSystemNavBar = true;
mNavigationBarCanMove = false;
}
ICSでは600dp以上をTabletとして扱っていました。
Android 4.1で追加されたNAVIGATION_BAR_PANEL_LAYERについて
android, memo, JB, frameworks
以下の記事にて、表示レイヤーの確認を行いました。
http://d.hatena.ne.jp/baroqueworksdev/20120630/1341084903
今回は新規追加レイヤー、NAVIGATION_BAR_PANEL_LAYERの確認です。
NAVIGATION_BAR_PANEL_LAYERの使用箇所
PhoneWindowManager#windowTypeToLayerLw()にてwindowTypeからLayerの値に変換するので、grepはTYPE_NAVIGATION_BAR_PANELで。
引っかかるのは以下の3ファイルでした。
SystemUIが使用していますね。
- com\android\systemui\statusbar\phone\PhoneStatusBar.java
- com\android\systemui\statusbar\tablet\TabletStatusBar.java
- com\android\systemui\statusbar\tablet\TabletTicker.java
PhoneStatusBar.javaに焦点をあてて調査します。
TYPE_NAVIGATION_BAR_PANELを使用しているのは以下のモジュール。
BaseStatusBar#updateSearchPanel ↓ PhoneStatusBar#getSearchLayoutParams() ←★ここでWindowLayoutのパラメータとして使用
BaseStatusBar#updateSearchPanelのモジュール内で、
mSearchPanelViewというViewをWindowにaddViewしていました。
protected void updateSearchPanel() {
// Search Panel
boolean visible = false;
if (mSearchPanelView != null) {
visible = mSearchPanelView.isShowing();
WindowManagerImpl.getDefault().removeView(mSearchPanelView);
}
// Provide SearchPanel with a temporary parent to allow layout params to work.
LinearLayout tmpRoot = new LinearLayout(mContext);
mSearchPanelView = (SearchPanelView) LayoutInflater.from(mContext).inflate(
R.layout.status_bar_search_panel, tmpRoot, false);
mSearchPanelView.setOnTouchListener(
new TouchOutsideListener(MSG_CLOSE_SEARCH_PANEL, mSearchPanelView));
mSearchPanelView.setVisibility(View.GONE);
WindowManager.LayoutParams lp = getSearchLayoutParams(mSearchPanelView.getLayoutParams());
WindowManagerImpl.getDefault().addView(mSearchPanelView, lp);
mSearchPanelView.setBar(this);
if (visible) {
mSearchPanelView.show(true, false);
}
}
SearchPanelViewってなんだ?
mSearchPanelViewの表示タイミングは以下のソースを参照。
com\android\systemui\statusbar\phone\PhoneStatusBar.java
@Override
public void showSearchPanel() {
super.showSearchPanel();
WindowManager.LayoutParams lp =
(android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp);
}
private Runnable mShowSearchPanel = new Runnable() {
public void run() {
showSearchPanel();
}
};
View.OnTouchListener mHomeSearchActionListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!shouldDisableNavbarGestures()) {
mHandler.removeCallbacks(mShowSearchPanel);
mHandler.postDelayed(mShowSearchPanel, mShowSearchHoldoff);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mHandler.removeCallbacks(mShowSearchPanel);
break;
}
return false;
}
};
private void prepareNavigationBarView() {
mNavigationBarView.reorient();
mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPanel);
mNavigationBarView.getHomeButton().setOnTouchListener(mHomeSearchActionListener);
updateSearchPanel();
}
ようはHomeキーを一定時間押し続けると、SearchPanelViewが表示されます。
Viewの処理はこちらのソースを参照
\sources\android-16\com\android\systemui\SearchPanelView.java
JBの表示レイヤーについて
android, memo, JB, frameworks
一緒にソースもDLできるので、毎度おなじみの表示レイヤーのチェックを行いました。
確認OSバージョン
表示レイヤー
OSのメジャーアップデートなので、表示レイヤーの変更点があるかどうか確認しました。
ソース
SDK\sources\android-16\com\android\internal\policy\impl
- PhoneWindowManager.java
| 値 | レイヤー名 | 用途 |
|---|---|---|
| 2 | WALLPAPER_LAYER | 壁紙 |
| 2 | APPLICATION_LAYER | 一般アプリケーション |
| 3 | PHONE_LAYER | 着信などの電話用 |
| 4 | SEARCH_BAR_LAYER | 検索バー |
| 5 | SYSTEM_DIALOG_LAYER | 電源OFFダイアログなど |
| 6 | TOAST_LAYER | トースト表示 |
| 7 | PRIORITY_PHONE_LAYER | SIMエラー表示など |
| 8 | SYSTEM_ALERT_LAYER | ANRやLowバッテリー通知 |
| 9 | INPUT_METHOD_LAYER | 文字入力UI |
| 10 | INPUT_METHOD_DIALOG_LAYER | 文字入力UIのダイアログ |
| 11 | KEYGUARD_LAYER | キーガード表示 |
| 12 | KEYGUARD_DIALOG_LAYER | シャットダウン中やSIMロック表示、キーガード表示中の電源OFFダイアログなど |
| 13 | SCREENSAVER_LAYER | スクリーンセーバー★ |
| 14 | STATUS_BAR_SUB_PANEL_LAYER | Phone用expandしたパネル |
| 15 | STATUS_BAR_LAYER | StatusBar |
| 16 | STATUS_BAR_PANEL_LAYER | StatusBarをexpandしたパネル |
| 17 | VOLUME_OVERLAY_LAYER | ボリューム変更 |
| 18 | SYSTEM_OVERLAY_LAYER | キーガードより上位に表示するシステムオーバーレイ |
| 19 | NAVIGATION_BAR_LAYER | ナビゲーションBar |
| 20 | NAVIGATION_BAR_PANEL_LAYER | ナビゲーションBarの上に表示するために必要なパネル(searchなど)★ |
| 21 | SYSTEM_ERROR_LAYER | システムエラー通知 |
| 22 | DRAG_LAYER | ドラッグ&ドロップ操作用 |
| 23 | SECURE_SYSTEM_OVERLAY_LAYER | |
| 24 | BOOT_PROGRESS_LAYER | Boot中のDialog表示 |
| 25 | POINTER_LAYER | マウスポインター |
| 26 | HIDDEN_NAV_CONSUMER_LAYER | FakeWindow用 |
大きな変更点は
- SCREENSAVER_LAYERの追加
- NAVIGATION_BAR_PANEL_LAYERの追加
NAVIGATION_BAR_PANEL_LAYERのの使用箇所はべっと調査します。
2012-06-28
AOSPへのソースアップは数週間中に
以下、Android Buildingを参照。
Nexus 7 and AOSP.
https://groups.google.com/forum/?fromgroups#!topic/android-building/BnspdkGvgOE
GPL components for the Jelly Bean preview
https://groups.google.com/forum/?fromgroups#!topic/android-building/pf6ppcoWJLc
Docomo版Galaxy NexusをAndroid 4.1にする方法
その1
[GSM] How to update to JB 4.1 JRN84D
http://forum.xda-developers.com/showthread.php?t=1737618
1.IMM30D(GSM用takyu)にバージョンダウン
2.IMM30D → JRN84DのOTA updateを適用
その2
Wifiが繋がらない方はこちら




