Android锁屏实践+保活

简介: 本菜开源的一个自己写的Demo,希望能给Androider们有所帮助,水平有限,见谅见谅…https://github.com/zhiaixinyang/PersonalCollect(拆解GitHub上的优秀框架于一体,全部拆离不含任何额外的库导入)https://github.

本菜开源的一个自己写的Demo,希望能给Androider们有所帮助,水平有限,见谅见谅…

https://github.com/zhiaixinyang/PersonalCollect

(拆解GitHub上的优秀框架于一体,全部拆离不含任何额外的库导入)

https://github.com/zhiaixinyang/MyFirstApp

(Retrofit+RxJava+MVP)

写在前面

刚刚入职的时候,因为我在面试的时候去Service掌握并不好,组长就根据我所要加入的音乐组的项目给我讲了音乐后台Service相关的内容,并且以锁屏为例讲到了AIDL相关的内容。
因为AIDL涉及到不少的内容,所以,以我现在所掌握的理解的深度并不能够把这个东西梳理清楚。
所以这次的学习记录是针对锁屏这一模块。技术组本来要把锁屏模块重新构架一番,抽成公共组件,但是最近这几周由于要上线新的产品,所以就被放下了,不过不影响了解锁屏的原理,抽离只是思想上的东西,本质不会变。而且还可以在被抽离出来之后,再进行学习记录封装的思想,俩不耽误。


开始

思路

整体的思路还是比较清晰的:首先写一个用于展示锁屏内容的Activity,然后监听屏幕熄灭和亮起的事件,接到事件后start我们的锁屏Activity。当然里边还有一些体验上的细节要处理,比如:既然要让我们的锁屏显示,那么就要把系统的锁屏关闭。再比如:如果有密码锁,我们是否需要让锁屏先于密码锁展示。等等。


监听屏幕状态

这个很简单,我们只需要写一个BroadcastReceiver,除了onReceive()方法,比如下面的方式:


    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent == null) {
            return;
        }
        //清掉系统锁屏(还有其他方式)
        KeyguardManager keyguardManager = (KeyguardManager) context
                    .getSystemService(Context.KEYGUARD_SERVICE);
        KeyguardManager.KeyguardLock keyguardLock= keyguardManager 
                    .newKeyguardLock(context.getPackageName());
        keyguardManager.disableKeyguard();    
        //接收屏幕事件      
        if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
            LockScreenActivity.start(context);
        } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
            LockScreenActivity.start(context);
        }
    }

我们startActivity的时候,一般要把这个锁屏Activity放到一个全新的task中,以及一些Flags。


android:taskAffinity="xxxxxx"
android:autoRemoveFromRecents="true"
android:excludeFromRecents="true"

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Tips:

监听屏幕的广播,必须要动态注册。所以我们正常要启动一个服务去动态的registerReceiver()。既然提到服务,必然会涉及到保活,关于保活的问题将会在保活篇简单记录部分代码。

//注册广播接受者
IntentFilter filter = new IntentFilter();
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
registerReceiver(实例化自己的接受者, filter);


最上层显示Activity

可以在密码锁上面显示,当然肯定是不可能绕过密码锁的。


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //添加<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>  权限
        //去掉系统锁屏页
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
        //使Activity在锁屏时仍然能够显示
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
        setContentView(R.layout.activity_lock_screen);

    }

屏蔽物理键

屏蔽返回键,菜单键等操作。

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        int key = event.getKeyCode();
        switch (key) {
            case KeyEvent.KEYCODE_BACK: {
                return true;
            }
            case KeyEvent.KEYCODE_MENU:{
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }



当然我们的锁屏Activity肯定是需要滑动消失。
一般是自定义一个滑动控件, 可以参考我的GitHub锁屏篇


保活篇

思想

公司一直使用的方案是:在正常启动用于动态注册锁屏广播的的Service上再开启一个另一个Service,但是这个Service运行在其他进程中。并且这俩个Service在onServiceDisconnected()以及onDestroy()方法中进行互相的start。

具体代码

本进程的Service:


public class LocalCoreService extends Service {
    //省略AIDL部分
    private ServiceConnection mConnection;
    private Handler mHandler;

    public static void starter(@NonNull Context context) {
        Intent intent = new Intent(context, LocalCoreService.class);
        context.startService(intent);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //省略AIDL部分
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mConnection = new LocalConnection();
        mHandler = new Handler();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        bindRemoteService();
        KeyguardService.starter(this);
        return START_STICKY;
    }

    protected class LocalConnection implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    RemoteCoreService.starter(LocalCoreService.this);
                }
            }, 1000);
        }
    }

    private void restartKeyguardService() {
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                KeyguardService.starter(LocalCoreService.this);
            }
        }, 1000);
    }

    private void bindRemoteService() {
        bindService(new Intent(LocalCoreService.this, RemoteCoreService.class), mConnection, Context.BIND_IMPORTANT);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //解除对远程service的绑定
        unbindService(mConnection);
        RemoteCoreService.starter(this);
    }
}

另进程Service:


public class RemoteCoreService extends Service {
    //省略AIDL操作部分
    private ServiceConnection mConnections;
    private Handler mHandler;

    public static void starter(@NonNull Context context) {
        Intent intent = new Intent(context, RemoteCoreService.class);
        context.startService(intent);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //省略AIDL操作部分
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mBinder = new RemoteBinder();
        mConnections = new Connections();
        mHandler = new Handler();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        LocalCoreService.starter(RemoteCoreService.this);
        bindLocalService();
        KeyguardService.starter(this);
        return START_STICKY;
    }

    /**
     * 1s 后重启锁屏service
     */
    private void restartKeyguardService() {
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                KeyguardService.starter(RemoteCoreService.this);
            }
        }, 1000);
    }

    private class Connections implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    LocalCoreService.starter(RemoteCoreService.this);
                }
            }, 1000);
        }
    }

    protected void bindLocalService() {
        bindService(new Intent(this, LocalCoreService.class), mConnections, Context.BIND_IMPORTANT);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //解绑之前绑定的服务
        unbindService(mConnections);
        //通知local service 开启
        LocalCoreService.starter(this);
    }
}

尾声

以上的操作也仅仅是尽可能的保证Service存活,保证锁屏能够出来,但是国内手机商各种定制很难保证这些效果能够顺利的出来。
就行在我的手机上,网易云音乐的锁屏就没有我们App的稳定性高;但反过来在其他品牌的手机上或许是另一种情况。这种事谁又能说得准呢?

最后希望各位看官可以star我的GitHub,三叩九拜,满地打滚求star:
https://github.com/zhiaixinyang/PersonalCollect
https://github.com/zhiaixinyang/MyFirstApp

2018年7月2号,我正式开始了自己的Android工作,为了能够让自己能够好好完成工作,并且能够快速得到技术提升。所以打算以公众号的方式去敦促自己学习,我会把自己日常的学习笔记发布到公众号上,如果可以,共同进步!~


