Страницы

Поиск по вопросам

воскресенье, 15 декабря 2019 г.

Ошибка при загрузке фотографий через камеру (Android)

#android #uri


Встретился с такой проблемой: 

При загрузке картинки с галереи или фотографии с приложения камеры в приложение,
сохраняется путь до этой картинки и производится её отображение в приложении.

Но, если версия андроид - 4.4.4 или 5, приложение вылетает именно после того, как
я открыл приложение камеры и сделал фото, чтобы оно пошло в приложение. Эта ошибка
наблюдается на 4х версиях андроид и на некоторых 5х(на Nexus5 - 6.0.1, SGS3 Cyanogen11
наблюдается ошибка, на LG G2 -5.0.2, sony z3c - 6.0.1, HTC - 4.3 не наблюдается). При
выборе картинки с галереи (повторюсь) всё работает нормально.

Вызов интента:

boolean hasPermission = false;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                hasPermission = (ContextCompat.checkSelfPermission(getContext(),
Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED);
            }
            if (hasPermission) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    ActivityCompat.requestPermissions((AppCompatActivity)getContext(),
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
                }
            }else {
                ((CategoryGoodsActivity) getContext()).startActivityForResult(Utils.getPickImageIntent(getContext()),
Integer.parseInt(v.getTag().toString()) );
            }


Генерация интента:

public static Intent getPickImageIntent(Context context) {
    Intent chooserIntent = null;

    List intentList = new ArrayList<>();
    Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    takePhotoIntent.putExtra("return-data", true);

    intentList = addIntentsToList(context, intentList, pickIntent);
    intentList = addIntentsToList(context, intentList, takePhotoIntent);

    if (intentList.size() > 0) {
        chooserIntent = Intent.createChooser(intentList.remove(intentList.size()
- 1), "Выберите");
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toArray(new
Parcelable[]{}));
    }

    return chooserIntent;
}


Получение картинки:

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    Log.e("sds", "requestCode="+requestCode+ "\nresultCode="+resultCode);
    if (resultCode == Activity.RESULT_OK && data != null) {

        String path = getPathFromCameraData(data, this);

        if (path != null) {
            Toast.makeText(getApplicationContext(), path, Toast.LENGTH_SHORT).show();
            Log.e("sds", path);
            switch (requestCode){
                case 1:
                    itemsComments.get(0).image1 = path;
                    break;
                case 2:
                    itemsComments.get(0).image2 = path;
                    break;
                case 3:
                    itemsComments.get(0).image3 = path;
                    break;
            }
            adapterComments.notifyDataSetChanged();
        }
    }
}

public String getPathFromCameraData(Intent data, Context context) {
    Uri selectedImage = data.getData();
    String[] filePathColumn = {MediaStore.Images.Media.DATA};

    Cursor cursor = context.getContentResolver().query(selectedImage, filePathColumn,
null, null, null);

    if(cursor != null) {
        cursor.moveToFirst();
        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        String picturePath = cursor.getString(columnIndex);
        cursor.close();
        return picturePath;
    }else{
        return selectedImage.getPath();
    }
}


Лог при сбое:

java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1,
result=-1, data=Intent { act=inline-data (has extras) }} to activity {ru.diit.lefood/ru.diit.lefood.screens.food.CategoryGoodsActivity}:
java.lang.NullPointerException
                                                                at android.app.ActivityThread.deliverResults(ActivityThread.java:3389)
                                                                at android.app.ActivityThread.handleSendResult(ActivityThread.java:3432)
                                                                at android.app.ActivityThread.access$1300(ActivityThread.java:144)
                                                                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1253)
                                                                at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                at android.os.Looper.loop(Looper.java:136)
                                                                at android.app.ActivityThread.main(ActivityThread.java:5146)
                                                                at java.lang.reflect.Method.invokeNative(Native
Method)
                                                                at java.lang.reflect.Method.invoke(Method.java:515)
                                                                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:732)
                                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566)
                                                                at dalvik.system.NativeStart.main(Native
Method)
                                                             Caused by: java.lang.NullPointerException
                                                                at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1420)
                                                                at android.content.ContentResolver.query(ContentResolver.java:445)
                                                                at android.content.ContentResolver.query(ContentResolver.java:404)
                                                                at ru.diit.lefood.screens.food.CategoryGoodsActivity.getPathFromCameraData(CategoryGoodsActivity.java:293)
                                                                at ru.diit.lefood.screens.food.CategoryGoodsActivity.onActivityResult(CategoryGoodsActivity.java:268)
                                                                at android.app.Activity.dispatchActivityResult(Activity.java:5423)
                                                                at android.app.ActivityThread.deliverResults(ActivityThread.java:3385)
                                                                at android.app.ActivityThread.handleSendResult(ActivityThread.java:3432) 
                                                                at android.app.ActivityThread.access$1300(ActivityThread.java:144) 
                                                                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1253) 
                                                                at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                at android.os.Looper.loop(Looper.java:136) 
                                                                at android.app.ActivityThread.main(ActivityThread.java:5146) 
                                                                at java.lang.reflect.Method.invokeNative(Native
Method) 
                                                                at java.lang.reflect.Method.invoke(Method.java:515) 
                                                                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:732) 
                                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566) 
                                                                at dalvik.system.NativeStart.main(Native
Method) 


Скрины того, что я делаю:

По нажатию на скрепку выходят 2 пункта



Выбрали камеру и сделали снимок



При нажатии на кнопку принятия изображения вылетает



В общем, жалуется в логе на эту строчку:

Cursor cursor = context.getContentResolver().query(selectedImage, filePathColumn,
null, null, null);


которая находится в методе getPathFromCameraData:

public String getPathFromCameraData(Intent data, Context context) {
    Uri selectedImage = data.getData();
    String[] filePathColumn = {MediaStore.Images.Media.DATA};

    Cursor cursor = context.getContentResolver().query(selectedImage, filePathColumn,
null, null, null);

    if(cursor != null) {
        cursor.moveToFirst();
        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        String picturePath = cursor.getString(columnIndex);
        cursor.close();
        return picturePath;
    }else{
        return selectedImage.getPath();
    }
}


Ругается, что переменная selectedImage нулевая. Делал дебаг этой строчки Uri selectedImage
= data.getData(); и data не пустая, думаю, что присвоение не работает или адрес на
фото с камеры где-то теряется. 

Не хочется извращаться, создавая пустой файл и позже присваивая ему фотографию, так
как это работает с единичной фотографией, хотелось бы найти более простое решение.

В методе как раз закомментил извращенство с созданием файла:

public static Intent getPickImageIntent(Context context) {
    Intent chooserIntent = null;

    List intentList = new ArrayList<>();


    //String imageFilePath = Environment.getExternalStorageDirectory().getAbsolutePath()
+          "/picture.jpg";
    //File imageFile = new File(imageFilePath);
    //Uri picUri = Uri.fromFile(imageFile); // convert path to Uri

    Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    takePhotoIntent.putExtra("return-data", true);
    //takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, picUri);
    intentList = addIntentsToList(context, intentList, pickIntent);
    intentList = addIntentsToList(context, intentList, takePhotoIntent);

    if (intentList.size() > 0) {
        chooserIntent = Intent.createChooser(intentList.remove(intentList.size()
- 1), "Выберите");
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toArray(new
Parcelable[]{}));
    }

    return chooserIntent;
}


Манифест имеет:







    


Ответы

Ответ 1



1) То что data.getData() возвращает null - это абсолютно нормально. Это означает лишь то,- что файл с полноразмерной фотографией небыл создан (нигде). Обычно в таких случаях система возвращает thumbnail. Обработать это можно например так: if(data.getData()==null){ bitmap = (Bitmap)data.getExtras().get("data"); }else{ bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), data.getData()); } 2) Для того чтобы получить полноразмерное фото обязятельно нужно указывать EXTRA_OUTPUT. Об этом явно сказано в документации в разделе "Taking Photos Simply" -> "Save the Full-size Photo" Итого: нужно просто раскомментировать строчку с EXTRA_OUTPUT :) UPD 14.09.2016 Создание временного файл. Для создания публичного файла в который может писать любое приложение (включая камеру) используйте: File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); path.mkdirs(); File file = new File(path, "DemoPicture.jpg");

Комментариев нет:

Отправить комментарий