【问题标题】:Android reading external storage gives securityExceptionAndroid读取外部存储给出securityException
【发布时间】:2015-02-14 17:38:00
【问题描述】:

我正在尝试获取设备中的音乐文件。这是我的工作:

public ArrayList<Track> getAllSongsFromSDCARD()
{
    allTracks = new ArrayList<Track>();
    String[] STAR = { "*" };
    Uri allsongsuri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
    String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";

    Cursor cursor = mContext.getApplicationContext().getContentResolver().query(allsongsuri, STAR, selection, null, null);

    if (cursor != null) {
        if (cursor.moveToFirst()) {
            do {
                String song_name = cursor
                        .getString(cursor
                                .getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
                int song_id = cursor.getInt(cursor
                        .getColumnIndex(MediaStore.Audio.Media._ID));

                String fullpath = cursor.getString(cursor
                        .getColumnIndex(MediaStore.Audio.Media.DATA));


                String album_name = cursor.getString(cursor
                        .getColumnIndex(MediaStore.Audio.Media.ALBUM));
                int album_id = cursor.getInt(cursor
                        .getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));

                String artist_name = cursor.getString(cursor
                        .getColumnIndex(MediaStore.Audio.Media.ARTIST));
                int artist_id = cursor.getInt(cursor
                        .getColumnIndex(MediaStore.Audio.Media.ARTIST_ID));



                String duration = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION));
                int[] splitTime = null;
                String hours, minutes, seconds, formattedTime;
                try{
                    splitTime = splitToComponentTimes(BigDecimal.valueOf(Long.valueOf(duration)/1000));
                    hours = String.valueOf(splitTime[0]);
                    minutes = String.valueOf(splitTime[1]);
                    seconds = String.valueOf(splitTime[2]);
                    if(hours.equals("0")){
                        formattedTime = minutes + ":" + seconds;
                    }else{
                        formattedTime = hours + ":" + minutes + ":" + seconds;
                    }
                }catch (Exception e){
                    formattedTime = "00:00";
                }

                allTracks.add(new Track(song_name, song_id, fullpath, album_name, album_id, artist_name, artist_id, formattedTime));
            } while (cursor.moveToNext());

        }

        sortTracksAlphabetically(allTracks);
        cursor.close();
    }
    return allTracks;
}

我的清单中有以下权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

当我在装有 Android 4.3 的设备上运行该代码时,它运行良好。但是当我在 Android 5.0.2 的设备上运行它时,它会给出

"java.lang.SecurityException: Permission Denial: 读取 com.android.providers.media.MediaProvider URI content://media/external/audio/media from pid=5701, uid=10054 需要 android.permission.READ_EXTERNAL_STORAGE"

谁能告诉我为什么?这是完整的堆栈跟踪:

02-14 19:25:52.812    5701-5701/com.yrazlik.musicplayer E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.yrazlik.musicplayer, PID: 5701
java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/audio/media from pid=5701, uid=10054 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
        at android.os.Parcel.readException(Parcel.java:1540)
        at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:185)
        at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:137)
        at android.content.ContentProviderProxy.query(ContentProviderNative.java:420)
        at android.content.ContentResolver.query(ContentResolver.java:478)
        at android.content.ContentResolver.query(ContentResolver.java:422)
        at com.yrazlik.musicplayer.dialogs.AllSongsDialog.getAllSongsFromSDCARD(AllSongsDialog.java:74)
        at com.yrazlik.musicplayer.dialogs.AllSongsDialog.onCreate(AllSongsDialog.java:59)
        at android.app.Dialog.dispatchOnCreate(Dialog.java:373)
        at android.app.Dialog.show(Dialog.java:274)
        at com.yrazlik.musicplayer.fragments.PlaylistFragment$1.onClick(PlaylistFragment.java:86)
        at android.view.View.performClick(View.java:4756)
        at android.view.View$PerformClick.run(View.java:19749)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

谢谢。

【问题讨论】:

  • 确保您的&lt;uses-permission&gt; 元素位置正确。他们需要是&lt;manifest&gt; 的直系子级,作为&lt;application&gt; 的同龄人。
  • @CommonsWare 哦,你是对的,我已经将权限放在应用程序标签中,现在我移动了它们。现在它起作用了。但是为什么我的android 4.3设备没有问题,但5.0.2设备有问题?

标签: android securityexception


【解决方案1】:

我的清单中有以下权限

如果清单中有&lt;uses-permission&gt; 元素,但经常出现权限错误,这是因为这些元素在清单中的位置错误。他们需要是&lt;manifest&gt; 的直系子级,作为&lt;application&gt; 的同龄人。

但为什么我的android 4.3设备没有问题,但5.0.2设备有问题?

在 Android 4.4 之前,READ_EXTERNAL_STORAGE 要么不存在,要么未在普通设备上强制执行。

【讨论】:

  • 我在 android 6 上遇到过这个问题,但权限是正确的
  • @nAkhmedov:那么你很可能会遇到issues with runtime permissions
  • 非常感谢@nAkhmedov,我在构建版本 23 时遇到了问题,您发布的链接确实很有帮助。
  • @CommonsWare 在 Android 23 模拟器上运行时,这实际上发生在 Leanback/VideoBrowse 示例中。
  • @IgorGanapolsky:“清单权限与 Marshmallow 的运行时权限无关”——当然有。运行时权限从拥有清单中的权限开始。除此之外,该示例的该项目的targetSdkVersion 低于23,因此在任何版本的Android 上都没有使用运行时权限系统。 Android 6.0 设备在权限方面与旧设备一样对待旧版应用程序(所有这些都是预先授予的)。
【解决方案2】:

“CommonsWare”在其他链接上的一个非常好的答案

现在没有获得您的许可的主要原因是您的项目的 targetSdkVersion 为 23 或更高,并且您请求的许可是“危险的”。在 Android 6.0 中,这包括:

ACCESS_COARSE_LOCATION
ACCESS_FINE_LOCATION
添加语音邮件
BODY_SENSORS
呼叫电话
相机
GET_ACCOUNTS
PROCESS_OUTGOING_CALLS
READ_CALENDAR
READ_CALL_LOG
READ_CELL_BROADCASTS
READ_CONTACTS
READ_EXTERNAL_STORAGE
READ_PHONE_STATE
READ_SMS
RECEIVE_MMS
RECEIVE_SMS
RECEIVE_WAP_PUSH
RECORD_AUDIO
发送短信
USE_SIP
WRITE_CALENDAR
WRITE_CALL_LOG WRITE_CONTACTS
WRITE_EXTERNAL_STORAGE

对于这些权限,您的 targetSdkVersion 23+ 应用不仅需要具有 &lt;uses-permission&gt; 元素,而且您还必须在运行时向 Android 6.0+ 设备上的用户请求这些权限,使用方法如下checkSelfPermission() 和 requestPermissions()。

作为临时解决方法,将 targetSdkVersion 降低到 23 以下。

但是,最终,您将有理由希望您的 targetSdkVersion 为 23 或更高。届时,您将需要调整您的应用程序以使用新的运行时权限系统。 Android 6.0 预览文档有一个专门讨论此主题的页面。

现在我将我的 targetSdkVersion 从 23 降级到 21 它的工作,但它是一个临时解决方案。

【讨论】:

    猜你喜欢
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-08
    • 2012-01-12
    • 1970-01-01
    • 1970-01-01
    • 2013-11-19
    相关资源
    最近更新 更多