Android M権限:onRequestPermissionsResult()が呼び出されない


291

新しいMランタイム権限システムを使用するようにアプリを更新しています。onRequestPermissionsResult()を除いてすべて機能しています。ボタンを押す許可を確認する必要があります。それが成功した場合は、テキストメッセージを送信します。実行する許可を与えると、ダイアログは閉じますが、もう一度ボタンを押すまで、テキストの送信はトリガーされません。

私はデバッグしてonRequestPermissionsResult()メソッドにブレークポイントを設定しましたが、その中には入りません。

このメソッドが最初に呼び出されます。

    private void askForPermission() {
    String[] permissions = new String[]{Manifest.permission.SEND_SMS};
    ActivityCompat.requestPermissions(getActivity(), permissions, PERMISSIONS_CODE);
}

そして、私のコールバックは次のようになります:

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

    if (requestCode == PERMISSIONS_CODE) {
        for (int i = 0; i < permissions.length; i++) {
            String permission = permissions[i];
            int grantResult = grantResults[i];

            if (permission.equals(Manifest.permission.SEND_SMS)) {
                if (grantResult == PackageManager.PERMISSION_GRANTED) {
                    onPPSButtonPress();
                } else {
                    requestPermissions(new String[]{Manifest.permission.SEND_SMS}, PERMISSIONS_CODE);
                }
            }
        }
    }
}

誰かが同様の問題に遭遇しましたか?これでどんな助けにも感謝します。ありがとう

回答:


576

同じ問題に遭遇し、解決策を見つけました。サポートライブラリを使用する場合は、正しいメソッド呼び出しを使用する必要があります。例えば:

  • AppCompatActivityの場合は、ActivityCompat.requestPermissionsを使用する必要があります。
  • android.support.v4.app.Fragmentの場合、単純にrequestPermissionsを使用する必要があります(これはandroid.support.v4.app.Fragmentのインスタンスメソッドです)

フラグメントでActivityCompat.requestPermissionsを呼び出すと、フラグメントではなくアクティビティでonRequestPermissionsResultコールバックが呼び出されます。

お役に立てれば!



11
「android.support.v4.app.Fragmentの場合は、単にrequestPermissionsを使用する必要があります」-ありがとうございます。
Tigran Sarkisian、2015年

5
@AnthonyBobenriethでは、noHistory活動家のためのここでの解決策は何ですか?彼らに許可を要求することはできませんか?
ディーンワイルド

2
リンクが壊れています@AnthonyBobenrieth。歴史がないための解決策はありますか?
fersarr 2016年

3
を使用するFragment.requestPermissions()場合、親アクティビティは実際にを受け取りますonRequestPermissionsResult()。(これはサポートライブラリ23.3.0に含まれています)
誰かがどこか

101

あなたはこれを試すことができます:

requestPermissions(permissions, PERMISSIONS_CODE);

このコードをフラグメントから呼び出す場合は、独自のrequestPermissionsメソッドがあります。問題は、静的メソッドを呼び出していることだと思います。

onRequestPermissionsResult()断片化したい場合のプロのヒント: FragmentCompat.requestPermissions(Fragment fragment, String[] permissions, int requestCode)


助けてくれてありがとう。フラグメント内にある場合、requestPermissionsメソッドがあることに気付きました。私は断片化していて、requestPermissionsだけを呼び出そうとしましたが、残念ながら機能しませんでした。私もあなたが言ったことを試してみましたが、それもうまくいきませんでした。
AndyOHart 2015

これはAndroid Mで私には有効でした。しかし、それがPre-Mデバイスで問題を引き起こすかどうか疑問に思っていますか?
Bala Vishnu、

4
@goodgamerguyは、アクティビティのonRequestPermissionsResultでリクエストコードを使用しないようにしてください。アクティビティでonRequestPermissionsResultコールバックも使用する場合は、デフォルトを提供する必要があります。
Timmy Simons

68

私はそれがうまくいくことを願っています

活動:

 ActivityCompat.requestPermissions(this,permissionsList,REQUEST_CODE);

フラグメントの場合:

 requestPermissions(permissionsList,REQUEST_CODE);

SDK 15以前はどうですか?
zulkarnain shah 2017

