我正在尝试编写一个应用程序来阻止用户将手机恢复出厂设置或重置设置。 问题是该应用程序以管理员身份激活,但显示有关缺乏权限的错误。同时,当单击“阻止擦除数据”时,应用程序将关闭。
我尝试了各种方法将应用程序的权限从配置文件所有者更改为设备所有者,但没有成功 这是我的 MainActivity.kt:
package com.example.test2
import android.annotation.SuppressLint
import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.UserManager
import androidx.appcompat.app.AppCompatActivity
import com.example.test2.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var devicePolicyManager: DevicePolicyManager
private lateinit var componentName: ComponentName
private val disallowFactoryReset = "no_factory_reset"
private lateinit var binding: ActivityMainBinding
@SuppressLint("WrongConstant")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
devicePolicyManager = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
componentName = ComponentName(this, MyDeviceAdminReceiver::class.java)
// Ustawienie tekstu przycisków na podstawie zasobów ciągów
binding.activateButton.setText(R.string.activate_button_text)
binding.deactivateButton.setText(R.string.deactivate_button_text)
binding.blockWipeDataButton.setText(R.string.block_wipe_data_button_text)
binding.unblockWipeDataButton.setText(R.string.unblock_wipe_data_button_text)
binding.activateButton.setOnClickListener {
if (!devicePolicyManager.isAdminActive(componentName)) {
val intent = Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName)
startActivity(intent) // Uruchamianie intencji
}
}
binding.deactivateButton.setOnClickListener {
if (devicePolicyManager.isAdminActive(componentName)) {
devicePolicyManager.removeActiveAdmin(componentName)
}
}
binding.blockWipeDataButton.setOnClickListener {
// Blokowanie możliwości resetowania do ustawień fabrycznych
devicePolicyManager.addUserRestriction(componentName, UserManager.DISALLOW_FACTORY_RESET)
}
binding.unblockWipeDataButton.setOnClickListener {
if (devicePolicyManager.isAdminActive(componentName)) {
// Odblokowywanie możliwości resetowania do ustawień fabrycznych
devicePolicyManager.clearUserRestriction(componentName, disallowFactoryReset)
}
}
}
}
MyDeviceAdminReceiver.kt:
package com.example.test2
import android.app.admin.DeviceAdminReceiver
import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.widget.Toast
class MyDeviceAdminReceiver : DeviceAdminReceiver() {
override fun onEnabled(context: Context, intent: Intent) {
super.onEnabled(context, intent)
showToast(context, "Device Admin Enabled")
setAsProfileOwner(context)
}
override fun onDisabled(context: Context, intent: Intent) {
super.onDisabled(context, intent)
showToast(context, "Device Admin Disabled")
}
private fun showToast(context: Context, msg: String) {
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
}
private fun setAsProfileOwner(context: Context) {
val intent = Intent(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE)
intent.putExtra(
DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
ComponentName(context, MyDeviceAdminReceiver::class.java)
)
context.startActivity(intent)
}
}
和 AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.test2">
<uses-permission android:name="android.permission.BIND_DEVICE_ADMIN"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Test2">
<receiver
android:name=".MyDeviceAdminReceiver"
android:label="@string/device_admin"
android:description="@string/device_admin_description"
android:permission="android.permission.BIND_DEVICE_ADMIN"
android:exported="true">
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin_receiver" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
<activity android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
以及来自 Logcat 的错误:
致命异常:主要 进程:com.example.test2,PID:21036 java.lang.SecurityException:Admin ComponentInfo{com.example.test2/com.example.test2.MyDeviceAdminReceiver} 不拥有该配置文件 在 android.os.Parcel.createExceptionOrNull(Parcel.java:2386) 在 android.os.Parcel.createException(Parcel.java:2370) 在 android.os.Parcel.readException(Parcel.java:2353) 在 android.os.Parcel.readException(Parcel.java:2295) 在 android.app.admin.IDevicePolicyManager$Stub$Proxy.setUserRestriction(IDevicePolicyManager.java:11904) 在 android.app.admin.DevicePolicyManager.addUserRestriction(DevicePolicyManager.java:9953) 在 com.example.test2.MainActivity.onCreate$lambda$2(MainActivity.kt:56) 在 com.example.test2.MainActivity.$r8$lambda$4IJy-QVha7hb97uWLhv_4shwM5Y(未知来源:0) 在 com.example.test2.MainActivity$$ExternalSyntheticLambda2.onClick(来源未知:2) 在 android.view.View.performClick(View.java:8160) 在 android.widget.TextView.performClick(TextView.java:16222) 在 com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1218) 在 android.view.View.performClickInternal(View.java:8137) 在 android.view.View.access$3700(View.java:888) 在 android.view.View$PerformClick.run(View.java:30236) 在 android.os.Handler.handleCallback(Handler.java:938) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java:246) 在 android.app.ActivityThread.main(ActivityThread.java:8625) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130) 引起原因:android.os.RemoteException:远程堆栈跟踪: 在 com.android.server.devicepolicy.DevicePolicyManagerService.getActiveAdminOrCheckPermissionForCallerLocked(DevicePolicyManagerService.java:3665) 在 com.android.server.devicepolicy.DevicePolicyManagerService.getActiveAdminOrCheckPermissionForCallerLocked(DevicePolicyManagerService.java:3710) 在 com.android.server.devicepolicy.DevicePolicyManagerService.getActiveAdminForCallerLocked(DevicePolicyManagerService.java:3688) 在com.android.server.devicepolicy.DevicePolicyManagerService.setUserRestriction(DevicePolicyManagerService.java:12295) 在 android.app.admin.IDevicePolicyManager$Stub.onTransact$setUserRestriction$(IDevicePolicyManager.java:19124)
好的,应用程序工作正常,它阻止恢复出厂设置。 这https://stackoverflow.com/a/42119378/23369606
adb shell
dpm set-device-owner com.foo.deviceowner/.DeviceAdminRcvr
方法有很大帮助,我只需要使其成为设备所有者,但是有没有机会在不删除所有现有帐户的情况下使应用程序设备所有者?新手机没有问题,但如果我需要让它在已经使用的手机上运行?