Stephen McCormick
Stephen McCormick

Reputation: 1796

Android - java.lang.RuntimeException with Older SDKs capturing video

Recently upgraded to SDK 27, and now I have been running into issues with file based operations associated with the Camera for older versions of the Android SDK 15 to 17 (OS is less than or equal to 5.0). It seems to be fine with the new versions of the OS (6 thru 8). Most have been solved by FileProvider.getUriForFile and setting permissions, but for capturing video I am getting the following error when attempting to save the video:

08-21 20:37:43.290 13831-13847/? E/GPS: [assist_gps_request_set_id][line = 1232] : Failed with INVALID SET-ID TYPE
08-21 20:37:46.500 16162-16162/? E/CursorWindow: Failed to read row 0, column -1 from a CursorWindow which has 1 rows, 2 columns.
08-21 20:37:46.530 16162-16162/? E/AndroidRuntime: FATAL EXCEPTION: main
    java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=2002, result=-1, data=Intent 
    { act=inline-data dat=content://com.mycompany.myapp.provider/external_files/myapp/311414eb-35fd-4a73-8368-b9b72b5b5717/1283_311414eb-35fd-4a73-8368-b9b72b5b5717_4fae434e-5a18-406f-8bf7-bf78668d4bd4.mp4 (has extras) }} to activity {com.sec.android.app.camera/com.sec.android.app.camera.Camcorder}: java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
      at android.app.ActivityThread.deliverResults(ActivityThread.java:2992)
      at android.app.ActivityThread.handleSendResult(ActivityThread.java:3035)
      at android.app.ActivityThread.access$1100(ActivityThread.java:127)
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1189)
      at android.os.Handler.dispatchMessage(Handler.java:99)
      at android.os.Looper.loop(Looper.java:137)
      at android.app.ActivityThread.main(ActivityThread.java:4507)
      at java.lang.reflect.Method.invokeNative(Native Method)
      at java.lang.reflect.Method.invoke(Method.java:511)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:978)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:745)
      at dalvik.system.NativeStart.main(Native Method)
    Caused by: java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
      at android.database.CursorWindow.nativeGetLong(Native Method)
      at android.database.CursorWindow.getLong(CursorWindow.java:523)
      at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75)
      at android.database.CursorWrapper.getLong(CursorWrapper.java:106)
      at com.sec.android.app.camera.Camcorder.onActivityResult(Camcorder.java:2419)
      at android.app.Activity.dispatchActivityResult(Activity.java:4653)
      at android.app.ActivityThread.deliverResults(ActivityThread.java:2988)
      at android.app.ActivityThread.handleSendResult(ActivityThread.java:3035) 
      at android.app.ActivityThread.access$1100(ActivityThread.java:127) 
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1189) 
      at android.os.Handler.dispatchMessage(Handler.java:99) 
      at android.os.Looper.loop(Looper.java:137) 
      at android.app.ActivityThread.main(ActivityThread.java:4507) 
      at java.lang.reflect.Method.invokeNative(Native Method) 
      at java.lang.reflect.Method.invoke(Method.java:511) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:978) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:745) 
      at dalvik.system.NativeStart.main(Native Method) 
08-21 20:37:46.550 13831-13848/? E/android.os.Debug: !@Dumpstate > dumpstate -k -t -n -z -d -o /data/log/dumpstate_app_error
08-21 20:37:49.510 13802-13829/? E/AudioHardware: AudioStreamOutALSA::standby spdifenable =0
08-21 20:37:52.070 13831-13958/? E/Watchdog: !@Sync 10

The code in question is:

   private void pickFromCamera() {
        mCaptureFileName = "MyTestFile.mp4";
        Intent captureIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
        int captureDefault = mField.getMaxLength();
        captureIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, captureDefault);
        captureIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
        captureIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, 524288000L); // 50 mb

        File output = new File(mDirectory, mCaptureFileName);
        Uri uri = FileProvider.getUriForFile(
                VideoCaptureViewActivity.this,
                VideoCaptureViewActivity.this.getApplicationContext()
                        .getPackageName() + ".provider", output);
        Utilities.setUriForPackages(getApplicationContext(),captureIntent,uri);
        captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
        this.startActivityForResult(captureIntent, PICK_FROM_CAMERA);
    }


    /*
     * Used to support new SDK 27 changes to support older devices URI operations - photos, recordings, etc.
     */
    public static void setUriForPackages(Context context, Intent captureIntent, Uri uri) {
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
            List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(captureIntent, PackageManager.MATCH_DEFAULT_ONLY);
            for (ResolveInfo resolveInfo : resInfoList) {
                String packageName = resolveInfo.activityInfo.packageName;
                context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
            }
        }
        else
            captureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }

The specific device is a Samsung Tablet running Android 4.0.4

UPDATE

Here is the working code:

private void pickFromCamera() {
    mCaptureFileName = "MyTestFile.mp4";
    Intent captureIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
    int captureDefault = mField.getMaxLength();
    captureIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, captureDefault);
    captureIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
    captureIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, 524288000L); // 50 mb

    File output = new File(mDirectory, mCaptureFileName);
    Uri uri;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        uri = FileProvider.getUriForFile(
                VideoCaptureViewActivity.this,
                VideoCaptureViewActivity.this.getApplicationContext()
                        .getPackageName() + ".provider", output);
    } else {
        uri = Uri.fromFile(output);
    }
    Utilities.setUriForPackages(getApplicationContext(),captureIntent,uri);
    captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
    this.startActivityForResult(captureIntent, PICK_FROM_CAMERA);
}


/*
 * Used to support new SDK 27 changes to support older devices URI operations - photos, recordings, etc.
 */
public static void setUriForPackages(Context context, Intent captureIntent, Uri uri) {
    if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
        List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(captureIntent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo resolveInfo : resInfoList) {
            String packageName = resolveInfo.activityInfo.packageName;
            context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
    }
    else
        captureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}

Upvotes: 0

Views: 53

Answers (1)

Stephen McCormick
Stephen McCormick

Reputation: 1796

Turns out video under the older OS with a higher SDK target (say 27) does NOT need the funky processing, just the old urifile stuff. Here is the link to the answer:

Video capturing crash on Samsung android 5 with FileProvider

Upvotes: 1

Related Questions