Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android Q适配问题 #602

Open
akathink opened this issue Apr 15, 2019 · 9 comments
Open

Android Q适配问题 #602

akathink opened this issue Apr 15, 2019 · 9 comments

Comments

@akathink
Copy link

akathink commented Apr 15, 2019

Android Q编译的APK,在Pixel3的Android Q系统上报错,具体信息如下:

配置:
compileSdkVersion 'android-Q'
minSdkVersion 'Q'
targetSdkVersion 'Q'

错误:
E/DatabaseUtils: Writing exception to parcel
java.lang.IllegalArgumentException: Invalid column bucket_id
at android.database.sqlite.SQLiteQueryBuilder.computeProjection(SQLiteQueryBuilder.java:886)
at android.database.sqlite.SQLiteQueryBuilder.buildQuery(SQLiteQueryBuilder.java:664)
at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:463)
at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:377)
at android.database.TranslatingCursor.query(TranslatingCursor.java:119)
at com.android.providers.media.MediaProvider.query(MediaProvider.java:1447)
at android.content.ContentProvider$Transport.query(ContentProvider.java:267)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:104)
at android.os.Binder.execTransactInternal(Binder.java:1026)
at android.os.Binder.execTransact(Binder.java:999)

请适配一下!

@belinwu
Copy link

belinwu commented Aug 1, 2019

以下是我的改版,针对targetSdkVersion为29的适配。

public class AlbumLoader extends CursorLoader {
    public static final String COLUMN_COUNT = "count";
    private static final Uri QUERY_URI = MediaStore.Files.getContentUri("external");
    private static final String COLUMN_BUCKET_ID = "bucket_id";
    private static final String COLUMN_BUCKET_NAME = "bucket_display_name";
    private static final String[] COLUMNS = {
            MediaStore.Files.FileColumns._ID,
            COLUMN_BUCKET_ID,
            COLUMN_BUCKET_NAME,
            MediaStore.MediaColumns.DATA,
            COLUMN_COUNT};
    private static final String[] PROJECTION = {
            MediaStore.Files.FileColumns._ID,
            COLUMN_BUCKET_ID,
            COLUMN_BUCKET_NAME,
            MediaStore.MediaColumns.DATA};

    // === params for showSingleMediaType: false ===
    private static final String SELECTION =
            "(" + MediaStore.Files.FileColumns.MEDIA_TYPE + "=?"
                    + " OR "
                    + MediaStore.Files.FileColumns.MEDIA_TYPE + "=?)"
                    + " AND " + MediaStore.MediaColumns.SIZE + ">0";
    private static final String[] SELECTION_ARGS = {
            String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE),
            String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO),
    };
    // =============================================

    // === params for showSingleMediaType: true ===
    private static final String SELECTION_FOR_SINGLE_MEDIA_TYPE =
            MediaStore.Files.FileColumns.MEDIA_TYPE + "=?"
                    + " AND " + MediaStore.MediaColumns.SIZE + ">0";

    private static String[] getSelectionArgsForSingleMediaType(int mediaType) {
        return new String[]{String.valueOf(mediaType)};
    }
    // =============================================

    private static final String BUCKET_ORDER_BY = "datetaken DESC";

    private AlbumLoader(Context context, String selection, String[] selectionArgs) {
        super(context, QUERY_URI, PROJECTION, selection, selectionArgs, BUCKET_ORDER_BY);
    }

    public static CursorLoader newInstance(Context context) {
        String selection;
        String[] selectionArgs;
        if (SelectionSpec.getInstance().onlyShowImages()) {
            selection = SELECTION_FOR_SINGLE_MEDIA_TYPE;
            selectionArgs = getSelectionArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE);
        } else if (SelectionSpec.getInstance().onlyShowVideos()) {
            selection = SELECTION_FOR_SINGLE_MEDIA_TYPE;
            selectionArgs = getSelectionArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO);
        } else {
            selection = SELECTION;
            selectionArgs = SELECTION_ARGS;
        }
        return new AlbumLoader(context, selection, selectionArgs);
    }

    @Override
    public Cursor loadInBackground() {
        Cursor cursor = super.loadInBackground();
        MatrixCursor albumCursor = new MatrixCursor(COLUMNS);
        if (cursor == null) {
            return albumCursor;
        }

        int totalCount = cursor.getCount();
        boolean allAdded = false;
        SparseArray<Album> albums = new SparseArray<>();
        while (cursor.moveToNext()) {
            String filepath = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DATA));
            int bucketId = cursor.getInt(cursor.getColumnIndex(COLUMN_BUCKET_ID));
            String bucketName = cursor.getString(cursor.getColumnIndex(COLUMN_BUCKET_NAME));
            if (!allAdded) {
                albumCursor.addRow(new String[]{ALBUM_ID_ALL, ALBUM_ID_ALL, ALBUM_NAME_ALL, filepath, String.valueOf(totalCount)});
                allAdded = true;
            }

            Album album = albums.get(bucketId);
            if (album == null) {
                album = new Album(bucketId + "", filepath, bucketName, 0);
                albums.append(bucketId, album);
            }
            album.addCaptureCount();
        }

        for (int i = 0; i < albums.size(); i++) {
            Album album = albums.valueAt(i);
            String id = album.getId();
            String name = album.getDisplayName(getContext());
            String coverPath = album.getCoverPath();
            String count = album.getCount() + "";
            albumCursor.addRow(new String[]{id, id, name, coverPath, count});
        }

        return albumCursor;
    }

    @Override
    public void onContentChanged() {
        // FIXME a dirty way to fix loading multiple times
    }
}

