質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.23%

android6.0のRuntimepermission対応

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,994

subjectman15

score 7

前提・実現したいこと

現在AndroidStudioでカメラアプリを作成しています。機能の作成は完了したのですが、作成したアプリを使用予定の実機がAndroid6.0で、Runtimepermissionの対応が必要なのですがなかなか上手くいきません。私の希望ではパーミッション許可の流れを以下のように進めたいです。

アプリ起動(インストール初回起動)

カメラ使用のパーミッション許可を求めるダイアログ

オーディオのパーミッション許可を求めるダイアログ

ストレージ使用のパーミッション許可を求めるダイアログ

カメラオープン(プレビュー表示)

という流れが理想です。

発生している問題・エラーメッセージ

現在実機にアプリをインストールして起動すると、パーミッション許可を求めるダイアログが表示される前にアプリがRuntimeExceptionにより終了してしまっています。アプリが終了しました〜という旨のメッセージの後ろに許可を求めるダイアログ表示されており、アプリが終了しました〜のメッセージをOKを選択してアプリを完全に停止した後にパーミッション許可を押す形になってしまっています。しかも、このダイアログボックスが一度にすべて表示されません(参考にしたサイトでは1/3のように一度のダイアログ表示でよいようになっていた)なので、アプリ起動→終了→ダイアログ表示の動作を3回繰り返さなければならない状態にあります。(全てのパーミッションを許可すればアプリの起動に問題はありません)
どうかどのようにコーディングしていけば良いかご教授お願いします。

以下エラーログです。

08-26 17:04:36.424 6846-6846パッケージ名 I/Process: Sending signal. PID: 6846 SIG: 9
08-26 17:04:37.671 6940-6940パッケージ名 W/System: ClassLoader referenced unknown path: /data/appパッケージ名-1/lib/arm64
08-26 17:04:37.773 6940-6940パッケージ名 W/System: ClassLoader referenced unknown path: /data/appパッケージ名-1/lib/arm64
08-26 17:04:37.827 6940-6940パッケージ名 D/AndroidRuntime: Shutting down VM
08-26 17:04:37.827 6940-6940パッケージ名 E/AndroidRuntime: FATAL EXCEPTION: main
                                                                            Process: パッケージ名, PID: 6940
                                                                            java.lang.RuntimeException: Unable to start activity ComponentInfo{パッケージ名パッケージ名.MainActivity}: java.lang.ArrayIndexOutOfBoundsException: length=2; index=2
                                                                                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2455)
                                                                                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2541)
                                                                                at android.app.ActivityThread.access$900(ActivityThread.java:169)
                                                                                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1382)
                                                                                at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                at android.os.Looper.loop(Looper.java:148)
                                                                                at android.app.ActivityThread.main(ActivityThread.java:5554)
                                                                                at java.lang.reflect.Method.invoke(Native Method)
                                                                                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:746)
                                                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)
                                                                             Caused by: java.lang.ArrayIndexOutOfBoundsException: length=2; index=2
                                                                                at パッケージ名.MainActivity.requestPermissions(MainActivity.java:123)
                                                                                at パッケージ名.MainActivity.checkPermission(MainActivity.java:112)
                                                                                at パッケージ名.MainActivity.onCreate(MainActivity.java:50)
                                                                                at android.app.Activity.performCreate(Activity.java:6285)
                                                                                at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
                                                                                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2408)
                                                                                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2541) 
                                                                                at android.app.ActivityThread.access$900(ActivityThread.java:169) 
                                                                                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1382) 
                                                                                at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                                at android.os.Looper.loop(Looper.java:148) 
                                                                                at android.app.ActivityThread.main(ActivityThread.java:5554) 
                                                                                at java.lang.reflect.Method.invoke(Native Method) 
                                                                                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:746) 
                                                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)

該当のソースコード

public class MainActivity extends Activity implements View.OnClickListener {
    private SurfaceView mySurfaceView;
    private Camera camera;
    private static final String TAG = "log";
    private SurfaceHolder holder = null;
    private boolean recording = false;
    MediaRecorder mediaRecorder;

    private final int REQUEST_PERMISSION = 1000;

    private Button btn1;
    private Button btn2;