4
あなたは、唯一のマシュマロと上記のバージョンの必要性.. SDK 15について許可を必要としない
サンジャイMangaroliya

50

私もこの問題に遭遇しました。履歴/最近のものではない権限を処理するアクティビティが必要な場合、あなたはあなたを変更したくなるでしょうAndroidManifest.xmlエントリ。

あなたが呼び出すrequestPermissionsまたはAppCompatActivity.requestPermissionsと一緒に 活動を設定した場合

android:noHistory="true"
android:excludeFromRecents="true"

あなたのAndroidManifest.xml当時onRequestPermissionsResult()は呼ばれません。これは、アクティビティがから派生したActivity場合、またはAppCompatActivity

これは、「AndroidManifest.xml」から両方のフラグを削除し、finishAndRemoveTask()代わりにアクティビティを終了することで修正できます。


noHistory属性を削除する必要はありませんでしたが、これが私に役立つ解決策でした。ありがとう!
エリックシュレンツ16

1
マシュマロでは問題がありましたが、ヌガーでは問題がありませんでした。問題なく機能しました
Yohan Dahmani

37

onRequestPermissionsResultアクティビティとフラグメントの両方を使用している場合は、必ずsuper.onRequestPermissionsResultアクティビティを呼び出してください。フラグメントでは必要ありませんが、アクティブです。


また、API(19など)をターゲットにした場合でも、古いアクセス許可モデルシステムの下にあるため、アクセス許可関連の関数呼び出しを要求されないことに注意してください
Bonatti

superを呼び出さない別のアクティビティを拡張した場合は、私の回答を参照してください
TouchBoarder

3
これにつまずいた。FragmentActivity.onRequestPermissionsResult(..)フラグメントへの呼び出しonRequestPermissionsResult(..)が転送される場所です。
JanPl

@Bonattiでは、Android 4.4.2で権限をリクエストしようとすると、結果が得られません。したがって、権限を変更することはできません。それらを表示するだけですか?
Alex Fragotsis

@AlexanderFragotsis結果が表示されます。唯一の違いは、許可を付与するように求められることはなく、システムによって自動的に付与されることです。
Dusan Zivkovic

33

非推奨の回答を参照してください: https //developer.android.com/training/permissions/requesting

フラグメント内では、次を呼び出す必要があります。

FragmentCompat.requestPermissions(permissionsList, RequestCode)

ない:

ActivityCompat.requestPermissions(Activity, permissionsList, RequestCode);

2
android.support.v13.app.FragmentCompatに関連
Udi Oshi

1
FragmentCompatはAPI 27.1.0で非推奨になりました。
Big McLargeHuge

私の回答は非推奨です。参照してください:developer.android.com/training/permissions/requesting
Ben.Slama.Jihed

15

requestPermissionsをフラグメントで使用している場合、3つではなく2つのパラメーターを受け入れます。

あなたは使うべきです requestPermissions(permissions, PERMISSIONS_CODE);


1
実際、それは質問に対する答えを提供します。ActivityCompat.requestPermissionsの代わりにrequestPermissions(フラグメントのインスタンスメソッド)を呼び出すと、結果メソッドがトリガーされます。ここで主な問題です。ありがとうドン
Waclock

15

何らかの理由で、スーパーを呼び出さない外部ライブラリにあるカスタムアクティビティを拡張した場合は、アクティビティのonRequestPermissionsResultでフラグメントsuper.onRequestPermissionsResultを手動で呼び出す必要があります。

YourActivity extends SomeActivityNotCallingSuperOnRequestPermissionsResult{
Fragment requestingFragment;//the fragment requesting the permission
...
@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(requestingFragment!=null)
            requestingFragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
...

12

FragmentCompatには、マシュマロ以前のデバイス用のcheckPermissions関数があります。私はこのように使用します:

FragmentCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);

2
これは、android.app.fragment内で権限が要求され、support-v13ライブラリをインポートする必要がある場合にのみ機能します。
MohammadReza

4
FragmentCompat.requestPermissions()は、android.support.v4.app.Fragmentでは機能しません。誰でもこれを処理する方法を知っています。
ジュティコーン

12

私は、あなたがどこで電話をかけるかが重要であることを知りましたandroid.support.v4.app.Fragment.requestPermissions

