實現鎖屏的方式有多種(鎖屏應用、懸浮窗、普通Activity偽造鎖屏等等)。但國內比較主流並且被廣泛應用的Activity偽造鎖屏方式。
實例演示圖片如下:

系列文章鏈接如下:
代碼文件地址:
https://github.com/wukong1688/Android-BaseLockScreen
1、廣播注冊
2、Activity設置
3、按鍵的屏蔽
4、滑屏解鎖
Activity實現自定義鎖屏頁的思路很簡單,即在聽書模式開啟時,啟動一個service,在service中監聽系統SCREEN_OFF的廣播。當屏幕熄滅時service監聽到廣播,開啟一個鎖屏頁Activity在屏幕最上層顯示,該Activity創建的同時會去掉系統的鎖屏(如果有密碼是禁不掉的)。示意圖如下:
二、重要實現
1、廣播注冊
<service android:name=".service.LockScreenService" android:enabled="true" android:exported="true" />
注意:SCREEN_OFF廣播監聽必須是 動態注冊 的,如果在AndroidManifest.xml中靜態注冊將無法接收到SCREEN_OFF廣播。
LockScreenService.java
詳細代碼如下:
package com.jack.applockscreen.service; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.content.IntentFilter; import android.graphics.BitmapFactory; import android.os.IBinder; import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; import android.widget.Toast; import com.jack.applockscreen.R; import com.jack.applockscreen.activity.DetailActivity; import com.jack.applockscreen.activity.LockScreenActivity; import com.jack.applockscreen.receiver.LockScreenReceiver; public class LockScreenService extends Service { private LockScreenReceiver mReceiver; private IntentFilter mIntentFilter = new IntentFilter(); private boolean isNotiShow = false; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { //動態注冊 mIntentFilter.addAction(Intent.ACTION_BOOT_COMPLETED); mIntentFilter.addAction(Intent.ACTION_SCREEN_OFF); mIntentFilter.addAction(Intent.ACTION_SCREEN_ON); mIntentFilter.addAction(Intent.ACTION_TIME_TICK); mIntentFilter.setPriority(Integer.MAX_VALUE); if (null == mReceiver) { mReceiver = new LockScreenReceiver(); mIntentFilter.setPriority(Integer.MAX_VALUE); registerReceiver(mReceiver, mIntentFilter); buildNotification(); Toast.makeText(getApplicationContext(), "開啟成功", Toast.LENGTH_LONG).show(); } return START_STICKY; } /** * 通知欄顯示 */ private void buildNotification() { if (!isNotiShow){ //避免多次顯示 NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); Intent intent = new Intent(this, DetailActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); Notification notification = new NotificationCompat.Builder(this, "default") .setTicker("APP正在運行") .setAutoCancel(false) .setContentTitle("APP正在運行") .setContentText("運行中") .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) .setSmallIcon(R.mipmap.ic_launcher) .setContentIntent(pendingIntent) .build(); manager.notify(1, notification); startForeground(0x11, notification); isNotiShow = true; } } @Override public void onDestroy() { if (mReceiver != null) { unregisterReceiver(mReceiver); mReceiver = null; } super.onDestroy(); } }
廣播接收 LockScreenReceiver.java
package com.jack.applockscreen.receiver; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.telecom.TelecomManager; import android.telephony.TelephonyManager; import com.jack.applockscreen.activity.LockScreenActivity; import com.jack.applockscreen.util.Parser; public class LockScreenReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (Intent.ACTION_SCREEN_OFF.equals(action)) { if (Parser.sPhoneCallState == TelephonyManager.CALL_STATE_IDLE) { // 手機狀態為未來電的空閑狀態 // 判斷鎖屏界面是否已存在,如果已存在就先finish,防止多個鎖屏出現 if (!Parser.KEY_GUARD_INSTANCES.isEmpty()) { for (Activity activity : Parser.KEY_GUARD_INSTANCES) { activity.finish(); } } Intent lockScreen = new Intent(context, LockScreenActivity.class); lockScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); context.startActivity(lockScreen); } } else { Parser.killBackgroundProcess(context); } } }
注意:
1) 標志位FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS,是為了避免在最近使用程序列表出現Service所啟動的Activity。
2) 啟動Activity時Intent的Flag,如果不添加
FLAG_ACTIVITY_NEW_TASK的標志位,會出現“Calling startActivity() from outside of an Activity”的運行時異常,因為我們是從Service啟動的Activity。Activity要存在於activity的棧中,而Service在啟動activity時必然不存在一個activity的棧,所以要新起一個棧,並裝入啟動的activity。使用該標志位時,也需要在AndroidManifest中聲明taskAffinity,即新task的名稱,否則鎖屏Activity實質上還是在建立在原來App的task棧中。
下接:
本博客地址: wukong1688
本文原文地址:https://www.cnblogs.com/wukong1688/p/10716875.html
轉載請著名出處!謝謝~~
