新しいM Permissionsシステムを使用するようにアプリを更新しています。 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);
}
}
}
}
}
誰かが似たような問題に遭遇したことがありますか?これでどんな助けでも感謝します。ありがとう
この問題は実際にはNestedFragmentsによって引き起こされていました。基本的にほとんどのフラグメントはHostedFragmentを拡張し、それがCompatFragmentを拡張します。これらの入れ子になった断片を持つことは、プロジェクトの他の開発者によって結局解決された問題を引き起こしました。
彼はこれを機能させるためにビット切り替えのようないくつかの低レベルのことをしていたので、私は実際の最終的な解決策についてはあまりわかりません。
私は同じ問題に遭遇しました、そして、私はちょうどその解決策を見つけました。サポートライブラリを使用するときは、正しいメソッド呼び出しを使用する必要があります。例えば:
フラグメント内でActivityCompat.requestPermissionsを呼び出すと、フラグメントに対してではなく onRequestPermissionsResult コールバックが呼び出されます。
お役に立てれば!
これを試すことができます:
requestPermissions(permissions, PERMISSIONS_CODE);
あなたがフラグメントからこのコードを呼んでいるならば、それはそれ自身のrequestPermissionsメソッドを持っています。私は問題はあなたが静的メソッドを呼んでいるということだと思います。
onRequestPermissionsResult()
をフラグメントにしたい場合はPro Tip:FragmentCompat.requestPermissions(Fragment fragment, String[] permissions, int requestCode)
うまくいくことを願っています
活動のために:
ActivityCompat.requestPermissions(this,permissionsList,REQUEST_CODE);
フラグメントの場合:
requestPermissions(permissionsList,REQUEST_CODE);
私もこの問題に遭遇しました。あなたがhistory/recentsにないパーミッションを処理するアクティビティが欲しいなら、あなたはあなたのAndroidManifest.xml
エントリを変更したくなるでしょう。
requestPermissions
またはAppCompatActivity.requestPermissions
を呼び出すアクティビティを次のように設定したとします。
Android:noHistory="true"
Android:excludeFromRecents="true"
あなたのAndroidManifest.xml
ではonRequestPermissionsResult()
は呼ばれません。あなたのActivityがActivity
またはAppCompatActivity
から派生している場合、これは当てはまります。
これは、 'AndroidManifest.xml'から両方のフラグを削除し、代わりにfinishAndRemoveTask()
でアクティビティを終了することで解決できます。
アクティビティとフラグメントの両方にonRequestPermissionsResult
がある場合は、必ずアクティビティでsuper.onRequestPermissionsResult
を呼び出してください。フラグメントでは必要ありませんが、活動中です。
フラグメント内部では、呼び出す必要があります:
FragmentCompat.requestPermissions(permissionsList, RequestCode)
ではない:
ActivityCompat.requestPermissions(Activity, permissionsList, RequestCode);
フラグメントでrequestPermissionsを使用している場合は、3ではなく2つのパラメーターを受け入れます。
requestPermissions(permissions, PERMISSIONS_CODE);
を使うべきです
何らかの理由でsuperを呼び出さない外部ライブラリにあるカスタムActivityを拡張した場合は、Activity onRequestPermissionsResultでFragment 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);
}
...
FragmentCompat には、以前のMarshmallowデバイス用の checkPermissions 関数があります。私はこのように使用します:
FragmentCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
私はあなたが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);
}
/* 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);
これは動作します。
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
このコードをフラグメントから呼び出す場合は、独自のrequestPermissionsメソッドがあります。
ですから、基本的な考え方は、あなたが活動の中にいるのなら、電話をすることです。
ActivityCompat.requestPermissions(this,
permissionsList,
permissionscode);
そして、もしフラグメントの中にいれば、ただ呼ぶだけです。
requestPermissions(permissionsList,
permissionscode);
私はコールを発信するためにボタンを押していたことを除いて同様の問題を抱えていました。それは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();
}
}
}
私はこれを達成するための素晴らしい解決策をこのような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);
これはあなたのフラグメントの中でも任意のアクティビティの中でも基本的なアクティビティが呼ばれることになるかどうかに関わらずいつでも起こります。
ありがとう
上記の回答に従ってすべてを確認する前に、リクエストコードが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);
}
}
}
goodgamerguyの回答に基づく 解決策は次のとおりです。
myFragment.this.requestPermissions(....)
更新:Activityでsuper.onRequestPermissionResult()を呼び出すことについての他の誰かの答えを見ました、そしてそれは私が述べたリクエストコード問題を修正して、そしてフラグメントのonRequestPermissionResultを呼び出します。
このことを無視してください。
Fragment.requestPermission(...)を呼び出したにもかかわらず、ActivityのonRequestPermissionResultを呼び出していましたが、間違ったrequestCodeで結果が返されました(111が65647になった理由はわかりません)。
幸いなことに、これはその画面上で要求する唯一の許可なので、要求コードは無視します(なぜそれが今正しくないのかを理解する時間がありません)。
モジュール - カメラ、場所、....
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 -> {
// }
// }
}
}
}
requestPermissions(PERMISSIONS, MULTIPLE_PERMISSIONS_CODE);
を使うことができます。 v4を使用している場合はFragmentCompatを使用しないでください。
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();
}
}
ここで私はこれをどうやって管理したかを自分のコードに見せたい。
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()関数を呼び出す必要があります。
それはそれです。また、一度に複数の権限を要求することができます。