で行う場合onCreate()onRequestPermissionsResult()呼び出されることはありません。

解決策:で呼び出しonActivityCreated()ます。

@Override
public void onActivityCreated(Bundle savedInstanceState) {

    super.onActivityCreated(savedInstanceState);

    if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_DENIED) 
        requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, 0);

}

1
同じ問題に直面していますonActivityCreated()が、コードを取得できません。SDK 23.
kAmol 2016


私は断片化されていません。アクティビティのonCreateで実行しようとしています
kAmol

うーん、それとも使うonPause()
almisoft 2016

10

この問題は実際にはNestedFragmentsが原因でした。基本的に、私たちが持っているほとんどのフラグメントは、CompatFragmentを拡張するHostedFragmentを拡張しています。これらのネストされたフラグメントがあると問題が発生し、プロジェクトの別の開発者によって最終的に解決されました。

彼はこれを機能させるためにビット切り替えのようないくつかの低レベルのことをしていたので、私は実際の最終的な解決策をあまり確信していません


これは私の問題の解決に役立ちました。onRequestPermissionsResultを親フラグメントから子(ネストされた)フラグメントにリダイレクトする必要がありました。先端をありがとう!
マーフィー

9
 /* use the object of your fragment to call the 
 * onRequestPermissionsResult in fragment after
 * in activity and use different request Code for 
 * both Activity and Fragment */

   if (isFragment)
    mFragment.requestPermissions(permissions.toArray(new
    String[permissions.size()]),requestPermission);

   else
    ActivityCompat.requestPermissions(mActivity,permissions.toArray(new
    String[permissions.size()]),requestPermission);

6

これは動作します。

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

スーパー実装は、フレームワークではなくフラグメント実装を呼び出します
Mohammad Yahia

5

このコードをフラグメントから呼び出す場合は、独自のrequestPermissionsメソッドがあります。

基本的なコンセプトは、あなたがアクティビティにいるなら、

ActivityCompat.requestPermissions(this,
                            permissionsList,
                            permissionscode);

フラグメントの場合は、呼び出すだけ

requestPermissions(permissionsList,
                            permissionscode);

1
APIレベル23が必要です...以前のバージョンではを使用しますFragmentCompat.requestPermissions()
Minas Mina

5

同様の問題がありましたが、ボタンを押して電話をかけると、callIntentがトリガーされました。最初に権限を確認しました。許可されていない場合は、権限を要求し、onRequestPermissionResultで確認権限を呼び出して、もう一度呼び出します。

 @Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case Constants.PERMISSIONS_REQUEST_CALL_PHONE: {
            if ( grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                checkPermissionsAndCall();
            }
        }
    }
}

public void checkPermissionsAndCall(){
    if (Build.VERSION.SDK_INT > 22) {
        if(ContextCompat.checkSelfPermission(getContext(),
                Manifest.permission.CALL_PHONE)
                != PackageManager.PERMISSION_GRANTED){
            requestPermissions( new String[]{Manifest.permission.CALL_PHONE}, Constants.PERMISSIONS_REQUEST_CALL_PHONE);
        }
        else{
            callIntent();
        }
    }
}


2

上記の回答に従ってすべてを確認する前に、リクエストコードが0ではないことを確認してください!!!

FragmentActivity.javaのonRequestPermissionsResult()のコードを確認します。

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
        @NonNull int[] grantResults) {
    int index = (requestCode>>16)&0xffff;
    if (index != 0) {
        index--;

        String who = mPendingFragmentActivityResults.get(index);
        mPendingFragmentActivityResults.remove(index);
        if (who == null) {
            Log.w(TAG, "Activity result delivered for unknown Fragment.");
            return;
        }
        Fragment frag = mFragments.findFragmentByWho(who);
        if (frag == null) {
            Log.w(TAG, "Activity result no fragment exists for who: " + who);
        } else {
            frag.onRequestPermissionsResult(requestCode&0xffff, permissions, grantResults);
        }
    }
}