@REBOOTERS
Copy link
Contributor

pr is welcome

@WanDa1993
Copy link

@belinwu 有一个问题,我有些疑惑,在Android10上面 MediaStore.MediaColumns.DATA 这个字段其实是拿不到的。在Android Q上面运行没问题么。

@belinwu
Copy link

belinwu commented Sep 11, 2019

@belinwu 有一个问题,我有些疑惑,在Android10上面 MediaStore.MediaColumns.DATA 这个字段其实是拿不到的。在Android Q上面运行没问题么。

确实DATA字段值在Q上不可靠,之后没有直接使用该值,用的是Content Uri。

@WanDa1993
Copy link

@belinwu 我发现DATA值不可靠后,我也是通过Uri获取。但是我发现一个问题 图库里面有一些图片我获取的Uri无法读取图片。。。

@beilvla
Copy link

beilvla commented Oct 11, 2019

以下是我的改版,针对targetSdkVersion为29的适配。

public class AlbumLoader extends CursorLoader {
    public static final String COLUMN_COUNT = "count";
    private static final Uri QUERY_URI = MediaStore.Files.getContentUri("external");
    private static final String COLUMN_BUCKET_ID = "bucket_id";
    private static final String COLUMN_BUCKET_NAME = "bucket_display_name";
    private static final String[] COLUMNS = {
            MediaStore.Files.FileColumns._ID,
            COLUMN_BUCKET_ID,
            COLUMN_BUCKET_NAME,
            MediaStore.MediaColumns.DATA,
            COLUMN_COUNT};
    private static final String[] PROJECTION = {
            MediaStore.Files.FileColumns._ID,
            COLUMN_BUCKET_ID,
            COLUMN_BUCKET_NAME,
            MediaStore.MediaColumns.DATA};

