问题描述
我在Android Studio中启动了一个新项目,该项目包括:空活动,Java,API 29,Android 10.0(Q)
我向AndroidManifest.xml添加了权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
我在activity_main.xml中添加了ImageView和一个按钮
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="80dp"
android:text="button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/my_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button"
/>
我在MainActivity.java中加载了一个图像-单击按钮后,将在运行时检查权限。然后,在另一个按钮上单击后,应查看图像。该代码还包含对正确活动的一些检查。
package mrppanther.com.example.read_image;
import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import java.io.File;
public class MainActivity extends AppCompatActivity {
private int STORAGE_PERMISSION_CODE = 1;
private int new_state = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// NOTE: use a button to request activity
Button buttonRequest = findViewById(R.id.button);
buttonRequest.setonClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// NOTE: declare "myfile",this is want I want to view
File myfile = new File("/storage/emulated/0/Pictures/henry1.jpg");
// NOTE: on the 1st click,check permissions
if (new_state == 1) {
requestStoragePermission();
new_state = 2; // NOTE: move to the next state,on the next click
// NOTE: on the 2nd click,view image
} else {
// NOTE: check that the "myfile"" exists
if (myfile.exists()) {
Log.i("myfile","FILE EXISTS PASS! " + myfile);
} else {
Log.i("myfile","FILE ABSENT FAIL! " + myfile);
}
// NOTE: declare "myimage"
ImageView myimage = (ImageView) findViewById(R.id.my_image);
// NOTE: experimenting with options did not help
BitmapFactory.Options options=new BitmapFactory.Options();
//options.inJustDecodeBounds=true;
options.inSampleSize=1;
// ERROR: E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException:
// ERROR: /storage/emulated/0/Pictures/henry1.jpg: open Failed: EACCES (Permission denied)
Bitmap bitmap = BitmapFactory.decodeFile(String.valueOf(myfile),options);
myimage.setimageBitmap(bitmap);
// NOTE: here is a test to check "myimage" is correct
// NOTE: this works OK,and image from drawable resource is displayed
// myimage.setimageResource(R.drawable.henry1);
new_state = 1; // NOTE: go back to the 1st state,on the next click
}
}
}); // NOTE: this is the end of button activity
}
// NOTE: request permission to read storage,at run time
private void requestStoragePermission() {
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE},STORAGE_PERMISSION_CODE);
// NOTE: here is a test which sets the wrong permission
// new String[]{Manifest.permission.READ_PHONE_NUMBERS,Manifest.permission.READ_PHONE_STATE},STORAGE_PERMISSION_CODE);
}
// NOTE: check read permission is granted,at run time
@Override
public void onRequestPermissionsResult(int requestCode,@NonNull String[] permissions,@NonNull int[] grantResults) {
if (requestCode == STORAGE_PERMISSION_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this,"Permission GRANTED",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,"Permission DENIED",Toast.LENGTH_SHORT).show();
}
}
}
}
结果:我看到了以下错误消息,但未显示图像。 但是,运行时权限检查指示为“权限已授予”。最后,我重新启动了平板电脑。我检查了该应用是否被允许访问存储(在设置,应用,存储权限中)。我在断开USB连接的情况下重新运行了该应用程序,但未显示该图像。
I/myfile: FILE EXISTS PASS! /storage/emulated/0/Pictures/henry1.jpg
E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /storage/emulated/0/Pictures/henry1.jpg: open Failed: EACCES (Permission denied)
解决方法
在Android 10及更高版本中,您只能将File类用于本地私有目录中的媒体。无法使用文件路径直接访问外部媒体。
对于公共媒体,您必须使用媒体商店中的实际媒体Uri。对于您的具体情况,请执行以下操作:
- 使用媒体商店获取目标图片Uri
- Open a Stream定位此类Uri。
- Use the stream与BitmapFactory。
- 别忘了关闭流。
备注:Media Store中的DATA字段已被弃用,它可能包含路径也可能不包含路径,因此,在涉及文件时,应避免使用路径,并遵守内容Uri的内容。