普通APP如何使得系统休眠

来源:互联网 发布:小企业的会计软件 编辑:程序博客网 时间:2024/06/06 19:57

  • 引言
  • lockNow函数的作用
  • 普通APP如何使得系统休眠
    • 普通APP如何成为device admin
  • 结束语


引言

Android 系统休眠,常见的接口是PowerManager提供的goToSleep,但是很遗憾,调用这个接口需要System 权限;即用Platform key签名的APP才可以;

那么普通APP 可否使得系统suspend呢?

lockNow函数的作用

lockNow定义于文件DevicePolicyManager.java中,实现如下:

mService即IDevicePolicyManager,由DevicePolicyManagerService实现;

public void lockNow() {    if (mService != null) {        try {                mService.lockNow();            } catch (RemoteException e) {                Log.w(TAG, "Failed talking with device policy service", e);            }        }    }

mService即IDevicePolicyManager,由DevicePolicyManagerService实现;
所以lockNow的具体实现在DevicePolicyManagerService中

public void lockNow() {    if (!mHasFeature) {        return;    }    synchronized (this) {        // This API can only be called by an active device admin,        // so try to retrieve it to check that the caller is one.       getActiveAdminForCallerLocked(null,           DeviceAdminInfo.USES_POLICY_FORCE_LOCK);       lockNowUnchecked();    }}private void lockNowUnchecked() {    long ident = Binder.clearCallingIdentity();    try {        // Power off the display                mPowerManager.goToSleep(SystemClock.uptimeMillis(),                           PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN, 0);        // Ensure the device is locked        new LockPatternUtils(mContext).requireCredentialEntry(UserHandle.USER_ALL);        getWindowManager().lockNow(null);    } catch (RemoteException e) {    } finally {        Binder.restoreCallingIdentity(ident);    } }

getActiveAdminForCallerLocked检查当前的调用者是否为Device admin,如果是的,则执行lockNowUnchecked,否则会在getActiveAdminForCallerLocked执行过程中抛出SecurityException;

而lockNowUnchecked函数实际上调用了goToSleep使得系统suspend;

总的来说,lockNow是对goToSleep降低权限的封装,所以我们可以通过调用lockNow来实现系统suspend

普通APP如何使得系统休眠

在Android系统中,APP根据签名不同分为system app或者普通app,system app使用platform key签名,具备system权限,可以做一些系统级别的操作,例如调用goToSleep,调用reboot等;普通APP即用没有用哦platform key签名的app;那么这样的APP 如何实现系统休眠呢?我们刚刚提到的lockNow函数就是一种办法;但是问题是,嗲用lockNow之前得先具备device admin权限;

普通APP如何成为device admin

1.. 在AndroidManifest.xml中添加receiver类继承自DeviceAdminReceiver

<application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name="com.example.suspendappnormal.MainActivity"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <receiver            android:name="com.example.suspendappnormal.MyAdmin"            android:label="@string/app_name"            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" />            </intent-filter>        </receiver>    </application>

MyAdmin即为添加的receiver

2.. 为MyAdmin添加java code

package com.example.suspendappnormal;import android.app.admin.DeviceAdminReceiver;public class MyAdmin extends DeviceAdminReceiver {}

很简单,就是一个继承自DeviceAdminReceiver的类,不用实现任何函数

3.. 在Activity中实现device admin的添加
activity_main.xml文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.example.suspendappnormal.MainActivity" >    <Button         android:id="@+id/admin_add_btn"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="AddToAdminDevice"/>    <Button         android:id="@+id/suspend_btn"        android:layout_height="wrap_content"        android:layout_width="wrap_content"        android:text="suspend"/></LinearLayout>

id 为admin_add_btn的button,做 device admin的添加,如果添加成功之后,该按钮编程灰色,不可点击;如果已经具备device admin权限,该按钮也是灰色,不可点击;

id为suspend_btn的Button,完成lockNow函数的执行;

onCreate函数

protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mAdminName = new ComponentName(this, MyAdmin.class);        mDm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);        mAdminAddBtn = (Button)findViewById(R.id.admin_add_btn);        mAdminAddBtn.setOnClickListener(this);        mSuspendBtn = (Button)findViewById(R.id.suspend_btn);        mSuspendBtn.setOnClickListener(this);        if (!mDm.isAdminActive(mAdminName)) {            mAdminAddBtn.setEnabled(true);        } else {            mAdminAddBtn.setEnabled(false);        }    }

new 出mAdminName的component组件,就是为该组件所在的process添加admin权限;

点击AddToAdminDevice button,则添加admin权限,button的click相应事件如下:

@Override    public void onClick(View v) {        // TODO Auto-generated method stub        switch(v.getId()) {        case R.id.admin_add_btn:            if (mDm != null) {                if (!mDm.isAdminActive(mAdminName)) {                    Log.i(TAG, "has no admin, add it");                    Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);                    intent.putExtra (DevicePolicyManager.EXTRA_DEVICE_ADMIN, mAdminName);                    intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "sara sara sara");                    startActivityForResult(intent, 0);                    mAdminAddBtn.setEnabled(false);                }            }            break;        case R.id.suspend_btn:            if (mDm != null) {                if (mDm.isAdminActive(mAdminName)) {                    Log.i(TAG, "lockNow");                    mDm.lockNow();                } else {                    Log.i(TAG, "admin not active");                }            }            break;        default:            break;        }    }

4.. 运行效果如下:
第一次运行该APP时:
这里写图片描述

点击ADDTOADMIN button
这里写图片描述
点击Active
这里写图片描述
此时ADDTOADMIN button是disable的,因为此时APP已经获得了admin权限;
点击Suspend即会使得系统suspend

结束语

device admin权限,只用申请一次,该APP就一直拥有,所以不用每次调用lockNow时,都去为该APP申请;

此外Android系统中,admin权限的管理在Setting app中;
Setting->security->Device Adminstrators;

如果要删除具备admin权限的APP,需要先到Setting中,将该权限移除;否则无法删除该APP;

阅读全文
0 0
原创粉丝点击