2
private void showContacts() {
    if (getActivity().checkSelfPermission(Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {
        requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, PERMISSIONS_REQUEST_READ_CONTACTS);
    } else {
        doShowContacts();
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        doShowContacts();
    }
}

2

これを達成するための素晴らしいソリューションがあり、BaseActivityをこのようにします。

public class BaseActivity extends AppCompatActivity {

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this));


}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
    switch (requestCode) {
        case 1: {
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                CustomToast.getInstance().setCustomToast("Now you can share the Hack.");

            } else {
                Toast.makeText(this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

}

これで、コードを呼び出して、このような許可を求めることができます

 ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);

これがフラグメントやアクティビティのどこにでも発生するたびに、ベースアクティビティが呼び出されます。

ありがとう


1

使用できますrequestPermissions(PERMISSIONS, MULTIPLE_PERMISSIONS_CODE);。v4を使用している場合は、FragmentCompatを使用しないでください。


理由を詳しく説明してください。
2018

1

細部

  • コトリン1.2.70
  • minSdkVersion 19でチェックイン
  • Android Studio 3.1.4

アルゴリズム

モジュール -カメラ、場所、...

  1. hasSystemFeature(モジュールが電話に存在する場合)を確認します
  2. ユーザーがモジュールにアクセスできるかどうかを確認する
  3. 権限要求を送信します(モジュールの使用を許可するようユーザーに要求します)

特徴

  1. アクティビティとフラグメントを操作する
  2. 結果の応答は1つだけです
  3. 1つのリクエストで複数のモジュールをチェックできます

解決

class PermissionType(val manifest_permission: String, val packageManager: String) {
    object Defined {
        val camera = PermissionType(Manifest.permission.CAMERA, PackageManager.FEATURE_CAMERA)
        val currentLocation = PermissionType(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.FEATURE_LOCATION_GPS)
    }
}

class  Permission {

    enum class PermissionResult {
        ACCESS_ALLOWED, ACCESS_DENIED, NO_SYSTEM_FEATURE;
    }

    interface ManagerDelegate {
        fun permissionManagerDelegate(result: Array<Pair<String, PermissionResult>>)
    }

    class Manager internal constructor(private val delegate: ManagerDelegate?) {

        private var context: Context? = null
        private var fragment: Fragment? = null
        private var activity: AppCompatActivity? = null
        private var permissionTypes: Array<PermissionType> = arrayOf()
        private val REQUEST_CODE = 999
        private val semaphore = Semaphore(1, true)
        private var result: Array<Pair<String, PermissionResult>> = arrayOf()


        constructor(permissionType: PermissionType, delegate: ManagerDelegate?): this(delegate) {
            permissionTypes = arrayOf(permissionType)
        }

        constructor(permissionTypes: Array<PermissionType>, delegate: ManagerDelegate?): this(delegate) {
            this.permissionTypes = permissionTypes
        }

        init {
            when (delegate) {
                is Fragment -> {
                    this.fragment = delegate
                    this.context = delegate.context
                }

                is AppCompatActivity -> {
                    this.activity = delegate
                    this.context = delegate
                }
            }
        }

        private fun hasSystemFeature(permissionType: PermissionType) : Boolean {
            return context?.packageManager?.hasSystemFeature(permissionType.packageManager) ?: false
        }

        private fun hasAccess(permissionType: PermissionType) : Boolean {
            return if (Build.VERSION.SDK_INT < 23) true else {
                context?.checkSelfPermission(permissionType.manifest_permission) == PackageManager.PERMISSION_GRANTED
            }
        }

        private fun sendRequest(permissionTypes: Array<String>) {

            if (fragment != null) {
                fragment?.requestPermissions(permissionTypes, REQUEST_CODE)
                return
            }

            if (activity != null){
                ActivityCompat.requestPermissions(activity!!, permissionTypes, REQUEST_CODE)
            }
        }

        fun check() {

            semaphore.acquire()
            AsyncTask.execute {
                var permissionsForSendingRequest: Array<String> = arrayOf()
                this.result = arrayOf()

                for (it in permissionTypes) {
                    if (!hasSystemFeature(it)) {
                        result += Pair(it.manifest_permission, PermissionResult.NO_SYSTEM_FEATURE)
                        continue
                    }

                    if (hasAccess(it)) {
                        result += Pair(it.manifest_permission, PermissionResult.ACCESS_ALLOWED)
                    } else {
                        permissionsForSendingRequest += it.manifest_permission
                    }
                }

                if (permissionsForSendingRequest.isNotEmpty()) {
                    sendRequest(permissionsForSendingRequest)
                } else {
                    delegate?.permissionManagerDelegate(result)
                }
            }
        }

        fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
            when (requestCode) {
                REQUEST_CODE -> {
                    if (grantResults.isEmpty()) {
                        return
                    }
                    for ((i,permission) in permissions.withIndex()) {
                        for (item in this.permissionTypes) {
                            if (permission == item.manifest_permission && i < grantResults.size) {
                                result += if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                                    Pair(item.manifest_permission, PermissionResult.ACCESS_ALLOWED)
                                } else {
                                    Pair(item.manifest_permission, PermissionResult.ACCESS_DENIED)
                                }
                                break
                            }
                        }
                    }
                    delegate?.permissionManagerDelegate(result)
                }
            }
            semaphore.release()
        }
    }
}

