前段时间公司有个需求,需要控制手机的摄像头和录音全部禁用,以达到用户公司那不可告人的小秘密~ 嘿嘿嘿~我把这个需求告诉了我的大哥..于是乎大哥会心一笑对我说..留个后门..看看是不是A.V公司的工作人员要配置的内部手机..开过玩笑~ 评审哥哥不要当真~
这篇文章我会使用android提供的设备管理器类,来实现禁用手机摄像头的功能,还能够改变密码,锁屏,重启等功能,具体功能情去查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;
/**
* Created by Administrator on 2017/8/16 0016.
*/
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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#edeaea"
tools:context="com.sq.devicedemo.MainActivity">
<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.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
/**
* 激活组件的请求码
*/
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在设备管理器中的权限。