くま's Tech系Blog

基本的には技術で学んだことを書き留めようと思います。雑談もやるかもね!

再起動をadbコマンドで実行する

Androidで開発していて、PCを実機につないで、再起動を確認するときに実際に再起動してしまうと実行が消えてしまいますよね? どうやらADBコマンドで実際に再起動せずに再起動を再現できるみたいなので、やってみました。 ただ、やってみると意外にハマったので、手順を残したいと思います。

①実際に実機で試す

とりあえず、PCに実機をつないで、下記コマンドを入力する

adb shell am broadcast -a android.intent.action.ACTION_BOOT_COMPLETED

すると権限がないというエラーが発生

Security exception: Permission Denial: not allowed to send broadcast android.intent.action.BOOT_COMPLETED

java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.BOOT_COMPLETED
        at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:19504)
        at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:20142)
...........

どうやら権限がないようなので、調べてみるとAndroidManifestに権限の追加が必要みたいでした。

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest ....">

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application.......>
        <activity.....></activity>
        <receiver android:name = ".(クラス名)" android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

uses-permissionのタグとactionタグに上記表記を追加しました。 こうすると、指定したreceiverのクラスが再起動時に動くようになるはずです。 それでも動かない場合は、上記のようにandroid:exported="true"を追加すると、うまくいく場合もあるようです。(外部に非公開ならfalseを設定する必要があります)

②検証環境をエミュレーターに変更

なんだこれ合ってるのにと思いながら、長いこと検証していましたが、なかなかエラーは解消されませんでした。 (root権限で実行、android:enabled="true"をreceiverに追加、android:installLocation="internalOnly"をmanifestタグに追加などいろいろ試しました。)

そこで1度エミュレーターを使ってみようと思い、試しましたが、それでもだめでした。 これでうまくいくと思ったら、エラーは解消されませんでした。 また、いろいろ試している中でADB rootコマンドではなく、下記コマンドを使うと、エラーの原因がわかりました

>adb shell
generic_x86:/ $ su
/system/bin/sh: su: not found

root権限になっていませんでした.....

adb rootを使ったときはエラーも出てなかったので、問題なくできていると思ったのですが、できてなかったみたいです。(なんか表示してくれよと思いました)

確かに/system/binにはsuコマンドがありませんでした。

調べてみると、下記、記事に行き当たりました。

ADBコマンドをroot権限で使いたい

つまり、実機はもちろんroot権限は使えなくて、エミュレーターでも(Google Play)という表記があろものはroot権限が使えないのです。

それで、(Google APIs)という表記のデータを使い、試すとroot権限になれました。

>adb shell
generic_x86:/ $ su
generic_x86:/ #  (#に変更したので、root権限)

この状態で、再度実行するとうまくいきました!

# am broadcast -a android.intent.action.ACTION_BOOT_COMPLETED -n (パッケージ名) / (クラス名)

Broadcasting: Intent { act=android.intent.action.ACTION_BOOT_COMPLETED flg=0x400000 cmp=com.kumaydevelop.todoreminder/AlarmBroadCastReciever }
Broadcast completed: result=0

なお、am broadcastで-nオプションをつけないとうまくいかなかったので、追加しました。 これでうまくいき確認が取れました。

今回は根本の原因を見つけるのに時間がかかってしまいました。試している段階である程度の見立てを早めに見つけないと、かなり時間がかかるなあと感じました。

参照

ADBコマンドをroot権限で使いたい

stack overflow