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

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

ただいまの
回答率

91.37%

  • Android

    5155questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

PermissionsDispatcherの使い方について

解決済

回答 1

投稿 2017/11/30 16:54 ・編集 2017/12/03 16:35

  • 評価
  • クリップ 0
  • VIEW 35

komon4242

score 5

いつもお世話になっています。

Androidの端末ストレージから画像を読込む処理が必要なためpermission.READ_EXTERNAL_STORAGEを許可するMパーミッション対応を行いました。

Mパーミッションの実装はPermissonDispatcherを使用させて頂きました。
https://qiita.com/kazy/items/0ded30d80cef9df54c98 を参考にさせていただきました。

以下の様に変更しました(gradleの設定は省略しています)

import android.Manifest;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.widget.CursorAdapter;
import android.widget.GridView;

import permissions.dispatcher.NeedsPermission;
import permissions.dispatcher.RuntimePermissions;
/*
 *
 * 端末のストレージから画像を読み込むために READ_EXTERNAL_STORAGE のMパーミッション対応をしています。
 * Mパーミッション実装のためにPermissionsDispatcherを利用しています。
 *
*/

@RuntimePermissions
public class MainActivity extends AppCompatActivity {

    private GridView mGridView = null;

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

        // パーミッションの要求
        MainActivityPermissionsDispatcher.onCreateWithPermissionCheck(this, savedInstanceState);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);

        // ここで Cursor を使って端末ストレージから画像を取得する
    }
}

起動してパーミッションの許可を求めるダイアログの表示まではうまくいきました。
しかしパーミッションの「許可」を行った所、onRequestPermissionsResultでエラーが起きて落ちました。

11-30 16:45:20.880 26358-26358/hoge.example.com.gridviewapplication E/AndroidRuntime: FATAL EXCEPTION: main
      Process: hoge.example.com.gridviewapplication, PID: 26358
      java.lang.RuntimeException: Failure delivering result ResultInfo{who=@android:requestPermissions:, request=0, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {hoge.example.com.gridviewapplication/hoge.example.com.gridviewapplication.MainActivity}: java.lang.IllegalStateException: Already attached
          at android.app.ActivityThread.deliverResults(ActivityThread.java:3699)
          at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
          at android.app.ActivityThread.-wrap16(ActivityThread.java)
          at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
          at android.os.Handler.dispatchMessage(Handler.java:102)
          at android.os.Looper.loop(Looper.java:148)
          at android.app.ActivityThread.main(ActivityThread.java:5417)
          at java.lang.reflect.Method.invoke(Native Method)
          at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
       Caused by: java.lang.IllegalStateException: Already attached
          at android.support.v4.app.FragmentManagerImpl.attachController(FragmentManager.java:2939)
          at android.support.v4.app.FragmentController.attachHost(FragmentController.java:104)
          at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:275)
          at android.support.v7.app.AppCompatActivity.onCreate(AppCompatActivity.java:84)
          at hoge.example.com.gridviewapplication.MainActivity.onCreate(MainActivity.java:31)
          at hoge.example.com.gridviewapplication.MainActivityPermissionsDispatcher$MainActivityOnCreatePermissionRequest.grant(MainActivityPermissionsDispatcher.java:71)
          at hoge.example.com.gridviewapplication.MainActivityPermissionsDispatcher.onRequestPermissionsResult(MainActivityPermissionsDispatcher.java:36)
          at hoge.example.com.gridviewapplication.MainActivity.onRequestPermissionsResult(MainActivity.java:61)
          at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:6582)
          at android.app.Activity.dispatchActivityResult(Activity.java:6460)
          at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
          at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742) 
          at android.app.ActivityThread.-wrap16(ActivityThread.java) 
          at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393) 
          at android.os.Handler.dispatchMessage(Handler.java:102) 
          at android.os.Looper.loop(Looper.java:148) 
          at android.app.ActivityThread.main(ActivityThread.java:5417) 
          at java.lang.reflect.Method.invoke(Native Method) 

「何度も呼んでんじゃねぇよ!」的なエラーですが、これはどうすれば解決しますか?
try ~ catch で投げるしかないのでしょうか?

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • keicha_hrs

    2017/12/02 03:41 編集

    記事見出し及び本文中のPermissonDispatcherの綴りが微妙に誤っていますので、修正していただけると今後の閲覧者のためにもなるかと思います(解決済になってしまうと直せないのかな?)。

    キャンセル

  • komon4242

    2017/12/03 16:33

    ご指摘ありがとうございます。修正できるかやってみます。

    キャンセル

回答 1

check解決した方法

0

考え方が間違っていました。

@NeedsPermission(Manifest.permission.READ_EXTERNAL_STORAGE)をMパーミッションの要求が呼ばれるメソッドで呼ぶものだと思い込んでいました。
実際は、許可した場合に呼び出すメソッドを認識させるためのアノテーションでした。
書き直しましたのでこれで解決とさせて下さい。

@RuntimePermissions
public class MainActivity extends AppCompatActivity {


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

        MainActivityPermissionsDispatcher.getThumbnailWithPermissionCheck(this);
    }

    // 許可した場合はこっちが呼ばれる(一度許可すれば設定で制限を外すまでこちらが呼ばれる)
    @NeedsPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
    void getThumbnail() {
        // TODO: ここにサムネイルを取得した時の処理を書く
    }

    // 絶対に表示しない状態で呼ばれる
    @OnNeverAskAgain(Manifest.permission.READ_EXTERNAL_STORAGE)
    void onNeverAskAgain() {
        Toast.makeText(this, "call @OnNeverAskAgain", Toast.LENGTH_SHORT).show();
    }

    // 許可しない状態の時に呼ばれる(onNeverAskAgain -> onRequestPermissionsResult)
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);

        Toast.makeText(this, "call onRequestPermissionsResult", Toast.LENGTH_SHORT).show();
    }

    // 許可しない
    @OnShowRationale(Manifest.permission.READ_EXTERNAL_STORAGE)
    void onShowRationale(final PermissionRequest request) {
        Toast.makeText(this, "call @OnShowRationale", Toast.LENGTH_SHORT).show();

        new AlertDialog.Builder(this)
                .setTitle("警告")
                .setMessage("ストレージの権限を許可しないとサムネイルを取得することが出来ません。アプリを使いたい場合は許可して下さい。")
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // パーミッション許可ダイアログ
                        request.proceed();
                    }
                })
                .setNegativeButton("Cancel", null)
                .show();
    }
}

投稿 2017/12/01 17:08

編集 2017/12/05 13:32

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

ただいまの回答率

91.37%

関連した質問

同じタグがついた質問を見る

  • Android

    5155questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。