img_89788b3a8f3f86257453cbc8264959f6.png
个人公众号
目录
相关文章
|
25天前
|
调度 数据库 Android开发
构建高效Android应用:Kotlin协程的实践与优化
在Android开发领域,Kotlin以其简洁的语法和平台友好性成为了开发的首选语言。其中,Kotlin协程作为处理异步任务的强大工具,它通过提供轻量级的线程管理机制,使得开发者能够在不阻塞主线程的情况下执行后台任务,从而提升应用性能和用户体验。本文将深入探讨Kotlin协程的核心概念,并通过实例演示如何在实际的Android应用中有效地使用协程进行网络请求、数据库操作以及UI的流畅更新。同时,我们还将讨论协程的调试技巧和常见问题的解决方法,以帮助开发者避免常见的陷阱,构建更加健壮和高效的Android应用。
32 4
|
27天前
|
移动开发 Java Android开发
构建高效Android应用:Kotlin协程的实践之路
【2月更文挑战第31天】 在移动开发领域,性能优化和流畅的用户体验一直是开发者追求的目标。随着Kotlin语言的流行,其异步编程解决方案——协程(Coroutines),为Android应用带来了革命性的并发处理能力。本文将深入探讨Kotlin协程的核心概念、设计原理以及在Android应用中的实际应用案例,旨在帮助开发者掌握这一强大的工具,从而提升应用的性能和响应能力。
|
28天前
|
移动开发 调度 Android开发
构建高效Android应用:探究Kotlin协程的优势与实践
【2月更文挑战第30天】 在移动开发领域,尤其是针对Android平台,性能优化和应用流畅度始终是开发者关注的重点。近年来,Kotlin语言凭借其简洁性和功能性成为Android开发的热门选择。其中,Kotlin协程作为一种轻量级的线程管理解决方案,为异步编程提供了强大支持,使得编写非阻塞性代码变得更加容易。本文将深入分析Kotlin协程的核心优势,并通过实际案例展示如何有效利用协程提升Android应用的性能和响应速度。
|
1月前
|
数据库 Android开发 开发者
构建高性能微服务架构:从理论到实践构建高效Android应用:探究Kotlin协程的优势
【2月更文挑战第16天】 在当今快速迭代和竞争激烈的软件市场中,微服务架构以其灵活性、可扩展性和独立部署能力而受到企业的青睐。本文将深入探讨如何构建一个高性能的微服务系统,涵盖从理论基础到具体实现的各个方面。我们将重点讨论服务拆分策略、通信机制、数据一致性以及性能优化等关键主题,为读者提供一个清晰、实用的指南,以便在复杂多变的业务环境中构建和维护健壮的微服务体系结构。 【2月更文挑战第16天】 在移动开发领域,性能优化和流畅的用户体验是至关重要的。随着技术的不断进步,Kotlin作为一种现代编程语言,在Android开发中被广泛采用,尤其是其协程特性为异步编程带来了革命性的改进。本文旨在深入
239 5
|
17天前
|
Java Android开发 开发者
构建高效Android应用:Kotlin协程的实践与优化
在响应式编程范式日益盛行的今天,Kotlin协程作为一种轻量级的线程管理解决方案,为Android开发带来了性能和效率的双重提升。本文旨在探讨Kotlin协程的核心概念、实践方法及其在Android应用中的优化策略,帮助开发者构建更加流畅和高效的应用程序。通过深入分析协程的原理与应用场景,结合实际案例,本文将指导读者如何优雅地解决异步任务处理,避免阻塞UI线程,从而优化用户体验。
|
11天前
|
移动开发 API Android开发
构建高效Android应用:探究Kotlin协程的优势与实践
【4月更文挑战第7天】 在移动开发领域,性能优化和应用响应性的提升一直是开发者追求的目标。近年来,Kotlin语言因其简洁性和功能性在Android社区中受到青睐,特别是其对协程(Coroutines)的支持,为编写异步代码和处理并发任务提供了一种更加优雅的解决方案。本文将探讨Kotlin协程在Android开发中的应用,揭示其在提高应用性能和简化代码结构方面的潜在优势,并展示如何在实际项目中实现和优化协程。
|
28天前
|
移动开发 安全 Android开发
构建高效Android应用:探究Kotlin协程的优势与实践
【2月更文挑战第30天】 在移动开发领域,性能优化和应用流畅度始终是开发者追求的核心目标。特别是对于Android平台,由于设备多样性和系统资源限制,如何提升应用的响应速度和处理效率成为关键挑战。近年来,Kotlin语言因其简洁、安全且易于阅读的特性而广受欢迎。其中,Kotlin协程作为一种轻量级的线程管理方案,提供了异步编程的强大能力,使得编写非阻塞性代码变得简单高效。本文将深入探讨Kotlin协程在Android开发中的应用优势,并通过实例演示如何在实际项目中有效利用协程来改善应用性能。
|
4月前
|
编解码 监控 定位技术
抖音技术分享:抖音Android端手机功耗问题的全面分析和详细优化实践
本文结合抖音的功耗优化实践中产出了一些实验结论,优化思路,从功耗的基础知识,功耗组成,功耗分析,功耗优化等几个方面,对 Android 应用的功耗优化做一个总结沉淀。
201 0
|
8月前
|
存储 BI 定位技术
高德Android高性能高稳定性代码覆盖率技术实践
高德这套全新的方案,简洁而不简单,巧妙地实现了无Hack采集,在保证高稳定性和不侵入源码的前提下,优雅地实现了生产环境代码覆盖率的高性能采集,已经过高德地图多版本验证,是一套成熟、稳定且高效的方案。
高德Android高性能高稳定性代码覆盖率技术实践
|
8月前
|
Android开发
Android实践之简易天气(二)
Android实践之简易天气(二)