欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android6.0 屏幕固定功能詳解

 更新時(shí)間:2016年09月19日 11:10:32   作者:kc專欄  
android6.0在設(shè)置->安全->屏幕固定開啟后,然后再長(zhǎng)按home鍵出現(xiàn)最近的幾個(gè)Activity可以選擇一個(gè)圖釘按鈕就開啟了屏幕固定功能。這篇文章主要介紹了Android6.0 屏幕固定功能的相關(guān)資料,感興趣的朋友一起看看吧

可能大家看到這個(gè)標(biāo)題不知道是什么東西,我先說明下,android6.0在設(shè)置->安全->屏幕固定開啟后,然后再長(zhǎng)按home鍵出現(xiàn)最近的幾個(gè)Activity可以選擇一個(gè)圖釘按鈕就開啟了屏幕固定功能。

屏幕固定開啟后,屏幕只能固定在設(shè)定的Task上的Activity切換。

一、設(shè)置固定屏幕

我們先來看SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java的代碼,這段代碼就是長(zhǎng)按home鍵出現(xiàn)幾個(gè)Activity,然后按了圖釘?shù)哪莻€(gè)按鈕。在這里直接調(diào)用了AMS的startLockTaskModeOnCurrent函數(shù)。

@Override 
public void onClick(View v) { 
if (v.getId() == R.id.screen_pinning_ok_button || mRequestWindow == v) { 
try { 
ActivityManagerNative.getDefault().startLockTaskModeOnCurrent(); 
} catch (RemoteException e) {} 
} 
clearPrompt(); 
}

我們來看AMS的startLockTaskModeOnCurrent函數(shù),先調(diào)用ActivityStackSupervisor的topRunningActivityLocked獲取最前面的Activity,然后調(diào)用startLockTaskModeLocked函數(shù),參數(shù)是TaskRecord。

public void startLockTaskModeOnCurrent() throws RemoteException { 
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, 
"startLockTaskModeOnCurrent"); 
long ident = Binder.clearCallingIdentity(); 
try { 
synchronized (this) { 
ActivityRecord r = mStackSupervisor.topRunningActivityLocked(); 
if (r != null) { 
startLockTaskModeLocked(r.task); 
} 
} 
} finally { 
Binder.restoreCallingIdentity(ident); 
} 
}

我們?cè)賮砜磘opRunningActivityLocked函數(shù),先從mFocusedStack中獲取最前面的Activity。如果沒有再遍歷所有的mStacks獲取。

ActivityRecord topRunningActivityLocked() { 
final ActivityStack focusedStack = mFocusedStack; 
ActivityRecord r = focusedStack.topRunningActivityLocked(null); 
if (r != null) { 
return r; 
} 
// Return to the home stack. 
final ArrayList<ActivityStack> stacks = mHomeStack.mStacks; 
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { 
final ActivityStack stack = stacks.get(stackNdx); 
if (stack != focusedStack && isFrontStack(stack)) { 
r = stack.topRunningActivityLocked(null); 
if (r != null) { 
return r; 
} 
} 
} 
return null; 
}

在startLockTaskModeLocked函數(shù)中主要是調(diào)用了ActivityStackSupervisor的setLockTaskModeLocked函數(shù),下面我們來看這個(gè)函數(shù),我們的task不為null,第一次mLockTaskModeTasks為空,會(huì)發(fā)送一個(gè)LOCK_TASK_START_MSG消息

void setLockTaskModeLocked(TaskRecord task, int lockTaskModeState, String reason, 
boolean andResume) { 
if (task == null) { 
// Take out of lock task mode if necessary 
final TaskRecord lockedTask = getLockedTaskLocked(); 
if (lockedTask != null) { 
removeLockedTaskLocked(lockedTask); 
if (!mLockTaskModeTasks.isEmpty()) { 
// There are locked tasks remaining, can only finish this task, not unlock it. 
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, 
"setLockTaskModeLocked: Tasks remaining, can't unlock"); 
lockedTask.performClearTaskLocked(); 
resumeTopActivitiesLocked(); 
return; 
} 
} 
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, 
"setLockTaskModeLocked: No tasks to unlock. Callers=" + Debug.getCallers(4)); 
return; 
} 
// Should have already been checked, but do it again. 
if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) { 
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, 
"setLockTaskModeLocked: Can't lock due to auth"); 
return; 
} 
if (isLockTaskModeViolation(task)) { 
Slog.e(TAG_LOCKTASK, "setLockTaskMode: Attempt to start an unauthorized lock task."); 
return; 
} 
if (mLockTaskModeTasks.isEmpty()) { 
// First locktask. 
final Message lockTaskMsg = Message.obtain(); 
lockTaskMsg.obj = task.intent.getComponent().getPackageName(); 
lockTaskMsg.arg1 = task.userId; 
lockTaskMsg.what = LOCK_TASK_START_MSG;//發(fā)送消息 
lockTaskMsg.arg2 = lockTaskModeState; 
mHandler.sendMessage(lockTaskMsg); 
} 
// Add it or move it to the top. 
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "setLockTaskModeLocked: Locking to " + task + 
" Callers=" + Debug.getCallers(4)); 
mLockTaskModeTasks.remove(task); 
mLockTaskModeTasks.add(task);//加入到mLockModeTasks中 
if (task.mLockTaskUid == -1) { 
task.mLockTaskUid = task.effectiveUid; 
} 
if (andResume) { 
findTaskToMoveToFrontLocked(task, 0, null, reason);//把task放最前面 
resumeTopActivitiesLocked();//顯示新的Activity 
} 
}

我們?cè)賮砜聪⑻幚?,在消息處理中主要調(diào)用了WMS的disableKeyguard函數(shù)。

case LOCK_TASK_START_MSG: { 
// When lock task starts, we disable the status bars. 
try { 
if (mLockTaskNotify == null) { 
mLockTaskNotify = new LockTaskNotify(mService.mContext); 
} 
mLockTaskNotify.show(true); 
mLockTaskModeState = msg.arg2; 
if (getStatusBarService() != null) { 
int flags = 0; 
if (mLockTaskModeState == LOCK_TASK_MODE_LOCKED) { 
flags = StatusBarManager.DISABLE_MASK 
& (~StatusBarManager.DISABLE_BACK); 
} else if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) { 
flags = StatusBarManager.DISABLE_MASK 
& (~StatusBarManager.DISABLE_BACK) 
& (~StatusBarManager.DISABLE_HOME) 
& (~StatusBarManager.DISABLE_RECENT); 
} 
getStatusBarService().disable(flags, mToken, 
mService.mContext.getPackageName()); 
} 
mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG); 
if (getDevicePolicyManager() != null) { 
getDevicePolicyManager().notifyLockTaskModeChanged(true, 
(String)msg.obj, msg.arg1); 
} 
} catch (RemoteException ex) { 
throw new RuntimeException(ex); 
} 
} break;

二、固定屏幕后Activity啟動(dòng)流程

在固定屏幕后,如果我們啟動(dòng)其他TaskRecord的Activity是不能啟動(dòng)的,我們來看下這個(gè)原理。在startActivityUncheckedLocked函數(shù)中會(huì)調(diào)用isLockTaskModeViolation函數(shù)來判斷是否進(jìn)一步的Activity的啟動(dòng)流程,我們來看下這個(gè)函數(shù),調(diào)用getLockedTaskLocked來看mLockTaskModeTasks(就是鎖定屏幕的那些Task),如果當(dāng)前的task就是當(dāng)前正在固定屏幕的task,直接return false就是可以繼續(xù)啟動(dòng)Activity的流程,而如果不是,我們需要看task的mLockTaskAuth變量。

boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) { 
if (getLockedTaskLocked() == task && !isNewClearTask) { 
return false; 
} 
final int lockTaskAuth = task.mLockTaskAuth; 
switch (lockTaskAuth) { 
case LOCK_TASK_AUTH_DONT_LOCK: 
return !mLockTaskModeTasks.isEmpty(); 
case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: 
case LOCK_TASK_AUTH_LAUNCHABLE: 
case LOCK_TASK_AUTH_WHITELISTED: 
return false; 
case LOCK_TASK_AUTH_PINNABLE: 
// Pinnable tasks can't be launched on top of locktask tasks. 
return !mLockTaskModeTasks.isEmpty(); 
default: 
Slog.w(TAG, "isLockTaskModeViolation: invalid lockTaskAuth value=" + lockTaskAuth); 
return true; 
} 
}

我們?cè)賮砜碩askRecord的setLockedTaskAuth函數(shù),在新建一個(gè)TaskRecord的時(shí)候會(huì)調(diào)用setIntent函數(shù),而setIntent函數(shù)又是在TaskRecord的構(gòu)造函數(shù)中調(diào)用的。我們來看這個(gè)函數(shù)mLockTaskAuth的值是根據(jù)mLockTaskMode來定的,而mLockTaskMode又是ActivityInfo傳入的,這個(gè)值是在PKMS解析AndroidManifest.xml的時(shí)候構(gòu)造的,默認(rèn)就是LOCK_TASK_LAUNCH_MODE_DEFAULT,而當(dāng)沒有白名單mLockTaskAuth最后就是LOCK_TASK_AUTH_PINNABLE。

void setLockTaskAuth() { 
if (!mPrivileged && 
(mLockTaskMode == LOCK_TASK_LAUNCH_MODE_ALWAYS || 
mLockTaskMode == LOCK_TASK_LAUNCH_MODE_NEVER)) { 
// Non-priv apps are not allowed to use always or never, fall back to default 
mLockTaskMode = LOCK_TASK_LAUNCH_MODE_DEFAULT; 
} 
switch (mLockTaskMode) { 
case LOCK_TASK_LAUNCH_MODE_DEFAULT: 
mLockTaskAuth = isLockTaskWhitelistedLocked() ? 
LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE; 
break; 
case LOCK_TASK_LAUNCH_MODE_NEVER: 
mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK; 
break; 
case LOCK_TASK_LAUNCH_MODE_ALWAYS: 
mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV; 
break; 
case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED: 
mLockTaskAuth = isLockTaskWhitelistedLocked() ? 
LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE; 
break; 
} 
if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this + 
" mLockTaskAuth=" + lockTaskAuthToString()); 
}

我們?cè)賮砜磇sLockTaskModeViolation函數(shù)如下代碼,現(xiàn)在是task的mLockTaskAuth 是LOCK_TASK_AUTH_PINNABLE,而當(dāng)前處于固定屏幕,所以mLockTaskModeTasks不為null,最后返回true。那Activity啟動(dòng)流程就不能走下去了,那就是代表啟動(dòng)普通的Activity會(huì)被阻止。

case LOCK_TASK_AUTH_PINNABLE: 
// Pinnable tasks can't be launched on top of locktask tasks. 
return !mLockTaskModeTasks.isEmpty();

三、取消固定屏幕

最后我們?cè)賮砜纯慈∠潭ㄆ聊?,取消屏幕?huì)在PhoneStatusBar中取消,但是一定是要有虛擬鍵,原生就是這么設(shè)定的。最后調(diào)用了AMS的stopLockTaskModeOnCurrent函數(shù)。這個(gè)函數(shù)主要是調(diào)用了stopLockTaskMode函數(shù),這個(gè)函數(shù)中主要是調(diào)用了ActivityStackSupervisor的setLockTaskModeLocked函數(shù),之前在固定屏幕時(shí)也是調(diào)用了這個(gè)函數(shù),但是這里我們仔細(xì)看,其第一個(gè)參數(shù)為null。

public void stopLockTaskMode() { 
final TaskRecord lockTask = mStackSupervisor.getLockedTaskLocked(); 
if (lockTask == null) { 
// Our work here is done. 
return; 
} 
final int callingUid = Binder.getCallingUid(); 
final int lockTaskUid = lockTask.mLockTaskUid; 
// Ensure the same caller for startLockTaskMode and stopLockTaskMode. 
// It is possible lockTaskMode was started by the system process because 
// android:lockTaskMode is set to a locking value in the application manifest instead of 
// the app calling startLockTaskMode. In this case {@link TaskRecord.mLockTaskUid} will 
// be 0, so we compare the callingUid to the {@link TaskRecord.effectiveUid} instead. 
if (getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_LOCKED && 
callingUid != lockTaskUid 
&& (lockTaskUid != 0 
|| (lockTaskUid == 0 && callingUid != lockTask.effectiveUid))) { 
throw new SecurityException("Invalid uid, expected " + lockTaskUid 
+ " callingUid=" + callingUid + " effectiveUid=" + lockTask.effectiveUid); 
} 
long ident = Binder.clearCallingIdentity(); 
try { 
Log.d(TAG, "stopLockTaskMode"); 
// Stop lock task 
synchronized (this) { 
mStackSupervisor.setLockTaskModeLocked(null, ActivityManager.LOCK_TASK_MODE_NONE, 
"stopLockTask", true); 
} 
} finally { 
Binder.restoreCallingIdentity(ident); 
} 
}

我們來看下這個(gè)函數(shù),如果為空,現(xiàn)在調(diào)用getLockedTaskLocked獲取當(dāng)前固定屏幕的TaskRecord,然后調(diào)用removeLockedTaskLocked去除這個(gè)TaskRecord,如果還不為null,調(diào)用resumeTopActivitiesLocked啟動(dòng)下個(gè)Activity(一般也就是下個(gè)屏幕鎖定的TaskRecord的Activity)。

如果為空了,直接返回。但是在我們下次啟動(dòng)普通的Activity的時(shí)候就恢復(fù)正常了,因?yàn)閙LockTaskModeTasks已經(jīng)為空了。

void setLockTaskModeLocked(TaskRecord task, int lockTaskModeState, String reason, 
boolean andResume) { 
if (task == null) { 
// Take out of lock task mode if necessary 
final TaskRecord lockedTask = getLockedTaskLocked(); 
if (lockedTask != null) { 
removeLockedTaskLocked(lockedTask); 
if (!mLockTaskModeTasks.isEmpty()) { 
// There are locked tasks remaining, can only finish this task, not unlock it. 
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, 
"setLockTaskModeLocked: Tasks remaining, can't unlock"); 
lockedTask.performClearTaskLocked(); 
resumeTopActivitiesLocked(); 
return; 
} 
} 
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, 
"setLockTaskModeLocked: No tasks to unlock. Callers=" + Debug.getCallers(4)); 
return; 
}

四、沒有虛擬鍵如何取消屏幕固定

前面說過如果沒有虛擬鍵就不能取消屏幕固定了,我們說下幾種方式

1.使用am命令 am task lock stop可以調(diào)用am的stopLockTaskMode函數(shù)

2.另一種我們可以在Activity.java中修改代碼,比較長(zhǎng)按返回鍵調(diào)用AMS的stopLockTaskMode方法,下面就是實(shí)現(xiàn),Activity本身提供了stopLockTask就是調(diào)用了AMS的stopLockTaskMode方法

public boolean onKeyLongPress(int keyCode, KeyEvent event) { 
if (keyCode == KeyEvent.KEYCODE_BACK) { 
stopLockTask(); 
} 
return false; 
}

以上所述是小編給大家介紹的Android6.0 屏幕固定功能詳解,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • Android開發(fā)DataBinding基礎(chǔ)使用

    Android開發(fā)DataBinding基礎(chǔ)使用

    這篇文章主要為大家介紹了Android開發(fā)DataBinding基礎(chǔ)使用實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • Android 實(shí)現(xiàn)帶進(jìn)度條的WebView的實(shí)例

    Android 實(shí)現(xiàn)帶進(jìn)度條的WebView的實(shí)例

    這篇文章主要介紹了Android 實(shí)現(xiàn)帶進(jìn)度條的WebView的實(shí)例的相關(guān)資料,這里介紹了Webview加載網(wǎng)頁的方法及帶進(jìn)度的Drawable文件view_progress_webview的實(shí)現(xiàn),需要的朋友可以參考下
    2017-07-07
  • Android顯示網(wǎng)絡(luò)圖片實(shí)例

    Android顯示網(wǎng)絡(luò)圖片實(shí)例

    這篇文章主要介紹了Android顯示網(wǎng)絡(luò)圖片的方法,以實(shí)例形式展示了Android程序顯示網(wǎng)絡(luò)圖片的方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2014-10-10
  • Android 邊播邊緩存的實(shí)現(xiàn)(MP4 未加密m3u8)

    Android 邊播邊緩存的實(shí)現(xiàn)(MP4 未加密m3u8)

    這篇文章主要介紹了Android 邊播邊緩存的實(shí)現(xiàn)(MP4 未加密m3u8),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Android使用Intent發(fā)送短信的實(shí)現(xiàn)方法

    Android使用Intent發(fā)送短信的實(shí)現(xiàn)方法

    這篇文章主要介紹了Android使用Intent發(fā)送短信的實(shí)現(xiàn)方法,結(jié)合簡(jiǎn)單實(shí)例形式分析了Android短信發(fā)送功能的實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-07-07
  • Android自定義ScrollView實(shí)現(xiàn)阻尼回彈

    Android自定義ScrollView實(shí)現(xiàn)阻尼回彈

    這篇文章主要為大家詳細(xì)介紹了Android自定義ScrollView實(shí)現(xiàn)阻尼回彈,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Android 關(guān)于“NetworkOnMainThreadException”問題的原因分析及解決辦法

    Android 關(guān)于“NetworkOnMainThreadException”問題的原因分析及解決辦法

    這篇文章主要介紹了Android 關(guān)于“NetworkOnMainThreadException”的相關(guān)知識(shí),本文介紹的非常詳細(xì),具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧
    2016-02-02
  • Android DigitalClock組件用法實(shí)例

    Android DigitalClock組件用法實(shí)例

    這篇文章主要介紹了Android DigitalClock組件用法,結(jié)合實(shí)例形式分析了DigitalClock組件的布局調(diào)用技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下
    2016-01-01
  • Flutter 構(gòu)建一個(gè)常用的頁面框架

    Flutter 構(gòu)建一個(gè)常用的頁面框架

    大多數(shù) App 中都會(huì)有底部導(dǎo)航欄,通過底部導(dǎo)航欄切換實(shí)現(xiàn)不同頁面之間的切換。在Flutter 中提供了 BottomNavigationBar組件實(shí)現(xiàn)底部導(dǎo)航。本篇介紹通過 BottomNavigationBar和 IndexedStack構(gòu)建最為常見的 App 頁面框架。
    2021-05-05
  • Android實(shí)現(xiàn)無標(biāo)題欄全屏的方法

    Android實(shí)現(xiàn)無標(biāo)題欄全屏的方法

    這篇文章主要介紹了Android實(shí)現(xiàn)無標(biāo)題欄全屏的三種方法,感興趣的小伙伴們可以參考一下
    2016-07-07

最新評(píng)論