苹果手机上出现press home to upgrade to pro,但是home 键损坏了怎么破?

苹果手机上出现press home to upgrade,但是home 键破损了怎么破?
最好不要升级 设置小白点的话 小白点在设置助理的时候没有办法使用的 或者维修好换好home键再升级
按Home键打开
启用小白点
人的综合分
感谢您为社区的和谐贡献力量请选择举报类型
经过核实后将会做出处理感谢您为社区和谐做出贡献
确定要取消此次报名,退出该活动?苹果手机上出现press home to upgrade,但是home 键损坏了怎么破?_百度知道
苹果手机上出现press home to upgrade,但是home 键损坏了怎么破?
我有更好的答案
最好不要升级 设置小白点的话 小白点在设置助理的时候没有办法使用的 或者维修好换好home键再升级
采纳率:78%
来自团队:
启用小白点
屏幕上没有小白点
按Home键打开
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。博客访问: 173922
博文数量: 60
博客积分: 235
博客等级: 二等列兵
技术积分: 409
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: Java 12:24:43
&如果想在Android手机要想扩展一个实体键,就我知道而言有两种方法,基于Android4.0的源码来分析的和2.3的源码有点区别,区别不大,下面分享给大家:
&&& 转载请标明出处:
&&&&&&&& (一)可以在frameworks层的KeyEvent.java这个类中定义一个值,在PhoneWindowManager.java这个类中做处理就可以了。(Home键就是这么实现的)。效果图如下:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&(二)可以利用广播的形式,frameworks层PhoneWindow.java这个类的onKeyDown( )对这个实体键发广播,上层接受这个广播来处理也可以达到这个效果。耳机键就是利用广播来接受的。无论在哪个界面长按耳机键,都会进入到音乐的界面。(长按耳机键的)效果图如下:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
下面我详细展开来说明一下:
&&&一、先说Home键的实现的大致流程,即---->为什么点击Home键,都进入到launcher的待机界面;
& (1)Home键的定义在
&&&&&& step1: frameworks/base/core/java/android/view/KeyEvent.java这个类中,在KeyEvent.java这个类中有个static的静态块:
static&{&&
&&&&&&populateKeycodeSymbolicNames();&&
populateKeycodeSymbolicNames();
&&&&& &step2: 这个populateKeycodeSymbolicNames()方法其实就是加载了许多键的定义,把这些键对应的值都放到Array数组中。
<span&style="font-size:16">private&static&void&populateKeycodeSymbolicNames()&{&&
&&&&&&&&SparseArray&names&=&KEYCODE_SYMBOLIC_NAMES;&&
&&&&&&&&names.append(KEYCODE_UNKNOWN,&"KEYCODE_UNKNOWN");&&
&&&&&&&&names.append(KEYCODE_SOFT_LEFT,&"KEYCODE_SOFT_LEFT");&&
&&&&&&&&names.append(KEYCODE_SOFT_RIGHT,&"KEYCODE_SOFT_RIGHT");&&
&&&&&&&&names.append(KEYCODE_HOME,&"KEYCODE_HOME");&&
&&&&&&&&names.append(KEYCODE_BACK,&"KEYCODE_BACK");&&
&&&&&&&&names.append(KEYCODE_CALL,&"KEYCODE_CALL");&&
&&&&&&&&names.append(KEYCODE_ENDCALL,&"KEYCODE_ENDCALL");&&
&&&&&&&&names.append(KEYCODE_0,&"KEYCODE_0");&&
&&&&&&&&names.append(KEYCODE_1,&"KEYCODE_1");&&
&&&&&&&&names.append(KEYCODE_2,&"KEYCODE_2");&&
&&&&&&&&names.append(KEYCODE_3,&"KEYCODE_3");&&
&&&&&&&&names.append(KEYCODE_4,&"KEYCODE_4");&&
&&&&&&&&names.append(KEYCODE_5,&"KEYCODE_5");&&
&&&&&&&&names.append(KEYCODE_6,&"KEYCODE_6");&&
&&&&&&&&names.append(KEYCODE_7,&"KEYCODE_7");&&
&&&&&&&&names.append(KEYCODE_8,&"KEYCODE_8");&&
&&&&&&&&names.append(KEYCODE_9,&"KEYCODE_9");&&private static void populateKeycodeSymbolicNames() {
SparseArray names = KEYCODE_SYMBOLIC_NAMES;
names.append(KEYCODE_UNKNOWN, "KEYCODE_UNKNOWN");
names.append(KEYCODE_SOFT_LEFT, "KEYCODE_SOFT_LEFT");
names.append(KEYCODE_SOFT_RIGHT, "KEYCODE_SOFT_RIGHT");
names.append(KEYCODE_HOME, "KEYCODE_HOME");
names.append(KEYCODE_BACK, "KEYCODE_BACK");
names.append(KEYCODE_CALL, "KEYCODE_CALL");
names.append(KEYCODE_ENDCALL, "KEYCODE_ENDCALL");
names.append(KEYCODE_0, "KEYCODE_0");
names.append(KEYCODE_1, "KEYCODE_1");
names.append(KEYCODE_2, "KEYCODE_2");
names.append(KEYCODE_3, "KEYCODE_3");
names.append(KEYCODE_4, "KEYCODE_4");
names.append(KEYCODE_5, "KEYCODE_5");
names.append(KEYCODE_6, "KEYCODE_6");
names.append(KEYCODE_7, "KEYCODE_7");
names.append(KEYCODE_8, "KEYCODE_8");
names.append(KEYCODE_9, "KEYCODE_9");
&&&&&& step3: 而Home键对应的值如下:
<span&style="font-size:16">&
&&&public&static&final&int&KEYCODE_HOME&&&&&&&&&&&&=&3;&& /** Key code constant: Home key.
* This key is handled by the framework and is never delivered to applications. */
public static final int KEYCODE_HOME
(2)Home键的处理如下:在&&&& &step1: frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java这个类中:
在这个方法interceptKeyBeforeDispatching(... ... ...)中处理有对Home,Search,menu,音量大小键等等:
<span&style="font-size:16">&&&&
&&&&@Override&&
&&&&public&long&interceptKeyBeforeDispatching(WindowState&win,&KeyEvent&event,&int&policyFlags)&{&&
&&&&&&&&final&boolean&keyguardOn&=&keyguardOn();&&
&&&&&&&&final&int&keyCode&=&event.getKeyCode();&&
&&&&&&&&final&int&repeatCount&=&event.getRepeatCount();&&
&&&&&&&&final&int&metaState&=&event.getMetaState();&&
&&&&&&&&final&int&flags&=&event.getFlags();&&
&&&&&&&&final&boolean&down&=&event.getAction()&==&KeyEvent.ACTION_DOWN;&&
&&&&&&&&final&boolean&canceled&=&event.isCanceled();&&
&&&&&&&&if&(false)&{&&
&&&&&&&&&&&&Log.d(TAG,&"interceptKeyTi&keyCode="&+&keyCode&+&"&down="&+&down&+&"&repeatCount="&&
&&&&&&&&&&&&&&&&&&&&+&repeatCount&+&"&keyguardOn="&+&keyguardOn&+&"&mHomePressed="&+&mHomePressed);&&
&&&&&&&&}&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&if&((flags&&&KeyEvent.FLAG_FALLBACK)&==&0)&{&&
&&&&&&&&&&&&if&(mVolumeDownKeyTriggered&&&&!mPowerKeyTriggered)&{&&
&&&&&&&&&&&&&&&&final&long&now&=&SystemClock.uptimeMillis();&&
&&&&&&&&&&&&&&&&final&long&timeoutTime&=&mVolumeDownKeyTime&+&SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;&&
&&&&&&&&&&&&&&&&if&(now&<&timeoutTime)&{&&
&&&&&&&&&&&&&&&&&&&&return&timeoutTime&-&&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&if&(keyCode&==&KeyEvent.KEYCODE_VOLUME_DOWN&&
&&&&&&&&&&&&&&&&&&&&&&&mVolumeDownKeyConsumedByScreenshotChord)&{&&
&&&&&&&&&&&&&&&&if&(!down)&{&&
&&&&&&&&&&&&&&&&&&&&mVolumeDownKeyConsumedByScreenshotChord&=&false;&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&return&-1;&&
&&&&&&&&&&&&}&&
&&&&&&&&}&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&if&(keyCode&==&KeyEvent.KEYCODE_HOME)&{&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&if&(mHomePressed&&&&!down)&{&&
&&&&&&&&&&&&&&&&mHomePressed&=&false;&&
&&&&&&&&&&&&&&&&if&(!canceled)&{&&
&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&boolean&incomingRinging&=&false;&&
&&&&&&&&&&&&&&&&&&&&try&{&&
&&&&&&&&&&&&&&&&&&&&&&&&ITelephony&telephonyService&=&getTelephonyService();&&
&&&&&&&&&&&&&&&&&&&&&&&&if&(telephonyService&!=&null)&{&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&incomingRinging&=&telephonyService.isRinging();&&
&&&&&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&&&&&}&catch&(RemoteException&ex)&{&&
&&&&&&&&&&&&&&&&&&&&&&&&Log.w(TAG,&"RemoteException&from&getPhoneInterface()",&ex);&&
&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&&&&&if&(incomingRinging)&{&&
&&&&&&&&&&&&&&&&&&&&&&&&Log.i(TAG,&"Ignoring&HOME;&there's&a&ringing&incoming&call.");&&
&&&&&&&&&&&&&&&&&&&&}&else&{&&
&&&&&&&&&&&&&&&&&&&&&&&&launchHomeFromHotKey();&&
&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&}&else&{&&
&&&&&&&&&&&&&&&&&&&&Log.i(TAG,&"Ignoring&HOME;&event&canceled.");&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&return&-1;&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&WindowManager.LayoutParams&attrs&=&win&!=&null&?&win.getAttrs()&:&null;&&
&&&&&&&&&&&&if&(attrs&!=&null)&{&&
&&&&&&&&&&&&&&&&final&int&type&=&attrs.&&
&&&&&&&&&&&&&&&&if&(type&==&WindowManager.LayoutParams.TYPE_KEYGUARD&&
&&&&&&&&&&&&&&&&&&&&&&&&||&type&==&WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG)&{&&
&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&return&0;&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&final&int&typeCount&=&WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.&&
&&&&&&&&&&&&&&&&for&(int&i=0;&i<typeC&i++)&{&&
&&&&&&&&&&&&&&&&&&&&if&(type&==&WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i])&{&&
&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&return&-1;&&
&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&if&(down)&{&&
&&&&&&&&&&&&&&&&if&(repeatCount&==&0)&{&&
&&&&&&&&&&&&&&&&&&&&mHomePressed&=&true;&&
&&&&&&&&&&&&&&&&}&else&if&((event.getFlags()&&&KeyEvent.FLAG_LONG_PRESS)&!=&0)&{&&
&&&&&&&&&&&&&&&&&&&&if&(!keyguardOn)&{&&
&&&&&&&&&&&&&&&&&&&&&&&&handleLongPressOnHome();&&
&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&return&-1;&&
&&&&&&&&}&else&if&(keyCode&==&KeyEvent.KEYCODE_MENU)&{&&
&&&&&&&&&&&........&&
/** {@inheritDoc} */
public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
final boolean keyguardOn = keyguardOn();
final int keyCode = event.getKeyCode();
final int repeatCount = event.getRepeatCount();
final int metaState = event.getMetaState();
final int flags = event.getFlags();
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final boolean canceled = event.isCanceled();
if (false) {
Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
+ repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
// If we think we might have a volume down & power key chord on the way
// but we're not sure, then tell the dispatcher to wait a little while and
// try again later before dispatching.
if ((flags & KeyEvent.FLAG_FALLBACK) == 0) {
if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) {
final long now = SystemClock.uptimeMillis();
final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
if (now < timeoutTime) {
return timeoutTime -
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
&& mVolumeDownKeyConsumedByScreenshotChord) {
if (!down) {
mVolumeDownKeyConsumedByScreenshotChord =
return -1;
// First we always handle the home key here, so applications
// can never break it, although if keyguard is on, we do let
// it handle it, because that gives us the correct 5 second
// timeout.
if (keyCode == KeyEvent.KEYCODE_HOME) {
// If we have released the home key, and didn't do anything else
// while it was pressed, then it is time to go home!
if (mHomePressed && !down) {
mHomePressed =
if (!canceled) {
// If an incoming call is ringing, HOME is totally disabled.
// (The user is already on the InCallScreen at this point,
// and his ONLY options are to answer or reject the call.)
boolean incomingRinging =
ITelephony telephonyService = getTelephonyService();
if (telephonyService != null) {
incomingRinging = telephonyService.isRinging();
} catch (RemoteException ex) {
Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
if (incomingRinging) {
Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
launchHomeFromHotKey();
Log.i(TAG, "Ignoring HOME; event canceled.");
return -1;
// If a system window has focus, then it doesn't make sense
// right now to interact with applications.
WindowManager.LayoutParams attrs = win != null ? win.getAttrs() :
if (attrs != null) {
final int type = attrs.
if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
|| type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
// the "app" is keyguard, so give it the key
final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.
for (int i=0; i<typeC i++) {
if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
// don't do anything, but also don't pass it to the app
return -1;
if (down) {
if (repeatCount == 0) {
mHomePressed =
} else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
if (!keyguardOn) {
handleLongPressOnHome();
return -1;
} else if (keyCode == KeyEvent.KEYCODE_MENU) {
<span&style="font-size:16">&&
&&<span&style="font-size:24">&<span&style="font-size:18">Step2:&<span&style="color:#990000;">插曲《<span&style="color:#006600;">网上有例子说怎么在自己的应用中屏蔽Home键》--->原理:是在你的应用的Activity中加入了锁屏的type,因为系统对锁屏界面,点击Home键失效!网摘代码如下:&&
&& Step2: 插曲《网上有例子说怎么在自己的应用中屏蔽Home键》--->原理:是在你的应用的Activity中加入了锁屏的type,因为系统对锁屏界面,点击Home键失效!网摘代码如下:
public&class&DMActivity&extends&Activity&{&&&&
&&&&private&boolean&flag&=&true;&&
&&&&@Override&&&&
&&&&public&void&onCreate(Bundle&savedInstanceState)&{&&&&
&&&&&&&&super.onCreate(savedInstanceState);&&&&
&&&&&&&&setContentView(R.layout.main);&&&&
&&&&@Override&&&&
&&&&public&void&onAttachedToWindow()&{&&&&
&&&&&&&&if(flag)&{&&&&
&&&&&&&&&&&&this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);&&&&
&&&&&&&&}&&&&
&&&&&&&&super.onAttachedToWindow();&&&&
&&&&@Override&&&&
&&&&public&boolean&onKeyDown(int&keyCode,&KeyEvent&event)&{&&&&
&&&&&&&&if(keyCode&==&KeyEvent.KEYCODE_HOME){&&&&
&&&&&&&&&&&&return&true;&&&&
&&&&&&&&}&&&&
&&&&&&&&return&super.onKeyDown(keyCode,&event);&&&&
}&&&&public class DMActivity extends Activity {
private boolean flag =//true位屏蔽,false位不屏蔽
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
public void onAttachedToWindow() {
if(flag) {
this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);
super.onAttachedToWindow();
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_HOME){
return super.onKeyDown(keyCode, event);
&&&&& &Step3: 真正的原因如下,对锁屏模式的处理:
<span&style="font-size:16">&&&&&&&&&&&&&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&WindowManager.LayoutParams&attrs&=&win&!=&null&?&win.getAttrs()&:&null;&&
&&&&&&&&&&&&if&(attrs&!=&null)&{&&
&&&&&&&&&&&&&&&&final&int&type&=&attrs.&&
&&&&&&&&&&&&&&&&if&(type&==&WindowManager.LayoutParams.TYPE_KEYGUARD&&
&&&&&&&&&&&&&&&&&&&&&&&&||&type&==&WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG)&{&&
&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&return&0;&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&final&int&typeCount&=&WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.&&
&&&&&&&&&&&&&&&&for&(int&i=0;&i<typeC&i++)&{&&
&&&&&&&&&&&&&&&&&&&&if&(type&==&WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i])&{&&
&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&return&-1;&&
&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&}&&
// If a system window has focus, then it doesn't make sense
// right now to interact with applications.
WindowManager.LayoutParams attrs = win != null ? win.getAttrs() :
if (attrs != null) {
final int type = attrs.
if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
|| type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
// the "app" is keyguard, so give it the key
final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.
for (int i=0; i<typeC i++) {
if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
// don't do anything, but also don't pass it to the app
return -1;
&&&&& Step4: 我们来看点击home键,为什么进入到launcher的待机界面:
<span&style="font-size:16">&&
if&(mHomePressed&&&&!down)&{&&
&&&&mHomePressed&=&false;&&
&&&&if&(!canceled)&{&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&boolean&incomingRinging&=&false;&&
&&&&&&&&try&{&&
&&&&&&&&&&&&ITelephony&telephonyService&=&getTelephonyService();&&
&&&&&&&&&&&&if&(telephonyService&!=&null)&{&&
&&&&&&&&&&&&&&&&incomingRinging&=&telephonyService.isRinging();&&
&&&&&&&&&&&&}&&
&&&&&&&&}&catch&(RemoteException&ex)&{&&
&&&&&&&&&&&&Log.w(TAG,&"RemoteException&from&getPhoneInterface()",&ex);&&
&&&&&&&&}&&
&&&&&&&&if&(incomingRinging)&{&&
&&&&&&&&&&&&Log.i(TAG,&"Ignoring&HOME;&there's&a&ringing&incoming&call.");&&
&&&&&&&&}&else&{&&
&&&&&&&&&&&&launchHomeFromHotKey();&&
&&&&&&&&}&&
&&&&}&else&{&&
&&&&&&&&Log.i(TAG,&"Ignoring&HOME;&event&canceled.");&&
&&&&return&-1;&&
// If we have released the home key, and didn't do anything else
// while it was pressed, then it is time to go home!
if (mHomePressed && !down) {
mHomePressed =
if (!canceled) {
// If an incoming call is ringing, HOME is totally disabled.
// (The user is already on the InCallScreen at this point,
// and his ONLY options are to answer or reject the call.)
boolean incomingRinging =
ITelephony telephonyService = getTelephonyService();
if (telephonyService != null) {
incomingRinging = telephonyService.isRinging();
} catch (RemoteException ex) {
Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
if (incomingRinging) {
Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
launchHomeFromHotKey();
Log.i(TAG, "Ignoring HOME; event canceled.");
return -1;
&&&&&&&&&& Step5: 系统会判断,当前点击Home键并且没有电话打入的情况,才对Home键进行处理---->launchHomeFromHotKey();进入到----->launchHomeFromHotKey()方法中:
void&launchHomeFromHotKey()&{&&
&&&&if&(mKeyguardMediator.isShowingAndNotHidden())&{&&
&&&&&&&&&&
&&&&}&else&if&(!mHideLockScreen&&&&mKeyguardMediator.isInputRestricted())&{&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&mKeyguardMediator.verifyUnlock(new&OnKeyguardExitResult()&{&&
&&&&&&&&&&&&public&void&onKeyguardExitResult(boolean&success)&{&&
&&&&&&&&&&&&&&&&if&(success)&{&&
&&&&&&&&&&&&&&&&&&&&try&{&&
&&&&&&&&&&&&&&&&&&&&&&&&ActivityManagerNative.getDefault().stopAppSwitches();&&
&&&&&&&&&&&&&&&&&&&&}&catch&(RemoteException&e)&{&&
&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&&&&&sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);&&
&&&&&&&&&&&&&&&&&&&&startDockOrHome();&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&}&&
&&&&&&&&});&&
&&&&}&else&{&&
&&&&&&&&&&
&&&&&&&&try&{&&
&&&&&&&&&&&&ActivityManagerNative.getDefault().stopAppSwitches();&&
&&&&&&&&}&catch&(RemoteException&e)&{&&
&&&&&&&&}&&
&&&&&&&&sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);&&
&&&&&&&&startDockOrHome();&&
* A home key -> launch home action was detected.
Take the appropriate action
* given the situation with the keyguard.
void launchHomeFromHotKey() {
if (mKeyguardMediator.isShowingAndNotHidden()) {
// don't launch home if keyguard showing
} else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
// when in keyguard restricted mode, must first verify unlock
// before launching home
mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {
public void onKeyguardExitResult(boolean success) {
if (success) {
ActivityManagerNative.getDefault().stopAppSwitches();
} catch (RemoteException e) {
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
startDockOrHome();
// no keyguard stuff to worry about, just launch home!
ActivityManagerNative.getDefault().stopAppSwitches();
} catch (RemoteException e) {
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
startDockOrHome();
&&&&&&& &Step6: 也是对锁屏模式有个判断,如果不在锁屏模式,就launch Home---->startDockOrHome(),进入——>
<span&style="font-size:16">&&&void&startDockOrHome()&{&&
&&&&&&&&Intent&dock&=&createHomeDockIntent();&&
&&&&&&&&if&(dock&!=&null)&{&&
&&&&&&&&&&&&try&{&&
&&&&&&&&&&&&&&&&mContext.startActivity(dock);&&
&&&&&&&&&&&&&&&&return;&&
&&&&&&&&&&&&}&catch&(ActivityNotFoundException&e)&{&&
&&&&&&&&&&&&}&&
&&&&&&&&}&&
&&&&&&&&mContext.startActivity(mHomeIntent);&&
void startDockOrHome() {
Intent dock = createHomeDockIntent();
if (dock != null) {
mContext.startActivity(dock);
} catch (ActivityNotFoundException e) {
mContext.startActivity(mHomeIntent);
&&&&&&&&& Step 7: 其实这个createHomeDockIntent()方法就是对android手机的几种模式进行判断,
The device is not in either car mode or desk mode&&&&&&&&&&&&& The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false&&&&&&&&&&&&& The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false&&&&&&&&&&&&& The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME&&&&&&&&&&&&& The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
&&&&&&&如果是以上模式,车载模式或者桌面模式,就返回dock不为空,否则为空。启动这个mHomeIntent。----->mHomeIntent定义如下:
<span&style="font-size:16">&&&&mHomeIntent&=&&new&Intent(Intent.ACTION_MAIN,&null);&&
&mHomeIntent.addCategory(Intent.CATEGORY_HOME);&&
&mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK&&
&&&&&&&&&|&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);&&
mHomeIntent =
new Intent(Intent.ACTION_MAIN, null);
mHomeIntent.addCategory(Intent.CATEGORY_HOME);
mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
&&&&&& Step 8: 这个mHomeIntent就是启动activity中配置Category属性的值为CATEGORY_HOME,启动的时候新启动一个任务,不是在当前的这个任务中启动launcherHome,而是新建一个task。
&&&&&& FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标记进入前台时(典型的操作是用户在主画面重启它),这个Activity和它之上的都将关闭,以至于用户不能再返回到它们,但是可以回到之前的Activity。
到这为止,Home键的流程已经分析完了。
&&&&&&& 二 、下面看看长按耳机键接受的广播的处理方式:&&&&
&&&&&&&(1)这个长按耳机键捕获是在PhoneWindow.java类的onKeyDown()中,然后发送有序的广播---->如下:
<span&xmlns="http://www.w3.org/1999/xhtml"&style=""><span&xmlns="http://www.w3.org/1999/xhtml"&style=""><span&xmlns="http://www.w3.org/1999/xhtml"&style="">&&&&&&&&&&&&case&KeyEvent.KEYCODE_HEADSETHOOK:&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&case&KeyEvent.KEYCODE_MEDIA_STOP:&&
&&&&&&&&&&&&case&KeyEvent.KEYCODE_MEDIA_NEXT:&&
&&&&&&&&&&&&case&KeyEvent.KEYCODE_MEDIA_PREVIOUS:&&
&&&&&&&&&&&&case&KeyEvent.KEYCODE_MEDIA_REWIND:&&
&&&&&&&&&&&&case&KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:&{&&
&&&&&&&&&&&&&&&&Intent&intent&=&new&Intent(Intent.ACTION_MEDIA_BUTTON,&null);&&
&&&&&&&&&&&&&&&&intent.putExtra(Intent.EXTRA_KEY_EVENT,&event);&&
&&&&&&&&&&&&&&&&getContext().sendOrderedBroadcast(intent,&null);&&
&&&&&&&&&&&&&&&&return&true;&&
&&&&&&&&&&&&}&&
& & & & & case KeyEvent.KEYCODE_HEADSETHOOK:
case KeyEvent.KEYCODE_MEDIA_STOP:
case KeyEvent.KEYCODE_MEDIA_NEXT:
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
case KeyEvent.KEYCODE_MEDIA_REWIND:
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
getContext().sendOrderedBroadcast(intent, null);
&&&&& 接受这个长按耳机键的广播是在Music的app中的----->
&& public&class&MediaButtonIntentReceiver&extends&BroadcastReceiver{&&...&...&}
&&&&&&&&&& , 需要在Manifest.xml中注册这个广播
&&&&&&&&&&&&&&
&&&&&&&&&&&&&& 。---->注册MediaButtonReceiver这个广播,
&&&&&&&&&&&&& 这个类中onReceive()方法定义的:代码如下--->
<span&style="font-size:16">&&&&@Override&&
&&&&public&void&onReceive(Context&context,&Intent&intent)&{&&
&&&&&&&&String&intentAction&=&intent.getAction();&&
&&&&&&&&if&(AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intentAction))&{&&
&&&&&&&&&&&&Intent&i&=&new&Intent(MediaPlaybackService.SERVICECMD);&&
&&&&&&&&&&&&i.putExtra(MediaPlaybackService.CMDNAME,&MediaPlaybackService.CMDPAUSE);&&
&&&&&&&&&&&&context.sendBroadcast(i);&&
&&&&&&&&}&else&if&(Intent.ACTION_MEDIA_BUTTON.equals(intentAction))&{&&
&&&&&&&&&&&&KeyEvent&event&=&(KeyEvent)&&
&&&&&&&&&&&&&&&&&&&&intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&if&(event&==&null)&{&&
&&&&&&&&&&&&&&&&return;&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&int&keycode&=&event.getKeyCode();&&
&&&&&&&&&&&&int&action&=&event.getAction();&&
&&&&&&&&&&&&long&eventtime&=&event.getEventTime();&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&String&command&=&null;&&
&&&&&&&&&&&&switch&(keycode)&{&&
&&&&&&&&&&&&&&&&case&KeyEvent.KEYCODE_MEDIA_STOP:&&
&&&&&&&&&&&&&&&&&&&&command&=&MediaPlaybackService.CMDSTOP;&&
&&&&&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&&&&&case&KeyEvent.KEYCODE_HEADSETHOOK:&&
&&&&&&&&&&&&&&&&case&KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:&&
&&&&&&&&&&&&&&&&&&&&command&=&MediaPlaybackService.CMDTOGGLEPAUSE;&&
&&&&&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&&&&&case&KeyEvent.KEYCODE_MEDIA_NEXT:&&
&&&&&&&&&&&&&&&&&&&&command&=&MediaPlaybackService.CMDNEXT;&&
&&&&&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&&&&&case&KeyEvent.KEYCODE_MEDIA_PREVIOUS:&&
&&&&&&&&&&&&&&&&&&&&command&=&MediaPlaybackService.CMDPREVIOUS;&&
&&&&&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&&&&&case&KeyEvent.KEYCODE_MEDIA_PAUSE:&&
&&&&&&&&&&&&&&&&&&&&command&=&MediaPlaybackService.CMDPAUSE;&&
&&&&&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&&&&&case&KeyEvent.KEYCODE_MEDIA_PLAY:&&
&&&&&&&&&&&&&&&&&&&&command&=&MediaPlaybackService.CMDPLAY;&&
&&&&&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&if&(command&!=&null)&{&&
&&&&&&&&&&&&&&&&if&(action&==&KeyEvent.ACTION_DOWN)&{&&
&&&&&&&&&&&&&&&&&&&&if&(mDown)&{&&
&&&&&&&&&&&&&&&&&&&&&&&&if&((MediaPlaybackService.CMDTOGGLEPAUSE.equals(command)&||&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&MediaPlaybackService.CMDPLAY.equals(command))&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&mLastClickTime&!=&0&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&eventtime&-&mLastClickTime&>&LONG_PRESS_DELAY)&{&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&mHandler.sendMessage(&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&mHandler.obtainMessage(MSG_LONGPRESS_TIMEOUT,&context));&&
&&&&&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&&&&&}&else&if&(event.getRepeatCount()&==&0)&{&&
&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&Intent&i&=&new&Intent(context,&MediaPlaybackService.class);&&
&&&&&&&&&&&&&&&&&&&&&&&&i.setAction(MediaPlaybackService.SERVICECMD);&&
&&&&&&&&&&&&&&&&&&&&&&&&if&(keycode&==&KeyEvent.KEYCODE_HEADSETHOOK&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&eventtime&-&mLastClickTime&<&300)&{&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&i.putExtra(MediaPlaybackService.CMDNAME,&MediaPlaybackService.CMDNEXT);&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&context.startService(i);&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&mLastClickTime&=&0;&&
&&&&&&&&&&&&&&&&&&&&&&&&}&else&{&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&i.putExtra(MediaPlaybackService.CMDNAME,&command);&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&context.startService(i);&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&mLastClickTime&=&&&
&&&&&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&&&&&&&&&mLaunched&=&false;&&
&&&&&&&&&&&&&&&&&&&&&&&&mDown&=&true;&&
&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&}&else&{&&
&&&&&&&&&&&&&&&&&&&&mHandler.removeMessages(MSG_LONGPRESS_TIMEOUT);&&
&&&&&&&&&&&&&&&&&&&&mDown&=&false;&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&if&(isOrderedBroadcast())&{&&
&&&&&&&&&&&&&&&&&&&&abortBroadcast();&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&}&&
&&&&&&&&}&&
public void onReceive(Context context, Intent intent) {
String intentAction = intent.getAction();
if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intentAction)) {
Intent i = new Intent(MediaPlaybackService.SERVICECMD);
i.putExtra(MediaPlaybackService.CMDNAME, MediaPlaybackService.CMDPAUSE);
context.sendBroadcast(i);
} else if (Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
KeyEvent event = (KeyEvent)
intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (event == null) {
int keycode = event.getKeyCode();
int action = event.getAction();
long eventtime = event.getEventTime();
// single quick press: pause/resume.
// double press: next track
// long press: start auto-shuffle mode.
String command =
switch (keycode) {
case KeyEvent.KEYCODE_MEDIA_STOP:
command = MediaPlaybackService.CMDSTOP;
case KeyEvent.KEYCODE_HEADSETHOOK:
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
command = MediaPlaybackService.CMDTOGGLEPAUSE;
case KeyEvent.KEYCODE_MEDIA_NEXT:
command = MediaPlaybackService.CMDNEXT;
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
command = MediaPlaybackService.CMDPREVIOUS;
case KeyEvent.KEYCODE_MEDIA_PAUSE:
command = MediaPlaybackService.CMDPAUSE;
case KeyEvent.KEYCODE_MEDIA_PLAY:
command = MediaPlaybackService.CMDPLAY;
if (command != null) {
if (action == KeyEvent.ACTION_DOWN) {
if (mDown) {
if ((MediaPlaybackService.CMDTOGGLEPAUSE.equals(command) ||
MediaPlaybackService.CMDPLAY.equals(command))
&& mLastClickTime != 0
&& eventtime - mLastClickTime > LONG_PRESS_DELAY) {
mHandler.sendMessage(
mHandler.obtainMessage(MSG_LONGPRESS_TIMEOUT, context));
} else if (event.getRepeatCount() == 0) {
// only consider the first event in a sequence, not the repeat events,
// so that we don't trigger in cases where the first event went to
// a different app (e.g. when the user ends a phone call by
// long pressing the headset button)
// The service may or may not be running, but we need to send it
// a command.
Intent i = new Intent(context, MediaPlaybackService.class);
i.setAction(MediaPlaybackService.SERVICECMD);
if (keycode == KeyEvent.KEYCODE_HEADSETHOOK &&
eventtime - mLastClickTime < 300) {
i.putExtra(MediaPlaybackService.CMDNAME, MediaPlaybackService.CMDNEXT);
context.startService(i);
mLastClickTime = 0;
i.putExtra(MediaPlaybackService.CMDNAME, command);
context.startService(i);
mLastClickTime =
mLaunched =
mHandler.removeMessages(MSG_LONGPRESS_TIMEOUT);
if (isOrderedBroadcast()) {
abortBroadcast();
&&&&&&& &step1:&& 在方法if (action == KeyEvent.ACTION_DOWN) { ... ... }做的处理,event.getRepeatCount() == 0这个判断的意思是“是否长按耳机键?”,如果长按耳机键event.getRepeatCount() 的值就一直增加。
&&& & step 2:短按耳机键:播放/暂停 --->音乐;短按启动MediaPlaybackService.java这个类,并且传入参数---->在这个服务类中有个接受广播的内部类:如下-->
<span&style="font-size:16">private&BroadcastReceiver&mIntentReceiver&=&new&BroadcastReceiver()&{&&
@Override&&
public&void&onReceive(Context&context,&Intent&intent)&{&&
&&&&String&action&=&intent.getAction();&&
&&&&String&cmd&=&intent.getStringExtra("command");&&
&&&&MusicUtils.debugLog("mIntentReceiver.onReceive&"&+&action&+&"&/&"&+&cmd);&&
&&&&if&(CMDNEXT.equals(cmd)&||&NEXT_ACTION.equals(action))&{&&
&&&&&&&&next(true);&&
&&&&}&else&if&(CMDPREVIOUS.equals(cmd)&||&PREVIOUS_ACTION.equals(action))&{&&
&&&&&&&&prev();&&
&&&&}&else&if&(CMDTOGGLEPAUSE.equals(cmd)&||&TOGGLEPAUSE_ACTION.equals(action))&{&&
&&&&&&&&if&(isPlaying())&{&&
&&&&&&&&&&&&pause();&&
&&&&&&&&&&&&mInternalPause&=&false;&&
&&&&&&&&}&else&{&&
&&&&&&&&&&&&play();&&
&&&&&&&&}&&
&&&&}&else&if&(CMDPAUSE.equals(cmd)&||&PAUSE_ACTION.equals(action))&{&&
&&&&&&&&pause();&&
&&&&&&&&mInternalPause&=&false;&&
&&&&}&else&if&(CMDPLAY.equals(cmd))&{&&
&&&&&&&&play();&&
&&&&}&else&if&(CMDSTOP.equals(cmd))&{&&
&&&&&&&&pause();&&
&&&&&&&&mInternalPause&=&false;&&
&&&&&&&&seek(0);&&
&&&&}&else&if&(MediaAppWidgetProvider.CMDAPPWIDGETUPDATE.equals(cmd))&{&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&int[]&appWidgetIds&=&intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);&&
&&&&&&&&mAppWidgetProvider.performUpdate(MediaPlaybackService.this,&appWidgetIds);&&
t;/span>&&
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String cmd = intent.getStringExtra("command");
MusicUtils.debugLog("mIntentReceiver.onReceive " + action + " / " + cmd);
if (CMDNEXT.equals(cmd) || NEXT_ACTION.equals(action)) {
next(true);
} else if (CMDPREVIOUS.equals(cmd) || PREVIOUS_ACTION.equals(action)) {
} else if (CMDTOGGLEPAUSE.equals(cmd) || TOGGLEPAUSE_ACTION.equals(action)) {
if (isPlaying()) {
mInternalPause =
} else if (CMDPAUSE.equals(cmd) || PAUSE_ACTION.equals(action)) {
mInternalPause =
} else if (CMDPLAY.equals(cmd)) {
} else if (CMDSTOP.equals(cmd)) {
mInternalPause =
} else if (MediaAppWidgetProvider.CMDAPPWIDGETUPDATE.equals(cmd)) {
// Someone asked us to refresh a set of specific widgets, probably
// because they were just added.
int[] appWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
mAppWidgetProvider.performUpdate(MediaPlaybackService.this, appWidgetIds);
&&&&&&&& 通过:如下方法来控制点击播放音乐,再次点击暂停,如此循环。
&else if (CMDTOGGLEPAUSE.equals(cmd) || TOGGLEPAUSE_ACTION.equals(action)) {
&&&&&&&& if (isPlaying()) {
&&&&&&&&&&&&&&&&&& pause();
&&&&&&&&&&&&&&&&&& mInternalPause =
&&&&&&&& &} else {
&&&&&&&&&&&&&&&&&&& play();
&&&&&&&&&&}
内部类的广播是在启动MediaPlaybackService.java中注册的,解除注册在onDestroy()的方法中。
<span&style="font-size:18">&&&&&&&&<span&style="font-size:16">IntentFilter&commandFilter&=&new&IntentFilter();&&
&&&&&&&&commandFilter.addAction(SERVICECMD);&&
&&&&&&&&commandFilter.addAction(TOGGLEPAUSE_ACTION);&&
&&&&&&&&commandFilter.addAction(PAUSE_ACTION);&&
&&&&&&&&commandFilter.addAction(NEXT_ACTION);&&
&&&&&&&&commandFilter.addAction(PREVIOUS_ACTION);&&
&&&&&&&&commandFilter.addAction(PLAYSTATUS_REQUEST);&&
&&&&&&&&registerReceiver(mIntentReceiver,&commandFilter);&&
IntentFilter commandFilter = new IntentFilter();
commandFilter.addAction(SERVICECMD);
commandFilter.addAction(TOGGLEPAUSE_ACTION);
commandFilter.addAction(PAUSE_ACTION);
commandFilter.addAction(NEXT_ACTION);
commandFilter.addAction(PREVIOUS_ACTION);
commandFilter.addAction(PLAYSTATUS_REQUEST);
registerReceiver(mIntentReceiver, commandFilter);
&&&&& Step 3:& 长按耳机键--->发消息给mHandler,
<span&style="font-size:18">&&&&&&&mHandler.removeMessages(MSG_LONGPRESS_TIMEOUT);&&
mHandler.removeMessages(MSG_LONGPRESS_TIMEOUT);
&&&& 在MediaButtonIntentReceiver.java中有个内部类Handler()如下——>
<span&style="font-size:16color:#000000;">&&&&&&&&private&static&Handler&mHandler&=&new&Handler()&{&&
&&&&&&&&@Override&&
&&&&&&&&public&void&handleMessage(Message&msg)&{&&
&&&&&&&&&&&&switch&(msg.what)&{&&
&&&&&&&&&&&&&&&&case&MSG_LONGPRESS_TIMEOUT:&&
&&&&&&&&&&&&&&&&&&&&if&(!mLaunched)&{&&
&&&&&&&&&&&&&&&&&&&&&&&&Context&context&=&(Context)msg.&&
&&&&&&&&&&&&&&&&&&&&&&&&Intent&i&=&new&Intent();&&
&&&&&&&&&&&&&&&&&&&&&&&&i.putExtra("autoshuffle",&"true");&&
&&&&&&&&&&&&&&&&&&&&&&&&i.setClass(context,&MusicBrowserActivity.class);&&
&&&&&&&&&&&&&&&&&&&&&&&&i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK&|&Intent.FLAG_ACTIVITY_CLEAR_TOP);&&
&&&&&&&&&&&&&&&&&&&&&&&&context.startActivity(i);&&
&&&&&&&&&&&&&&&&&&&&&&&&mLaunched&=&true;&&
&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&}&&
&&&&&&&&}&&
private static Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_LONGPRESS_TIMEOUT:
if (!mLaunched) {
Context context = (Context)msg.
Intent i = new Intent();
i.putExtra("autoshuffle", "true");
i.setClass(context, MusicBrowserActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(i);
mLaunched =
长按耳机后就启动MusicBrowserActivity.java这个音乐播放类。并且传入参数“autoshuffle==true”,这个启动和launcher的启动相似,也是启动一个新的任务task,但是这个后面的标志有不同的地方Intent.FLAG_ACTIVITY_CLEAR_TOP。
到这为止就是实现了在任何界面长按耳机键都能进入到music的主界面。
&&&&& 总结如下:
&&&&& 其实启动的时候,要注意当前activity的launcherMode是什么,如果是SingleTask,就要小心一下。比如说:想要长按耳机键,进入到launcher的Mainmenu界面,这时候如果单纯的用以上方法套,返回键点击的时候不会回到上个activity中,会有问题。因为launcher是一直启动的运行于每个task之中的,你再次启动Launcher的时候,无论是否设置属性“i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)”,都会把前一个activity给finish掉,launcher会在栈顶也是栈底。因为launcher的launcherMode=singleTask。我们可以做个实验;
&&&&三、例子写两个app,一个属性为singletask,一个为standard。应singletask的启动standard的activity,然后在再次基础上启动singletask的activity,看standard的activity是否会destory掉。
&&&&step1:先看截图:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&launchMode="singleTask"&&&&&&&&&&&&&&&&&&&&&&launchMode="standard"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&& &
&&&&&&&& Step 2:先启动launchMode="singleTask"的activity---->点击调用第二个App2的launchMode="standard"---->
点击按钮调用第一个App1的launchMode="singleTask"---->点击返回键。看log分析:
&&&&&&(1)点击启动launchMode="singleTask"的activity的log如下:
& (2)点击调用第二个App2的launchMode="standard"的activity的log如下图:&&&&&&&&&
&& &(3)点击调用第一个App1launchMode="singleTask"的activity的log如下:&&&&&&& 分析如下:看到这时候App2Activity--22已经执行了onStop()和onDestroy()方法了。验证了我以上的说法。
&&& (4)点击返回键---->直接回到了launcher界面。log如下:
&&&&&& 备注:要想解决以上问题也是可以的。就是在以上第(2)步:点击调用第二个App2的launchMode="standard"的activity的时候设置flag。Intent.FLAG_ACTIVITY_NEW_TASK。就可以解决以上问题了,每次启动一个新的任务,这样就能返回到App2Activity了。
&&&&&& (1)点击启动launchMode="singleTask"的activity的log如下:
&&& (2)点击调用第二个App2的launchMode="standard"的activity的log如下图:&&&
&&& &(3)点击调用第一个App1launchMode="singleTask"的activity的log如下:
&&&&& 看到如上图:App2Activity--22--->只是onStop()了,没有onDestroy掉。
&&&& (4)点击返回键---->直接回到了launcher界面---->log如下:
&& (5)通过log,我们可以看出返回到App2Activity了,我们再次点击返回键,--->返回到Launcher界面的log如下:
&&&& 通过以上验证说明我的结论是正确的。launcherMode一直是android的核心技术,通过这次我会更加注意到activity的LauncherMode的。
&&& 欢迎各界人士留言,讨论,拍砖!转载请标明出处!
阅读(8272) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
请登录后评论。}

我要回帖

更多关于 press home to unlock 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信