关于AppWidgetProvider的用法,下面通过一个锁屏功能的小应用介绍具体的使用。
步骤:
(1)继承AppWidgetProvider
(2)在清单文件中注册该AppWidgetProvider
(3)申请设备管理器权限
(4)锁屏功能开启
关于AppWidgetProvider的使用方法1和2两个步骤已经说明,步骤3和4只是作为完成锁屏这个小例子的后续步骤。
详细代码:
(1)继承AppWidgetProvider
需要重写的三个方法:
- onUpdate 插件刷新时调用
- onEnabled 当第一个插件被添加的时候调用
- onDisabled 当最后一个插件被删除的时候调用
class LockScreenWidget : AppWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
// There may be multiple widgets active, so update all of them
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
Log.d("LockScreenWidget","onUpdate"+appWidgetIds.size)
}
override fun onEnabled(context: Context) {
// Enter relevant functionality for when the first widget is created
// 当第一个插件被添加的时候调用
Log.d("LockScreenWidget","onEnabled")
}
override fun onDisabled(context: Context) {
// Enter relevant functionality for when the last widget is disabled
// 当最后一个插件被删除的时候调用
Log.d("LockScreenWidget","onDisabled")
}
companion object {
// 刷新插件
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager,
appWidgetId: Int) {
val startServiceIntent = Intent(context,LockService::class.java)
val pIntent = PendingIntent.getService(context, 0, startServiceIntent, 0)
val views = RemoteViews(context.packageName, R.layout.lock_screen_widget)
views.setOnClickPendingIntent(R.id.imageView,pIntent)
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views)
}
}
}
RemoteViews定义的是插件的视图,在这里实现的R.layout.lock_screen_widget只包含一个ImageView的简单布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/widget_margin">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:scaleType="fitCenter"
android:src="@mipmap/widget_lock_icon" />
</RelativeLayout>
(2)在清单文件中注册该AppWidgetProvider
AppWidgetProvider 是继承BroadcastReceiver,本质上也是一个BroadcastReceiver,需要在清单文件中注册该接收者。
<application
android:allowBackup="true"
android:icon="@mipmap/launch_lock"
android:label="@string/app_name"
android:roundIcon="@mipmap/launch_lock"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<receiver android:name=".LockScreenWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/lock_screen_widget_info" />
</receiver>
</application>
lock_screen_widget_info 定义的是该插件的一些配置信息,宽高等。
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/lock_screen_widget"
android:minHeight="40dp"
android:minWidth="40dp"
android:previewImage="@mipmap/widget_lock_icon"
android:updatePeriodMillis="86400000"
android:widgetCategory="home_screen"></appwidget-provider>
- android:initialLayout 布局
- android:minHeight 最小高度
- android:minWidth 最小宽度
- android:previewImage 预览图标,就是在小工具栏看到的效果预览
- android:updatePeriodMillis 刷新频率
- android:widgetCategory 插件类别
(3)申请设备管理权限
val mDeviceAdmin:ComponentName = ComponentName(this, AdminManageReceiver::class.java)
val intent = Intent(
DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
mDeviceAdmin)
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
"需要激活设备管理器,才能使用锁屏功能")
startActivity(intent)
AdminManageReceiver 是一个广播接收者,可以不做任何操作。
public class AdminManageReceiver extends DeviceAdminReceiver {}
(4)锁屏功能开启
实现锁屏需要使用DevicePolicyManager类
用到的方法:
- isAdminActive 判断是否激活管理权限
- lockNow 锁屏
//设备策略服务
var dpm: DevicePolicyManager = getSystemService(DEVICE_POLICY_SERVICE) as DevicePolicyManager
/**
* 一键锁屏
*/
private fun lockscreen() {
val who = ComponentName(this, AdminManageReceiver::class.java)
if (dpm?.isAdminActive(who)!!) {
dpm?.lockNow()//锁屏
dpm?.resetPassword("", 0)//设置屏蔽密码
//清除Sdcard上的数据
// dpm.wipeData(DevicePolicyManager.WIPE_EXTERNAL_STORAGE);
//恢复出厂设置
// dpm.wipeData(0);
} else {
openAdmin()
Toast.makeText(this, "还没有打开管理员权限", Toast.LENGTH_SHORT).show()
startActivity(Intent(this,MainActivity::class.java))
}
}
总结
锁屏功能小例子使用的是服务的形式,点击桌面插件唤起服务进行锁屏,这个小例子只有一个页面,可以激活管理权限和卸载该程序。
代码使用Kotlin编写,详细实现看源码:
https://github.com/StarsAaron/LockScreenApp/tree/master