前情提要:
自己用的魅族的手机,魅族15和魅族17,发现魅族系统没有自带的桌面息屏小工具,下一个网上提供的息屏apk又怕不安全,还有广告,故自己琢磨琢磨地就搞了一个简单的桌面息屏小工具;
正文:
先提供这个项目的github网址:https://github.com/oldsboy/CloseWindow。安装包在app/release/文件夹下面有分享。
emmmm,这个项目里涉及的技术其实不多,其一是android widget桌面小控件的开发,这个知识点在网上一查一大把,我也就不多赘述,其中有一个重点是:widget控件的交互(比如说点击)是以广播的形式进行传递的,而android8以后android便不允许应用接收隐式广播,而导致点击桌面小控件没有反应,所以需要在点击事件传递的intent中加入0x01000000这个flag来突破这个限制,也不知道以后会不会改,如果不行可以考虑再创建一个动态广播来处理锁屏事件。
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (intent != null && intent.getAction() != null) {
Log.d(TAG, "onReceive: 收到广播通知:" + intent.getAction());
switch (intent.getAction()) {
case BTN_CLICK_ACTION:
closeWindow(context);
}
}
}
private void closeWindow(final Context context) {
ComponentName adminReceiver = new ComponentName(context, AdminReceiver.class);
DevicePolicyManager systemService = (DevicePolicyManager) context.getSystemService(DEVICE_POLICY_SERVICE);
if (!systemService.isAdminActive(adminReceiver)){
Toast.makeText(context, "需要先进入app进行授权", Toast.LENGTH_SHORT).show();
}else {
Log.d(TAG, "closeWindow: ");
new Handler().postDelayed(systemService::lockNow, 300);
}
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.lock_layout);
remoteViews.setImageViewResource(R.id.img_lock, R.drawable.press_icon);
Intent intent = new Intent(BTN_CLICK_ACTION);
intent.setClass(context, MonitorWidgetProvider.class);
intent.setFlags(intent.getFlags()| 0x01000000);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
remoteViews.setOnClickPendingIntent(R.id.img_lock, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
Log.d(TAG, "onUpdate: 配置点击事件完成");
}
上述代码交代的是桌面小控件的行为逻辑。其二是锁屏的处理,我上篇文章也吐槽了网上使用wakeLock来实现锁屏的代码其实很难实现,至少我翻来覆去使用wakeLock也没见我屏幕黑掉。。。所以使用DevicePolicyManager来实现息屏的效果。而使用这个功能则必须要通过手机设备管理员权限才能实现。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.lock_layout);
ComponentName adminReceiver = new ComponentName(this, AdminReceiver.class);
DevicePolicyManager systemService = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
if (!requestLockAdmins(systemService, adminReceiver)){
Toast.makeText(this, "点击按钮申请权限后可以息屏", Toast.LENGTH_SHORT).show();
}
((TextView)this.findViewById(R.id.tv)).setOnClickListener(v -> {
if (requestLockAdmins(systemService, adminReceiver)){
systemService.lockNow();
}
});
}
/**
*申请设备管理员权限
*/
private boolean requestLockAdmins(DevicePolicyManager systemService, ComponentName adminReceiver) {
if (systemService == null) return false;
//检查是否已经获取设备管理权限
boolean active = systemService.isAdminActive(adminReceiver);
if (!active) {
//打开DevicePolicyManager管理器,授权页面
Intent intent = new Intent();
//授权页面Action --> DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN
intent.setAction(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
//设置DEVICE_ADMIN,告诉系统申请管理者权限的Component/DeviceAdminReceiver
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, adminReceiver);
//设置 提示语--可不添加
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "DevicePolicyManager涉及的管理权限,一次性激活!");
startActivityForResult(intent, REQUEST_DevicePolicy);
}
return active;
}
上述代码是跳转到申请设备管理员页面的实现,那至此就是这个息屏工具的大部分实现了,还有一些widget设定的细节就不展示了,没有在那里下多大功夫。