Android无法解码流:bitmapFactory.decodeFile()的java.io.FileNotFoundException

时间:2016-11-06 11:43:17

标签: java android bitmap

我有一个Android应用程序,我从相机拍摄照片,然后我想将其转换为base64格式,但我接受拍摄的照片后出错。看起来我无法访问外部存储,我认为这会导致空位图。 ANDROID_MANIFEST中的许可已被宣布。如何解决权限问题以及可能导致空位图的原因?

这是我的代码:

public class MainActivity extends AppCompatActivity {

private Button takePhotoButton;
private String encoded_string, image_name;
private Bitmap bitmap;
private File file;
private Uri file_uri;


private String getRealPathFromURI(Uri contentUri) {
    String[] proj = { MediaStore.Images.Media.DATA };
    CursorLoader loader = new CursorLoader(this, contentUri, proj, null, null, null);
    Cursor cursor = loader.loadInBackground();
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    String result = cursor.getString(column_index);
    cursor.close();
    return result;
}

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

    takePhotoButton = (Button) findViewById(R.id.take_photo);
    takePhotoButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            getFileUri();
            i.putExtra(MediaStore.EXTRA_OUTPUT, file_uri);
            startActivityForResult(i, 10);
        }
    });
}


private void getFileUri() {
    image_name= "test123.jpg";
    file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + image_name);
    file_uri = Uri.fromFile(file);
}



@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if(requestCode == 10 && resultCode == RESULT_OK){
        new Encode_image().execute();
    }
}


private class Encode_image extends AsyncTask<Void, Void, Void>{

    @Override
    protected Void doInBackground(Void... params) {

        BitmapFactory.Options options = new BitmapFactory.Options();

        int scale = 8;
        options.inSampleSize = scale;
        options.inJustDecodeBounds = false;
        bitmap = BitmapFactory.decodeFile(file_uri.getPath(), options);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 50,  stream);




        //convert stream to byte array
        byte[] array = stream.toByteArray();
        encoded_string = Base64.encodeToString(array, 0);
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        makeRequest();
    }
}

private void makeRequest() {
    RequestQueue requestQueue = Volley.newRequestQueue(this);
    StringRequest request = new StringRequest(Request.Method.POST, "http://192.168.1.102/AndroidFileUpload/connection.php",

            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {

                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {

        }
    }) {
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            HashMap<String, String> map = new HashMap<>();
            map.put("encoded_string", encoded_string);
            map.put("image_name", image_name);

            return map;
        }
    };
    requestQueue.add(request);
}


}

我在行

中收到错误
bitmap.compress(Bitmap.CompressFormat.JPEG, 50,  stream) 

因为位图为空。

运行应用程序后崩溃返回了此错误/消息:

E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /storage/emulated/0/Pictures/test123.jpg: open failed: EACCES (Permission denied)
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
              Process: com.example.andrei.sendphotos, PID: 17972
              java.lang.RuntimeException: An error occurred while executing doInBackground()
                  at android.os.AsyncTask$3.done(AsyncTask.java:309)
                  at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
                  at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
                  at java.util.concurrent.FutureTask.run(FutureTask.java:242)
                  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
                  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
                  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
                  at java.lang.Thread.run(Thread.java:818)
               Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
                  at com.example.andrei.sendphotos.MainActivity$Encode_image.doInBackground(MainActivity.java:115)
                  at com.example.andrei.sendphotos.MainActivity$Encode_image.doInBackground(MainActivity.java:92)
                  at android.os.AsyncTask$2.call(AsyncTask.java:295)
                  at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
                  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
                  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
                  at java.lang.Thread.run(Thread.java:818) 
E/Surface: getSlotFromBufferLocked: unknown buffer: 0xa23ae0e0

Android Manifest xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.andrei.sendphotos">

<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

1 个答案:

答案 0 :(得分:0)

您需要为Android 6.X实现运行时权限。请参阅此处的官方文档:Requesting Runtime Permissions

我可以使用我自己的公共助手课程:PermissionHelper.java

或者您可以简单地将目标SDK版本降级为22以及所有依赖项,我不建议这样做。

Android 6.X的一个主要变化是强制执行运行时权限模型。谷歌必须保持市场上已有的应用程序的向后兼容性(不检查并询问运行时的权限)。

因此他们使其工作 - 如果应用程序针对SDK版本22,则所有权限将在安装时授予应用程序。但是,如果应用程序以SDK 23为目标,则默认情况下不会授予权限,而应用程序应在执行任何需要dangerous permissions的任务之前检查权限,并在继续执行任务之前询问用户是否已授予权限。