Android锁屏实践
来源:互联网 发布:c语言char什么意思 编辑:程序博客网 时间:2024/06/07 03:02
转载请注意:http://blog.csdn.net/wjzj000/article/details/78511303
本菜开源的一个自己写的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
- Android锁屏实践
- Android杂谈(27)锁屏实践
- 【实践】Android apk瘦身实践
- Android实践(一)
- Android实践(二)
- Android内核开发实践
- android SQLiteDatebase 实践
- Android最佳实践
- Android 最佳实践
- android 实践配置环境
- android.graphics.Typeface实践
- Android Service小实践
- 开始实践android
- android ndk 入门实践
- Android最佳实践
- android SQLiteDatebase 实践
- Android 动画实践
- Android Fragment实践(一)
- Activity管理
- Vue.js组件——slot杂记
- JavaScript 笔记
- 3-2 构造函数的调用
- JDK容器学习之Map : HashMap,TreeMap,LinkedHashMap对比
- Android锁屏实践
- 打字游戏
- node基础
- Spark学习(一)基础介绍
- 每天回顾linux命令(tail)
- 桶排序
- 用单分支条件语句(if语句)求最值
- 人生的要务:提高自己的思维层次
- Linux常用命令