    @Override
    protected void onCreate(Bundle savedInstanceState) {

        checkPermission();
        Log.v( "Check", "permission" );


        super.onCreate( savedInstanceState );
        File dirs = new File( "storage" );
        if (!dirs.exists()) {
            dirs.mkdir();
        }


    }
    private  void prepareCamera(){
            setContentView( R.layout.activity_main );
            btn1 = (Button) findViewById( R.id.button1 );
            btn1.setOnClickListener( this );

            btn2 = (Button) findViewById( R.id.rebtn );
            btn2.setOnClickListener( this );

            mySurfaceView = (SurfaceView) findViewById( R.id.surface_view );

            holder = mySurfaceView.getHolder();

            holder.addCallback( callback );
            Log.v( "Holder", "ok" );
            holder.setType( SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS );
            Log.v( TAG, "Holder" + holder );



        }




    private boolean checkPermission() {
        boolean camP;

        boolean recP;

        boolean strP;


        if (ActivityCompat.checkSelfPermission( this, Manifest.permission.CAMERA ) != PackageManager.PERMISSION_GRANTED) {
            camP=false;
        }else {
            camP=true;
        }

        if (ActivityCompat.checkSelfPermission( this, Manifest.permission.RECORD_AUDIO ) != PackageManager.PERMISSION_GRANTED) {
            recP=false;
        }else {
            recP=true;
        }
        if (ActivityCompat.checkSelfPermission( this, Manifest.permission.WRITE_EXTERNAL_STORAGE ) != PackageManager.PERMISSION_GRANTED) {

            strP=false;
        }else {
            strP=true;
        }

        requestPermissions(camP,recP,strP);
        Log.v( "request","permission" );
        return camP && recP && strP;

    }


    private void requestPermissions(boolean camP, boolean recP, boolean strP) {
            boolean pList[]= new boolean[2];
            pList[0] = camP;
            pList[1] = recP;
            pList[2] = strP;

        for (int i=0;i<pList.length;i++){
            if (pList[i]){
                switch (i){
                    case 0:
                        ActivityCompat.requestPermissions( MainActivity.this, new String[]{Manifest.permission.CAMERA}, REQUEST_PERMISSION );
                        break;
                    case 1:
                        ActivityCompat.requestPermissions( MainActivity.this, new String[]{Manifest.permission.RECORD_AUDIO}, REQUEST_PERMISSION );
                        break;
                    case 2:
                        ActivityCompat.requestPermissions( MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSION );
                        break;
                }
            }
        }


    }




    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == REQUEST_PERMISSION) {
            // 使用が許可された
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                prepareCamera();
                return;

            }
        }
    }



以下文字数の関係で省略。

試したこと

課題に対してアプローチしたことを記載してください
上記のソースコードは以下のサイトを参考にして書きました

https://akira-watson.com/android/runtime-permission.html

http://firespeed.org/diary.php?diary=kenz-1821

http://qiita.com/incheon/items/178cb540b697cd9419fd

補足情報(言語/FW/ツール等のバージョンなど)

環境:AndroidStudio2.1.1

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+3

onCreateでcheckPermissionの結果を見ないで処理を続けているので例外が発生していますね。
checkPermissionで1つでもパーミッションが不足している場合はパーミッションが必要な処理を行ってはいけません。

また、ダイアログが複数出るのは複数出すように記述しているので当たり前ですね。
ActivityCompat.requestPermissionsの第二引数の配列に不足しているパーミッションをまとめて指定するようにしてください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/26 17:39

    ありがとうございます。コードとエラーメッセージを更新しました。
    受け取った変数で配列をつくり、falseを検出したらパーミッションをリクエストするように処理を組んでみたのですがエラーが出てしまっています。配列の使用法にエラーが出ているようなのですが、配列の作り方に問題があるのでしょうか?

    キャンセル

  • 2016/08/27 13:46

    エラーメッセージを読んでください。
    配列にはついては自分で調べましょう。

    また、boolean型ではなくString型のパーミッションの配列にしてください。

    キャンセル

  • 2016/08/30 12:42

    ありがとうございます!無事に問題を解決することができました!この度は長いことお付き合いいただきありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.23%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる