Androidアプリからロックスクリーンする


# 参考サイト
以下のページの内容を参考にしました。
[Android Working with Lock Screen and Device Administration API](http://technoatp.com/android-working-with-lock-screen-and-device-administration/)

仕様書とかきちんと調べていないので、誤りがあるかもしれませんが、とりあえず動きます。

# とりあえずやってみる
基本的には、DevicePolicyManagerのインスタンスを作って、lockNow()というメソドを呼べば良いです。ただ、色々設定があります。

とりあえず、EmptyActivityで雛形のプロジェクトを作って実験します。

ボタンを作って、押されたら LockScreen を呼ぶようにしておきます。

```xml:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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: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.ogilab.lockscreen.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:id="@+id/textView" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Lock Screen"
        android:id="@+id/button"
        android:layout_below="@+id/textView"
        android:layout_alignParentStart="true"
        android:layout_marginTop="23dp"
        android:onClick="LockScreen" />
</RelativeLayout>
```

LockScreen()の中で、lockNow()を呼んでみます。

```java:MainActivity.java
public class MainActivity extends AppCompatActivity {

    private DevicePolicyManager mDevicePolicyManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mDevicePolicyManager = (DevicePolicyManager)getSystemService(
                Context.DEVICE_POLICY_SERVICE);
    }

    public void LockScreen(View view) {
        Log.d("LockScreen", "LockScreen");
        mDevicePolicyManager.lockNow();
    }
}
```

これは駄目でした、、、。（アプリが異常終了します。）

# 真面目にやってみる

デバイスをロックするには、そのアプリが端末管理アプリであることを宣言して、かつ、ユーザがそのアプリが端末を管理して良いと許可しないといけません。（だいたい、そういうことらしい、、、）

端末管理アプリになるためには、DeviceAdminReceiverを継承したクラスが必要なので、とりあえず、Adminというクラスを作ります。

```java:Admin.java
package com.ogilab.lockscreen;

import android.app.admin.DeviceAdminReceiver;

public class Admin extends DeviceAdminReceiver {

}
```

中身はなくても動きます。メソドをoverrideすれば、色々できそうですが、、。

このアプリができる端末操作を定義します。

resの下に、xmlというフォルダーを作り、その中に、admin.xmlというファイルを作ります。

```xml:admin.xml
<device-admin xmlns:android="http://schemas.android.com/apk/res/android" >
    <uses-policies>
        <watch-login />
        <force-lock />
    </uses-policies>
</dev>
```

watch-loginはいらないかも、、、。

このアプリが、端末管理アプリであることをAndroidManifest.xmlの中に記述します。

```xml:AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ogilab.lockscreen">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver
            android:name=".Admin"
            android:permission="android.permission.BIND_DEVICE_ADMIN">
            <meta-data
                android:name="android.app.device_admin"
                android:resource="@xml/admin"/>
            <intent-filter>
                <action 
                android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
            </intent-filter>
        </receiver>
    </application>

</manifest>
```

追記しているのは、receiverのところです。

MainActivity.javaは、管理者権限がなかったら、追加する画面に移行するようなロジックを追記します。

```java.MainActivity.java
package com.ogilab.lockscreen;

import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private static final int ADMIN_INTENT = 1;
    private DevicePolicyManager mDevicePolicyManager;
    private ComponentName mComponentName;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mDevicePolicyManager = (DevicePolicyManager)getSystemService(
                Context.DEVICE_POLICY_SERVICE);
        mComponentName = new ComponentName(this, Admin.class);
    }

    public void LockScreen(View view) {
        Log.d("LockScreen", "LockScreen");
        if (mDevicePolicyManager.isAdminActive(mComponentName)) {
            mDevicePolicyManager.lockNow();
        } else {
            Log.d("LockScreen", "admin not active");
            Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
            intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mComponentName);
            intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "Administrator description");
            startActivityForResult(intent, ADMIN_INTENT);

        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == ADMIN_INTENT) {
            if (resultCode == RESULT_OK) {
                Toast.makeText(getApplicationContext(), "Registered As Admin", Toast.LENGTH_SHORT).show();
            }else{
                Toast.makeText(getApplicationContext(), "Failed to register as Admin", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d("LockScreen", "onResume");
    }
}
```

ロック画面から復帰すると、onResume()が呼ばれます。（それ以外の時も呼ばれる可能性があるので、何らかの判定が必要）

ちなみに、管理者権限がないと、ボタンを２回押さないといけません。そこは必要に応じて修正してください。

管理者権限は、設定のセキュリティの端末管理アプリの中でも変更できます。