これは Android 携帯電話のアップグレードに使用されます。現在は Android13 バージョンです。許可の問題により敏感になる可能性があります。しばらく前に、以前の方法は Android11 の新しいバージョンには適用できないことが開発によって判明しました。
読み取りおよび書き込み権限を申請する最善の方法は、設定にジャンプすることです。始めましょう。
1 つ目は AndroidManifest.xml ファイルの権限です。
<!-- android13的图片、音频、视频的权限-->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!--存储权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<!-- 打开相机权限-->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<!-- 网络权限-->
<uses-permission android:name="android.permission.INTERNET" />
次に、許可申請の状況について説明します。2つの状況があります。
最初のケースは、アクティビティで直接権限を申請することです。
2 番目のケースは、Fragment で許可を申請する場合です。
最初のケースはより単純で、android11 より前の許可アプリケーションによると、次のようになります。
//首先定义请求变量
private static final String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
//请求状态码,请求码的作用是与回调函数进行匹配的,这样就可以对不同权限操作进行不同的提示
private static final int REQUEST_EXTERNAL_STORAGE = 1;
//使用ActivityCompat.requestPermissions进行动态权限申请
ActivityCompat.requestPermissions(MainActivity.this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
//然后Activity会有一个回调函数,可以在这个回调函数做一些提示
//如下重写onRequestPermissionsResult方法
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { //申请文件读写权限
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_EXTERNAL_STORAGE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
havePermission = true;
Toast.makeText(this, "授权成功!", Toast.LENGTH_SHORT).show();
} else {
havePermission = false;
Toast.makeText(this, "授权被拒绝!", Toast.LENGTH_SHORT).show();
}
break;
case REQUEST_PERMISSION_CODE_33:
Toast.makeText(this, "授权成功!", Toast.LENGTH_SHORT).show();
break;
}
完全なコード例は次のとおりです
public class MainActivity extends AppCompatActivity {
private static final String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
//请求状态码
private static final int REQUEST_EXTERNAL_STORAGE = 1;
//创建Activity生命周期
protected void onCreate(Bundle savedInstanceState) {
}
//获取Activity焦点的生命周期
@Override
protected void onResume() {
super.onResume();
checkPermission();
}
private AlertDialog dialog;
private void checkPermission() {
//检查权限(NEED_PERMISSION)是否被授权 PackageManager.PERMISSION_GRANTED表示同意授权
//这里是android7以上就需要动态申请权限
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
//申请权限
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
dialog = new AlertDialog.Builder(this)
.setTitle("提示")//设置标题
.setMessage("请开启文件访问权限,否则无法正常使用应用!")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
ActivityCompat.requestPermissions(MainActivity.this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}
}).create();
dialog.show();
} else {
havePermission = true;
}
} else {
//android6以下不需要动态申请权限
havePermission = true;
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { //申请文件读写权限
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_EXTERNAL_STORAGE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
havePermission = true;
Toast.makeText(this, "授权成功!", Toast.LENGTH_SHORT).show();
} else {
havePermission = false;
Toast.makeText(this, "授权被拒绝!", Toast.LENGTH_SHORT).show();
}
break;
case REQUEST_PERMISSION_CODE_33:
Toast.makeText(this, "授权成功!", Toast.LENGTH_SHORT).show();
break;
}
以下は、Fragment で動的に権限を申請する 2 番目のケースです。Fragment は、Activity にアタッチされたページに相当するため、Fragment 内でのコールバック関数の処理はなく、そのため、Fragment が配置されている Activity のアクティビティ オブジェクトを使用する必要があります。たとえば、Fragment の定義は次のようになります。
public class PersonFragment extends Fragment {
//定义一个Activity对象,用于给MainActivity赋值
public static Activity context;
private static final String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.CAMERA};
//请求状态码
private static final int REQUEST_EXTERNAL_STORAGE = 1;
}
@Override
public void onStart() {
super.onStart();
checkPermission();
}
private AlertDialog dialog;
private void checkPermission() {
//检查权限(NEED_PERMISSION)是否被授权 PackageManager.PERMISSION_GRANTED表示同意授权
//这里是android7以上就需要动态申请权限
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
//申请权限
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
dialog = new AlertDialog.Builder(this)
.setTitle("提示")//设置标题
.setMessage("请开启文件访问权限,否则无法正常使用应用!")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
ActivityCompat.requestPermissions(context, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}
}).create();
dialog.show();
} else {
havePermission = true;
}
} else {
//android6以下不需要动态申请权限
havePermission = true;
}
}
次に、MainActivity で上記の Fragment にアクティビティ オブジェクトを割り当て、許可を申請する際に Fragment が MainActivity のコールバック関数を操作できるようにします。MainActivity のコード例は次のとおりです。
public class MainActivity extends AppCompatActivity {
//这里的请求码要和Fragment的请求码一致
private static final int REQUEST_EXTERNAL_STORAGE = 1;
//创建Activity生命周期
protected void onCreate(Bundle savedInstanceState) {
PersonFragment.context = MainActivity.this
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { //申请文件读写权限
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_EXTERNAL_STORAGE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
havePermission = true;
Toast.makeText(this, "授权成功!", Toast.LENGTH_SHORT).show();
} else {
havePermission = false;
Toast.makeText(this, "授权被拒绝!", Toast.LENGTH_SHORT).show();
}
break;
case REQUEST_PERMISSION_CODE_33:
Toast.makeText(this, "授权成功!", Toast.LENGTH_SHORT).show();
break;
}
上記の例は、一部の友達が理解していない人のために、パーミッションアプリケーションとコールバック関数の関係を説明するためのものです. 以下は、android7、android11、android13以下の動的パーミッションアプリケーションの状況です
1. ファイルの読み取りおよび書き込み権限がコードに直接アップロードされます
public class MainActivity extends AppCompatActivity {
//申请的权限放进数组里
private static final String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
//请求状态码
private static final int REQUEST_EXTERNAL_STORAGE = 1;
//创建Activity生命周期
protected void onCreate(Bundle savedInstanceState) {
}
//获取Activity焦点的生命周期
@Override
protected void onResume() {
super.onResume();
checkPermission();
}
private AlertDialog dialog;
private void checkPermission() {
//检查权限(NEED_PERMISSION)是否被授权 PackageManager.PERMISSION_GRANTED表示同意授权
//这里是android11以上的读写权限申请
//需要通过Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION跳转到权限设置打开权限
if (Build.VERSION.SDK_INT >= 30) {
if (!Environment.isExternalStorageManager()) {
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
dialog = new AlertDialog.Builder(this)
.setTitle("提示")//设置标题
.setMessage("请开启文件访问权限,否则无法正常使用本应用!")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
dialog.dismiss();
}
})
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivity(intent);
}
}).create();
dialog.show();
} else {
havePermission = true;
}
} else {
//这里就是android7到android11的权限申请
//直接通过ActivityCompat.requestPermissions就可以
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
//申请权限
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
dialog = new AlertDialog.Builder(this)
.setTitle("提示")//设置标题
.setMessage("请开启文件访问权限,否则无法正常使用应用!")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
ActivityCompat.requestPermissions(MainActivity.this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}
}).create();
dialog.show();
} else {
havePermission = true;
}
} else {
//android7以下的不需要动态申请权限
havePermission = true;
}
}
}
//权限申请成功后的回调函数,可以做提示或其他
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { //申请文件读写权限
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_EXTERNAL_STORAGE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
havePermission = true;
Toast.makeText(this, "授权成功!", Toast.LENGTH_SHORT).show();
} else {
havePermission = false;
Toast.makeText(this, "授权被拒绝!", Toast.LENGTH_SHORT).show();
}
break;
case REQUEST_PERMISSION_CODE_33:
Toast.makeText(this, "授权成功!", Toast.LENGTH_SHORT).show();
break;
}
}
2. フォトアルバムとカメラ権限の申請状況
Android 13 は、フォト アルバムを画像アプリケーション、ビデオ アプリケーション、オーディオ アプリケーションの 3 つの権限に分割しているため、ここで特別である可能性があります。
private static final String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA};
//请求状态码
private static final int REQUEST_EXTERNAL_STORAGE = 1;
//android13相册权限申请变量
private static final String[] PERMISSIONS_STORAGE_33 = {Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.READ_MEDIA_AUDIO, Manifest.permission.READ_MEDIA_VIDEO, Manifest.permission.CAMERA};
//请求状态码
private static final int REQUEST_PERMISSION_CODE_33 = 2;
権限配列は異なる場合があります。android13 以下の読み取りおよび書き込み権限を適用するだけで十分ですが、android13 はこれら 3 つの権限を動的に適用する必要がある場合があるため、コードは次のとおりです。ここでは Fragment を使用して権限を適用します。
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
@SuppressLint("StaticFieldLeak")
public class PersonFragment extends Fragment {
//MainActivity的activity对象
public static Activity context;
@Override
public void onStart() {
super.onStart();
ifHaveAlbumPermission(context)
}
//打开相册
private void openFile() {
Intent intentFromGallery = new Intent();
// 设置文件类型
intentFromGallery.setType("image/*");//选择图片
intentFromGallery.setAction(Intent.ACTION_GET_CONTENT);
//你需要使用系统提供的startActivityForResult(Intent intent,int requestCode)方法调用MainActivity的回调函数
context.startActivityForResult(intentFromGallery, REQUEST_PICTURE_CODE);
}
// 判断是否有文件存储权限
private void ifHaveAlbumPermission(Activity activity) {
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) {
//android13权限申请
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE_33, REQUEST_PERMISSION_CODE_33);
openFile();
} else {
//android13以下的权限申请
ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}
} else {
openFile();
}
}
}
上記はほぼ完成です、カメラの状況は似ています、他のブロガーが書いたものを読むことができます