    // === params for showSingleMediaType: false ===
    private static final String SELECTION =
            "(" + MediaStore.Files.FileColumns.MEDIA_TYPE + "=?"
                    + " OR "
                    + MediaStore.Files.FileColumns.MEDIA_TYPE + "=?)"
                    + " AND " + MediaStore.MediaColumns.SIZE + ">0";
    private static final String[] SELECTION_ARGS = {
            String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE),
            String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO),
    };
    // =============================================

    // === params for showSingleMediaType: true ===
    private static final String SELECTION_FOR_SINGLE_MEDIA_TYPE =
            MediaStore.Files.FileColumns.MEDIA_TYPE + "=?"
                    + " AND " + MediaStore.MediaColumns.SIZE + ">0";

    private static String[] getSelectionArgsForSingleMediaType(int mediaType) {
        return new String[]{String.valueOf(mediaType)};
    }
    // =============================================

    private static final String BUCKET_ORDER_BY = "datetaken DESC";

    private AlbumLoader(Context context, String selection, String[] selectionArgs) {
        super(context, QUERY_URI, PROJECTION, selection, selectionArgs, BUCKET_ORDER_BY);
    }

    public static CursorLoader newInstance(Context context) {
        String selection;
        String[] selectionArgs;
        if (SelectionSpec.getInstance().onlyShowImages()) {
            selection = SELECTION_FOR_SINGLE_MEDIA_TYPE;
            selectionArgs = getSelectionArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE);
        } else if (SelectionSpec.getInstance().onlyShowVideos()) {
            selection = SELECTION_FOR_SINGLE_MEDIA_TYPE;
            selectionArgs = getSelectionArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO);
        } else {
            selection = SELECTION;
            selectionArgs = SELECTION_ARGS;
        }
        return new AlbumLoader(context, selection, selectionArgs);
    }

    @Override
    public Cursor loadInBackground() {
        Cursor cursor = super.loadInBackground();
        MatrixCursor albumCursor = new MatrixCursor(COLUMNS);
        if (cursor == null) {
            return albumCursor;
        }

        int totalCount = cursor.getCount();
        boolean allAdded = false;
        SparseArray<Album> albums = new SparseArray<>();
        while (cursor.moveToNext()) {
            String filepath = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DATA));
            int bucketId = cursor.getInt(cursor.getColumnIndex(COLUMN_BUCKET_ID));
            String bucketName = cursor.getString(cursor.getColumnIndex(COLUMN_BUCKET_NAME));
            if (!allAdded) {
                albumCursor.addRow(new String[]{ALBUM_ID_ALL, ALBUM_ID_ALL, ALBUM_NAME_ALL, filepath, String.valueOf(totalCount)});
                allAdded = true;
            }

            Album album = albums.get(bucketId);
            if (album == null) {
                album = new Album(bucketId + "", filepath, bucketName, 0);
                albums.append(bucketId, album);
            }
            album.addCaptureCount();
        }

        for (int i = 0; i < albums.size(); i++) {
            Album album = albums.valueAt(i);
            String id = album.getId();
            String name = album.getDisplayName(getContext());
            String coverPath = album.getCoverPath();
            String count = album.getCount() + "";
            albumCursor.addRow(new String[]{id, id, name, coverPath, count});
        }

        return albumCursor;
    }

    @Override
    public void onContentChanged() {
        // FIXME a dirty way to fix loading multiple times
    }
}

你试拍照了么?
2019-10-11 12:08:21.226 3532-3532/com.zhihu.matisse.sample E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.zhihu.matisse.sample, PID: 3532
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Pictures/test/JPEG_20191011_120821.jpg
at androidx.core.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:739)
at androidx.core.content.FileProvider.getUriForFile(FileProvider.java:418)
at com.zhihu.matisse.internal.utils.MediaStoreCompat.dispatchCaptureIntent(MediaStoreCompat.java:86)
at com.zhihu.matisse.ui.MatisseActivity.capture(MatisseActivity.java:424)
at com.zhihu.matisse.internal.ui.adapter.AlbumMediaAdapter$1.onClick(AlbumMediaAdapter.java:75)
at android.view.View.performClick(View.java:7176)
at android.view.View.performClickInternal(View.java:7150)
at android.view.View.access$3500(View.java:818)
at android.view.View$PerformClick.run(View.java:27539)
at android.os.Handler.handleCallback(Handler.java:888)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8108)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)

@yanchengdeng
Copy link

等待适配androidQ 方案

@thirtyyuan
Copy link

有何进展吗?望告知下

@beilvla
Copy link

beilvla commented Jan 7, 2020 via email

moodcal pushed a commit to moodcal/Matisse that referenced this issue Mar 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants