編輯:關於Android編程
看網上,大家對Home和長按Home鍵的監聽,都有相應的監聽方法,但是對於長按Menu鍵的監聽,沒有比較詳細的資料,我把我的一個在launcher界面來監聽長按Menu鍵的一個實現和大家探討一下:
我要實現的功能是在launcher界面,當用戶長按Menu鍵,來執行一個XXXXXX操作。
1.修改源碼:PhoneWindowManager.java---------frameworks\base\policy\src\com\android\internal\policy\impl
(1) 定義一個長按Menu鍵的標識位
[java]
//konka hexiaoming 20130409 start
boolean mMenuKeyLongPressed = false;
//konka hexiaoming 20130409 end
//konka hexiaoming 20130409 start
boolean mMenuKeyLongPressed = false;
//konka hexiaoming 20130409 end (2)重點修改interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags)方法:
在launcher界面長按Menu,發出廣播:android.intent.action.LONG_PRESS_MENU_KEY
[java] view plaincopyprint?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;
//konka hexiaoming 20130409 start
final boolean up = event.getAction() == KeyEvent.ACTION_UP;
//konka hexiaoming 20130409 end
final boolean canceled = event.isCanceled();
Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
+ repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
+ " canceled=" + canceled);
// 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 (mScreenshotChordEnabled && (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 - now;
}
}
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
&& mVolumeDownKeyConsumedByScreenshotChord) {
if (!down) {
mVolumeDownKeyConsumedByScreenshotChord = false;
}
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) {
/// M: [ALPS00054781]Dispatch the home key to the application @{
if (win != null && win.getAttrs() != null) {
final int flag = win.getAttrs().flags;
if ((flag & WindowManager.LayoutParams.FLAG_HOMEKEY_DISPATCHED) != 0) {
// the window wants to handle the home key, so dispatch it to it.
return 0;
}
}
/// @}
// 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 (!down) {
final boolean homeWasLongPressed = mHomeLongPressed;
mHomePressed = false;
mHomeLongPressed = false;
if (!homeWasLongPressed) {
if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
try {
IStatusBarService statusbar = getStatusBarService();
if (statusbar != null) {
statusbar.cancelPreloadRecentApps();
}
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException when showing recent apps", e);
// re-acquire status bar service next time it is needed.
mStatusBarService = null;
}
}
mHomePressed = false;
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 = 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 {
/// M:[AppLaunchTime] Improve the mechanism of AppLaunchTime
if (mAppLaunchTimeEnabled) Slog.i(TAG, "[AppLaunch] Home key pressed");
launchHomeFromHotKey();
}
} else {
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() : null;
if (attrs != null) {
final int type = attrs.type;
if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
|| type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
// the "app" is keyguard, so give it the key
return 0;
}
final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
for (int i=0; i<typeCount; 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 (!mHomePressed && mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
try {
IStatusBarService statusbar = getStatusBarService();
if (statusbar != null) {
statusbar.preloadRecentApps();
}
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException when preloading recent apps", e);
// re-acquire status bar service next time it is needed.
mStatusBarService = null;
}
}
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) {
// Hijack modified menu keys for debugging features
final int chordBug = KeyEvent.META_SHIFT_ON;
//konka hexiaoming 20130409 start
if(repeatCount == 3){
mMenuKeyLongPressed = true;
}
Log.i("hexiaoming_debug", "repeatCount:"+repeatCount);
Log.i("hexiaoming_debug", "mMenuKeyLongPressed:"+mMenuKeyLongPressed);
/**is launcher UI*************/
boolean isLauncherUI = false;
List<String> homePackageNames = new ArrayList<String>(); //桌面應用列表
PackageManager packageManager = mContext.getPackageManager();
//屬性
Intent intentL = new Intent(Intent.ACTION_MAIN);
intentL.addCategory(Intent.CATEGORY_HOME);
List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intentL,PackageManager.MATCH_DEFAULT_ONLY);
for(ResolveInfo ri : resolveInfo){
homePackageNames.add(ri.activityInfo.packageName);
}
ActivityManager mActivityManager = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);
isLauncherUI = homePackageNames.contains(rti.get(0).topActivity.getPackageName());
Log.i("hexiaoming_debug", "isLauncherUI:"+isLauncherUI);
Log.i("hexiaoming_debug", "down:"+down);
Log.i("hexiaoming_debug", "up:"+up);
//if(up && mMenuKeyLongPressed){
if(down && mMenuKeyLongPressed && isLauncherUI){
Log.i("hexiaoming_debug", "long press key:MENU");
Intent menuLongPress = new Intent();
menuLongPress.setAction("android.intent.action.LONG_PRESS_MENU_KEY");
mContext.sendBroadcast(menuLongPress);
mMenuKeyLongPressed = false;
return -1;
}else{
if (down && repeatCount == 0) {
//if (up && repeatCount == 0) {
//konka hexiaoming 20130409 end
Log.i("hexiaoming_debug", "press key:MENU");
if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
null, null, null, 0, null, null);
return -1;
} else if (SHOW_PROCESSES_ON_ALT_MENU &&
(metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
Intent service = new Intent();
service.setClassName(mContext, "com.android.server.LoadAverageService");
ContentResolver res = mContext.getContentResolver();
boolean shown = Settings.Global.getInt(
res, Settings.Global.SHOW_PROCESSES, 0) != 0;
if (!shown) {
mContext.startService(service);
} else {
mContext.stopService(service);
}
Settings.Global.putInt(
res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1);
return -1;
}
}
//konka hexiaoming 20130410 start
}
//konka hexiaoming 20130409 end
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;
//konka hexiaoming 20130409 start
final boolean up = event.getAction() == KeyEvent.ACTION_UP;
//konka hexiaoming 20130409 end
final boolean canceled = event.isCanceled();
Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
+ repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
+ " canceled=" + canceled);
// 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 (mScreenshotChordEnabled && (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 - now;
}
}
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
&& mVolumeDownKeyConsumedByScreenshotChord) {
if (!down) {
mVolumeDownKeyConsumedByScreenshotChord = false;
}
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) {
/// M: [ALPS00054781]Dispatch the home key to the application @{
if (win != null && win.getAttrs() != null) {
final int flag = win.getAttrs().flags;
if ((flag & WindowManager.LayoutParams.FLAG_HOMEKEY_DISPATCHED) != 0) {
// the window wants to handle the home key, so dispatch it to it.
return 0;
}
}
/// @}
// 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 (!down) {
final boolean homeWasLongPressed = mHomeLongPressed;
mHomePressed = false;
mHomeLongPressed = false;
if (!homeWasLongPressed) {
if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
try {
IStatusBarService statusbar = getStatusBarService();
if (statusbar != null) {
statusbar.cancelPreloadRecentApps();
}
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException when showing recent apps", e);
// re-acquire status bar service next time it is needed.
mStatusBarService = null;
}
}
mHomePressed = false;
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 = 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 {
/// M:[AppLaunchTime] Improve the mechanism of AppLaunchTime
if (mAppLaunchTimeEnabled) Slog.i(TAG, "[AppLaunch] Home key pressed");
launchHomeFromHotKey();
}
} else {
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() : null;
if (attrs != null) {
final int type = attrs.type;
if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
|| type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
// the "app" is keyguard, so give it the key
return 0;
}
final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
for (int i=0; i<typeCount; 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 (!mHomePressed && mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
try {
IStatusBarService statusbar = getStatusBarService();
if (statusbar != null) {
statusbar.preloadRecentApps();
}
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException when preloading recent apps", e);
// re-acquire status bar service next time it is needed.
mStatusBarService = null;
}
}
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) {
// Hijack modified menu keys for debugging features
final int chordBug = KeyEvent.META_SHIFT_ON;
//konka hexiaoming 20130409 start
if(repeatCount == 3){
mMenuKeyLongPressed = true;
}
Log.i("hexiaoming_debug", "repeatCount:"+repeatCount);
Log.i("hexiaoming_debug", "mMenuKeyLongPressed:"+mMenuKeyLongPressed);
/**is launcher UI*************/
boolean isLauncherUI = false;
List<String> homePackageNames = new ArrayList<String>(); //桌面應用列表
PackageManager packageManager = mContext.getPackageManager();
//屬性
Intent intentL = new Intent(Intent.ACTION_MAIN);
intentL.addCategory(Intent.CATEGORY_HOME);
List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intentL,PackageManager.MATCH_DEFAULT_ONLY);
for(ResolveInfo ri : resolveInfo){
homePackageNames.add(ri.activityInfo.packageName);
}
ActivityManager mActivityManager = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);
isLauncherUI = homePackageNames.contains(rti.get(0).topActivity.getPackageName());
Log.i("hexiaoming_debug", "isLauncherUI:"+isLauncherUI);
Log.i("hexiaoming_debug", "down:"+down);
Log.i("hexiaoming_debug", "up:"+up);
//if(up && mMenuKeyLongPressed){
if(down && mMenuKeyLongPressed && isLauncherUI){
Log.i("hexiaoming_debug", "long press key:MENU");
Intent menuLongPress = new Intent();
menuLongPress.setAction("android.intent.action.LONG_PRESS_MENU_KEY");
mContext.sendBroadcast(menuLongPress);
mMenuKeyLongPressed = false;
return -1;
}else{
if (down && repeatCount == 0) {
//if (up && repeatCount == 0) {
//konka hexiaoming 20130409 end
Log.i("hexiaoming_debug", "press key:MENU");
if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
null, null, null, 0, null, null);
return -1;
} else if (SHOW_PROCESSES_ON_ALT_MENU &&
(metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
Intent service = new Intent();
service.setClassName(mContext, "com.android.server.LoadAverageService");
ContentResolver res = mContext.getContentResolver();
boolean shown = Settings.Global.getInt(
res, Settings.Global.SHOW_PROCESSES, 0) != 0;
if (!shown) {
mContext.startService(service);
} else {
mContext.stopService(service);
}
Settings.Global.putInt(
res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1);
return -1;
}
}
//konka hexiaoming 20130410 start
}
//konka hexiaoming 20130409 end
(3)定義一個廣播接收器,接收長按Menu的廣播,執行XXX操作
[java]
public class MenuKeyBroadcastReceiver extends BroadcastReceiver{
public final String INTENT_ACTION_LONG_PRESS_MENU_KEY = "android.intent.action.LONG_PRESS_MENU_KEY";
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
// Intent menuLongPress = new Intent();
// menuLongPress.setAction(INTENT_ACTION_LONG_PRESS_MENU_KEY);
// context.sendBroadcast(menuLongPress);
//long time = System.currentTimeMillis();
String action = intent.getAction();
/**is speech client wakeup**/
boolean isWakeUp = Settings.System.getInt(context.getContentResolver(), "SPEECH_WAKE", 0) == 1 ? true : false;
/**is launcher UI*************/
boolean isLauncherUI = false;
List<String> homePackageNames = new ArrayList<String>(); //桌面應用列表
PackageManager packageManager = context.getPackageManager();
//屬性
Intent intentL = new Intent(Intent.ACTION_MAIN);
intentL.addCategory(Intent.CATEGORY_HOME);
List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intentL,PackageManager.MATCH_DEFAULT_ONLY);
for(ResolveInfo ri : resolveInfo){
homePackageNames.add(ri.activityInfo.packageName);
}
ActivityManager mActivityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);
isLauncherUI = homePackageNames.contains(rti.get(0).topActivity.getPackageName());
if(isWakeUp == true && INTENT_ACTION_LONG_PRESS_MENU_KEY.equals(action) && isLauncherUI == true){
Intent intentOpenSpeechKShow = new Intent(context, SpeechKShow.class);
intentOpenSpeechKShow.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intentOpenSpeechKShow);
Log.i("hexiaoming_debug", "長按MENU鍵,在Launcher界面彈出康佳小兵");
}
}
}
public class MenuKeyBroadcastReceiver extends BroadcastReceiver{
public final String INTENT_ACTION_LONG_PRESS_MENU_KEY = "android.intent.action.LONG_PRESS_MENU_KEY";
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
// Intent menuLongPress = new Intent();
// menuLongPress.setAction(INTENT_ACTION_LONG_PRESS_MENU_KEY);
// context.sendBroadcast(menuLongPress);
//long time = System.currentTimeMillis();
String action = intent.getAction();
/**is speech client wakeup**/
boolean isWakeUp = Settings.System.getInt(context.getContentResolver(), "SPEECH_WAKE", 0) == 1 ? true : false;
/**is launcher UI*************/
boolean isLauncherUI = false;
List<String> homePackageNames = new ArrayList<String>(); //桌面應用列表
PackageManager packageManager = context.getPackageManager();
//屬性
Intent intentL = new Intent(Intent.ACTION_MAIN);
intentL.addCategory(Intent.CATEGORY_HOME);
List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intentL,PackageManager.MATCH_DEFAULT_ONLY);
for(ResolveInfo ri : resolveInfo){
homePackageNames.add(ri.activityInfo.packageName);
}
ActivityManager mActivityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);
isLauncherUI = homePackageNames.contains(rti.get(0).topActivity.getPackageName());
if(isWakeUp == true && INTENT_ACTION_LONG_PRESS_MENU_KEY.equals(action) && isLauncherUI == true){
Intent intentOpenSpeechKShow = new Intent(context, SpeechKShow.class);
intentOpenSpeechKShow.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intentOpenSpeechKShow);
Log.i("hexiaoming_debug", "長按MENU鍵,在Launcher界面彈出康佳小兵");
}
}
}
(4)注冊長按MENU鍵的廣播接收器
[java]
!-- konka-hexiaoming-Speech-20130408-start -->
<receiver
android:name=".menukeybroadcastreceiver.MenuKeyBroadcastReceiver">
intent-filter>
<action android:name="android.intent.action.LONG_PRESS_MENU_KEY"></action>
</intent-filter>
</receiver>
<!-- konka-hexiaoming-Speech-20130408-end -->
最近項目中需要用到ListView下拉刷新的功能,一開始想圖省事,在網上直接找一個現成的,可是嘗試了網上多個版本的下拉刷新之後發現效果都不怎麼理想。有些是因為功能不完整或
Android 實現微信,微博,微信朋友圈,QQ分享的功能一、去各自所在的開發者平台注冊相應的Key值;引入相關jar包、權限等二、ShareUtil工具類import
目錄:1.ListView概述2.ListView使用中的重要角色(Adapter,ViewHolder,數據集,布局)3.ListView常用屬性4.ListView+
原創博客地址:點擊傳送 AndroidResideMenu 先看看如何使用: 把項目源碼下載下來導入工程,可以看到 ResideMenu為引用工程,再看