Android
JUnit

AndroidのJUnit時にスクリーンロックを解除する方法

More than 3 years have passed since last update.

AndroidでActivityInstrumentationTestCase2を使ってJUnitのテストを実行させるとき、スクリーンロック(キーガード)が掛かっていてActivityが起動できないときの対処法です。

ただし、PINロックやパターンロックが掛かっているときはこの手法では外せないので注意してください。

サンプルプロジェクト

まずスクリーンロックを解除するだけのActivityをテスト側のコードに作ります。

public class UnlockKeyguardActivity extends Activity {

private static Handler sHandler = new Handler();

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

Window window = this.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}

@Override
protected void onResume() {
super.onResume();
sHandler.postDelayed(new Runnable() {
@Override
public void run() {
checkUnlocked();
}
}, 100);
}

private void checkUnlocked() {
KeyguardManager km = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (!km.inKeyguardRestrictedInputMode() && pm.isScreenOn()) {
finish();
} else {
sHandler.postDelayed(new Runnable() {
@Override
public void run() {
checkUnlocked();
}
}, 100);
}
}
}

次にUnlockKeyguardActivityをテスト側のAndroidManifest.xmlに追加する。

このときにandroid:exported="true"にしておくのが大事。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="net.cattaka.android.fastchecklist.test"
>
<application>
<activity
android:name="net.cattaka.android.fastchecklist.test.UnlockKeyguardActivity"
android:exported="true"/>
</application>

</manifest>

そしてテストの開始時(setUpなど)にキーガードが掛かっているかチェックして、掛かっていたらUnlockKeyguardActivityを起動する処理を追加する。

    protected void setUp() throws Exception {

super.setUp();
{ // Unlock keyguard and screen on
KeyguardManager km = (KeyguardManager) getInstrumentation()
.getTargetContext().getSystemService(Context.KEYGUARD_SERVICE);
PowerManager pm = (PowerManager) getInstrumentation()
.getTargetContext().getSystemService(Context.POWER_SERVICE);
if (km.inKeyguardRestrictedInputMode() || !pm.isScreenOn()) {
Intent intent = new Intent(getInstrumentation().getContext(),
UnlockKeyguardActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getInstrumentation().getTargetContext().startActivity(intent);
while (km.inKeyguardRestrictedInputMode()) {
SystemClock.sleep(100);
}
}
}
}

ActivityInstrumentationTestCase2から派生させたクラスに実装し、そのActivityのテストではそのクラスを継承して書くようにすれば自動でスクリーンロックを解除して開始してくれるようになる。