アクティビティでの使用(同じフラグメント)

class BaseActivity : AppCompatActivity(), Permission.ManagerDelegate {

    private lateinit var permissionManager: Permission.Manager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.base_activity)

        permissionManager = Permission.Manager(arrayOf(PermissionType.Defined.camera, PermissionType.Defined.currentLocation), this)
        permissionManager.check()
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        permissionManager.onRequestPermissionsResult(requestCode, permissions, grantResults)
    }


    override fun permissionManagerDelegate(result: Array<Pair<String, Permission.PermissionResult>>) {
        result.forEach {
            println("!!! ${it.first} ${it.second}")
//            when (it.second) {
//                Permission.PermissionResult.NO_SYSTEM_FEATURE -> {
//                }
//
//                Permission.PermissionResult.ACCESS_DENIED  -> {
//                }
//
//                Permission.PermissionResult.ACCESS_ALLOWED -> {
//                }
//            }
        }
    }
}

1

ここで、これをどのように管理したかをコードに示します。

public class CheckPermission {

public Context context;

public static final int PERMISSION_REQUEST_CODE =  200;

public CheckPermission(Context context){
    this.context = context;
}

public boolean isPermissionGranted(){
    int read_contact = ContextCompat.checkSelfPermission(context.getApplicationContext() , READ_CONTACTS);
    int phone = ContextCompat.checkSelfPermission(context.getApplicationContext() , CALL_PHONE);

    return read_contact == PackageManager.PERMISSION_GRANTED && phone == PackageManager.PERMISSION_GRANTED;
   }
}

このクラスでは、許可されているかどうかを確認したいと思います。そうでない場合、私はMainActivityのような許可を呼び出します

public void requestForPermission() {
       ActivityCompat.requestPermissions(MainActivity.this, new String[]    {READ_CONTACTS, CALL_PHONE}, PERMISSION_REQUEST_CODE);
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case PERMISSION_REQUEST_CODE:
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)) {
                    showMessageOKCancel("You need to allow access to both the permissions",
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                        requestPermissions(new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.CALL_PHONE},
                                                PERMISSION_REQUEST_CODE);
                                    }
                                }
                            });
                    return;
                }
            }
    }
}

次に、onCreateメソッドで、requestForPermission()関数を呼び出す必要があります。

また、一度に複数の権限をリクエストすることもできます。


1

更新:super.onRequestPermissionResult()アクティビティの呼び出しに関する他の誰かの回答を見ました。これにより、前述のリクエストコードの問題が修正され、フラグメントのonRequestPermissionResultが呼び出されます

このものを無視してください:

私にとって、それは私が呼び出すにonRequestPermissionResultもかかわらず、活動のfragment.requestPermission(...)、不正なrequestCodeで結果を返しました(111が65647に変わった理由は???私にはわかりません)。

幸いなことに、これはその画面で要求する唯一のアクセス許可なので、要求コードを無視します(現時点で正しくない理由を理解する時間はありません)。


65536と111を追加すると、取得されます。これはビットマスクが原因です。いくつかのトピックを参照してください。
CoolMind 2018

0

また、正しいrequestPermissionsを呼び出しても、この問題が発生する可能性があるという問題にも遭遇しました。問題は、親アクティビティがsuperを呼び出さずにこのメソッドをオーバーライドする可能性があることです。スーパーを追加すると修正されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.