• [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

    转载请著名出处!谢谢~~

  • 相关阅读:
    问题大全
    redis学习笔记-03:redis安装
    redis学习笔记-02:为什么使用NoSQL数据库
    redis学习笔记-01:redis简介
    docker学习笔记-05:Docker安装mysql和redis
    docker学习笔记-06:自定义DockerFile生成镜像
    docker学习笔记-05:DockerFile解析
    全栈之路-杂篇-JPA多对多配置分析
    全栈之路-小程序API-JWT令牌详细剖析与使用
    全栈之路-小程序API-Json数据类型的序列化与反序列化
  • 原文地址:https://www.cnblogs.com/wukong1688/p/10716875.html
Copyright © 2020-2023  润新知