Сбой приложения в фоновом режиме при съемке фотографии с камеры в Oneplus - PullRequest
0 голосов
/ 06 ноября 2019

Я занимаюсь разработкой приложения с функцией получения изображения с камеры или галереи. Это работает нормально на всех устройствах, но не в OnePlus.

Это код:

public File dispatchTakePictureIntent(Activity activity) {
        File tempPhotoFile = null;
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity(activity.getPackageManager()) != null) {

            try {
                tempPhotoFile = Utils.createImageFile(activity);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (tempPhotoFile != null) {
                Uri photoURI = FileProvider.getUriForFile(activity, Utils.getFileProvider(activity), tempPhotoFile);
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
                takePictureIntent.setClipData(ClipData.newRawUri("", photoURI));
                takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                activity.startActivityForResult(takePictureIntent, Constants.REQUEST_IMAGE_CAPTURE);
            }
        }
        return tempPhotoFile;
    }

Код в утилитах:

public static File createImageFile(Context context) throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.ENGLISH).format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        File image = File.createTempFile(
                imageFileName,  /* prefix */
                ".jpg",         /* suffix */
                storageDir      /* directory */
        );

        // Save a file: path for use with ACTION_VIEW intents
        return image;
    }

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

Ответы [ 2 ]

0 голосов
/ 07 ноября 2019

Я проверил ваш код на OP7Pro.

Вот код, который я использовал для теста:

@Throws(IOException::class)
fun createImageFile(context: Context): File {
    // Create an image file name
    val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.ENGLISH).format(Date())
    val imageFileName = "JPEG_" + timeStamp + "_"
    val storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)

    // Save a file: path for use with ACTION_VIEW intents
    return File.createTempFile(
        imageFileName, /* prefix */
        ".jpg", /* suffix */
        storageDir      /* directory */
    )
}

private fun dispatchTakePictureIntent(activity: Activity): File? {
    var tempPhotoFile: File? = null
    val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    if (takePictureIntent.resolveActivity(activity.packageManager) != null) {

        try {
            tempPhotoFile = createImageFile(activity)
        } catch (e: Exception) {
            e.printStackTrace()
        }

        if (tempPhotoFile != null) {
            val photoURI = FileProvider.getUriForFile(
                activity,
                applicationContext.packageName + ".fileprovider",
                tempPhotoFile
            )
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
            takePictureIntent.clipData = ClipData.newRawUri("", photoURI)
            takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION)
            activity.startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
        }
    }
    return tempPhotoFile
}

Затем назвал его так:

btnOpenCamera.setOnClickListener{
     val r = dispatchTakePictureIntent(this)
     imageView.setImageDrawable(Drawable.createFromPath(r?.path))
}

Я установил результат в просмотре изображений.

Поставщик файлов:

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths" />
</provider>

@ xml / provider_paths:

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

Ниже приведены мои наблюдения:

return tempPhotoFile 

не ждет, пока камера сделает снимок и вернется с результатом. Он возвращает путь сразу же после завершения вызова activity.startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE), где файл изображения, возможно, не был создан во время возврата значения. В результате поведение непредсказуемо.

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

Что касается причины сбоя вашего приложения, возможно, вы пытаетесь что-то сделать с файлом, который возвращается с dispatchTakePictureIntent, и когда вы пытаетесь его обработать,изображение на самом деле не создано к тому времени. Следовательно, Unable to open content: file:///storage/emulated/0/Android/data/...

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

Здесь - это пример реализации, который вы можете посмотретьat.

Надеюсь, это поможет.

С уважением

Приябрата

0 голосов
/ 06 ноября 2019

Вы, вероятно, не дали разрешения для своего URI

. Пожалуйста, учтите, что https://developer.android.com/reference/android/support/v4/content/FileProvider

Редактировать фрагмент, наиболее важный для вас, это https://developer.android.com/reference/android/support/v4/content/FileProvider#Permissions

где-то перед startActivityForResult youнеобходимо добавить

 activity.grantUriPermission(activity.getActivityInfo().getPackageName(), photoURI, Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION)

, который является псевдокодом, поэтому, пожалуйста, проверьте его на своей стороне

РЕДАКТИРОВАТЬ 2: Я сделал ошибку, предложив вам добавить это разрешение в вашсобственный пакетВам нужно добавить его в приложение, которое сделает эту картинку для вас

heres kotlin-код для перехвата всех приложений, которые могут это сделать

val resInfoList = activity.packageManager.queryIntentActivities(Intent(MediaStore.ACTION_IMAGE_CAPTURE), PackageManager.MATCH_DEFAULT_ONLY)
    resInfoList
            .map { it.activityInfo.packageName }
            .forEach { this.grantUriPermission(it, photoURI, Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION) }

Также для захвата изображения вы можете использовать более простое намерение

    val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
            startActivityForResult(takePictureIntent, PICK_CAMERA_CODE)

ура

...