[Android] Android 鎖屏實現與總結 (一)


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

 

實例演示圖片如下:

Android 鎖屏實現

 

系列文章鏈接如下:

[Android] Android 鎖屏實現與總結 (一)

[Android] Android 鎖屏實現與總結 (二)

[Android] Android 鎖屏實現與總結 (三)

代碼文件地址:

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

轉載請著名出處!謝謝~~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM