需求:控制手机的摄像头和录音全部禁用~
这篇文章使用android提供的设备管理器类DeviceAdminReceiver ,来实现禁用手机摄像头的功能,还能够改变密码,锁屏,重启等功能,具体功能请去查API,如果我没记错的话有5千多行... ... 但是这篇文章主要就介绍常用的几个功能需求 = = 下面看代码:
1.首先你需要先创建xml文件如上图所示。
2.在device_admin.xml文件中,写入如下内容:(下面的内容就好比申请权限)
<device-admin xmlns:android="http://schemas.android.com/apk/res/android"> <uses-policies> <!--停用相机--> <disable-camera/> <!--锁屏时禁用某些功能--> <disable-keyguard-features/> <!--设置存储设备加密--> <encrypted-storage/> <!--设置锁定屏幕密码的有效期--> <expire-password/> <!--锁定屏幕--> <force-lock/> <!--设置密码规则--> <limit-password/> <!--更改屏幕解锁密码--> <reset-password/> <!--设置设备全局代理--> <set-global-proxy/> <!--监控屏幕解锁尝试次数--> <watch-login/> <!--恢复出厂设置--> <wipe-data/> </uses-policies> </device-admin>
3.你需要创建一个DeviceReceiver(你可以理解这是一个设备管理的监听器):
import android.app.admin.DeviceAdminReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast; public class DeviceReceiver extends DeviceAdminReceiver { @Override public void onEnabled(Context context, Intent intent) { super.onEnabled(context, intent); Toast.makeText(context, "设备管理器:已激活", Toast.LENGTH_SHORT).show(); } @Override public void onDisabled(Context context, Intent intent) { super.onDisabled(context, intent); Toast.makeText(context, "设备管理器:未激活", Toast.LENGTH_SHORT).show(); } @Override public CharSequence onDisableRequested(Context context, Intent intent) { Intent intent1 = context.getPackageManager().getLaunchIntentForPackage("com.android.settings"); intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent1); try { Thread.sleep(7000); } catch (InterruptedException e) { e.printStackTrace(); } return "This is a onDisableRequested response message"; } @Override public void onPasswordChanged(Context context, Intent intent) { super.onPasswordChanged(context, intent); Toast.makeText(context, "设备管理;密码已经改变", Toast.LENGTH_SHORT).show(); } @Override public void onPasswordFailed(Context context, Intent intent) { super.onPasswordFailed(context, intent); Toast.makeText(context, "设备管理:改变密码失败", Toast.LENGTH_SHORT).show(); } @Override public void onPasswordSucceeded(Context context, Intent intent) { super.onPasswordSucceeded(context, intent); Toast.makeText(context, "设备管理;改变密码成功", Toast.LENGTH_SHORT).show(); } }
4.接下来就是很重要的清单文件中注册receive了:
<!--设备管理--> <receiver android:name=".DeviceReceiver" android:permission="android.permission.BIND_DEVICE_ADMIN"> <meta-data android:name="android.app.device_admin" android:resource="@xml/device_admin"/> <intent-filter> <action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/> <!--<category android:name="android.intent.action.BOOT_COMPLETED"/>--> <!--<category android:name="android.intent.category.HOME"/>--> </intent-filter> </receiver>
5.布局文件,仅仅是设置几个按钮:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#edeaea"> <Button android:id="@+id/btn_action" android:text="激活设备管理器" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp"/> <Button android:id="@+id/btn_cancel_active" android:text="取消激活设备管理器" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp"/> <Button android:id="@+id/btn_change_password" android:text="修改密码为1234" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/btn_cancel_password" android:text="取消密码" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/btn_lock" android:text="锁屏" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp"/> <Button android:id="@+id/btn_setCameraDisabled" android:text="禁用 相机" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp"/> <Button android:id="@+id/btn_setCameraDisabled1" android:text="启动 相机" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp"/> </LinearLayout>
6.MainActivity中代码部分,初始化和判断设备管理器状态,以及用户是否同意点击的回调方法:
import android.app.Activity; import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.Toast; public class MainActivity extends Activity { /** * 激活组件的请求码 */ private static final int REQUEST_CODE_ACTIVE_COMPONENT = 1; /** * 设备安全管理服务,2.2之前需要通过反射技术获取 */ private DevicePolicyManager devicePolicyManager = null; /** * 对应自定义DeviceAdminReceiver的组件 */ private ComponentName componentName = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setTranslucent(this); devicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); componentName = new ComponentName(this,DeviceReceiver.class); /** * 激活设备管理器 */ findViewById(R.id.btn_action).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isAdminActive()){ Toast.makeText(MainActivity.this, "设备管理器已激活", Toast.LENGTH_SHORT).show(); }else { // 打开管理器的激活窗口 Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN); // 指定需要激活的组件 intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,componentName); intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "(激活窗口中的描述信息)"); startActivityForResult(intent, REQUEST_CODE_ACTIVE_COMPONENT); } } }); /** * 取消激活 */ findViewById(R.id.btn_cancel_active).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isAdminActive()){ devicePolicyManager.removeActiveAdmin(componentName); Toast.makeText(MainActivity.this, "将触发deviceAdminReceiver.onDisabled", Toast.LENGTH_SHORT).show(); }else { Toast.makeText(MainActivity.this, "设备管理未激活", Toast.LENGTH_SHORT).show(); } } }); /** * 锁屏 */ findViewById(R.id.btn_lock).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isAdminActive()){ devicePolicyManager.lockNow(); }else { Toast.makeText(MainActivity.this, "设备管理未激活", Toast.LENGTH_SHORT).show(); } } }); /** * 禁止使用摄像头 */ findViewById(R.id.btn_setCameraDisabled).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isAdminActive()){ devicePolicyManager.setCameraDisabled(componentName,true); } } }); /** * 启动摄像头 */ findViewById(R.id.btn_setCameraDisabled1).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isAdminActive()){ devicePolicyManager.setCameraDisabled(componentName,false); } } }); /** * 设置密码 */ findViewById(R.id.btn_change_password).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isAdminActive()){ devicePolicyManager.resetPassword("123456",1); } } }); /** * 取消密码 */ findViewById(R.id.btn_cancel_password).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isAdminActive()){ devicePolicyManager.resetPassword("",0); } } }); } /** * 判断该组建是否有系统管理员的权限(系统安全-设备管理器 中是否激活) * @return */ private boolean isAdminActive(){ return devicePolicyManager.isAdminActive(componentName); } /** * 用户是否点击激活或取消的回调 * @param requestCode * @param resultCode * @param data */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_ACTIVE_COMPONENT) { // 激活组件的响应 if (resultCode == Activity.RESULT_CANCELED) { Toast.makeText(this, "用户手动取消激活", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "已触发DeviceAdminReceiver.onEnabled", Toast.LENGTH_SHORT).show(); } } } public static void setTranslucent(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // 设置状态栏透明 activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); // 设置根布局的参数 ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0); rootView.setFitsSystemWindows(true); rootView.setClipToPadding(true); } } }
上个摄像头被禁用的效果图(微信调用扫一扫界面):
不知道你们有没有注意,在第三步中有一处添加了其他的代码部分,目的是用户手动点击取消激活时,开启线程阻塞,当睡眠超过5s后,询问是否真的取消设备管理器权限的弹框会失效(通过查看android源码可以知道),为了稳妥点设置成7s,当然也有不同的方法啦,譬如循环不停的锁屏,甚至可以写重启手机...只是锁屏后不同手机有差异,手速快一点一样可以在屏幕亮暗的瞬间点确定..当然你手机设置密码的话就不会有这种问题~ 还有一种老方法已经不能在比较新的android系统使用了,就是在设备管理器的界面弹出遮挡布局,来变相禁止用户擅自取消权限... android系统已经知道了这个bug,禁止一切弹窗或是布局活动页在此界面弹出,会报没有权限异常且自动取消本app在设备管理器中的权限。
转载自:https://blog.csdn.net/qq_37842258/article/details/77480022