Android 读取外部存储出现 securityException
Android reading external storage gives securityException
我正在尝试获取设备中的音乐文件。这是我的工作:
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: reading
com.android.providers.media.MediaProvider uri
content://media/external/audio/media from pid=5701, uid=10054 requires
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.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)
谢谢。
And i have the following permissions in my manifest
经常,如果您在清单中有 <uses-permission>
个元素但仍然出现权限错误,那是因为这些元素在清单中的位置错误。他们需要是 <manifest>
的直接子代,作为 <application>
.
的同龄人
But why there was no problem with my android 4.3 device but it is a problem in 5.0.2 device?
在 Android 4.4 之前,READ_EXTERNAL_STORAGE
不存在或未在普通设备上强制执行。
"CommonsWare" 在其他 link
上的一个很好的回答
现在没有得到您的许可很大的原因是因为您的项目的targetSdkVersion为23或更高,而您请求的权限是"dangerous"。在 Android 6.0 中,这包括:
ACCESS_COARSE_LOCATION
ACCESS_FINE_LOCATION
ADD_VOICEMAIL
BODY_SENSORS
CALL_PHONE
相机
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
SEND_SMS
USE_SIP
WRITE_CALENDAR
WRITE_CALL_LOG
WRITE_CONTACTS
WRITE_EXTERNAL_STORAGE
对于这些权限,您的 targetSdkVersion 23+ 应用不仅需要具有 <uses-permission>
元素,而且您还必须在运行时向 [=76= 上的用户请求这些权限] 6.0+ 设备,使用 checkSelfPermission() 和 requestPermissions() 等方法。
作为临时解决方法,将您的 targetSdkVersion 降低到 23 以下。
但是,最终,您将有一些理由希望您的 targetSdkVersion 为 23 或更高。届时,您将需要调整您的应用程序以使用新的运行时权限系统。 Android 6.0 预览版文档有一个专门介绍此主题的页面。
现在我将我的 targetSdkVersion 从 23 降级到 21 它的工作,但它是一个临时解决方案。
我正在尝试获取设备中的音乐文件。这是我的工作:
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: reading com.android.providers.media.MediaProvider uri content://media/external/audio/media from pid=5701, uid=10054 requires 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.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)
谢谢。
And i have the following permissions in my manifest
经常,如果您在清单中有 <uses-permission>
个元素但仍然出现权限错误,那是因为这些元素在清单中的位置错误。他们需要是 <manifest>
的直接子代,作为 <application>
.
But why there was no problem with my android 4.3 device but it is a problem in 5.0.2 device?
在 Android 4.4 之前,READ_EXTERNAL_STORAGE
不存在或未在普通设备上强制执行。
"CommonsWare" 在其他 link
上的一个很好的回答现在没有得到您的许可很大的原因是因为您的项目的targetSdkVersion为23或更高,而您请求的权限是"dangerous"。在 Android 6.0 中,这包括:
ACCESS_COARSE_LOCATION
ACCESS_FINE_LOCATION
ADD_VOICEMAIL
BODY_SENSORS
CALL_PHONE
相机
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
SEND_SMS
USE_SIP
WRITE_CALENDAR
WRITE_CALL_LOG
WRITE_CONTACTS
WRITE_EXTERNAL_STORAGE
对于这些权限,您的 targetSdkVersion 23+ 应用不仅需要具有 <uses-permission>
元素,而且您还必须在运行时向 [=76= 上的用户请求这些权限] 6.0+ 设备,使用 checkSelfPermission() 和 requestPermissions() 等方法。
作为临时解决方法,将您的 targetSdkVersion 降低到 23 以下。
但是,最终,您将有一些理由希望您的 targetSdkVersion 为 23 或更高。届时,您将需要调整您的应用程序以使用新的运行时权限系统。 Android 6.0 预览版文档有一个专门介绍此主题的页面。
现在我将我的 targetSdkVersion 从 23 降级到 21 它的工作,但它是一个临时解决方案。