普通APP如何使得系统休眠



引言

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
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值