5

我正在Android中创建音乐播放器应用程序。它工作正常,但每当我在歌曲滚动列表它开始崩溃并给出了这个异常要求写入外部存储权限的音乐播放器?

Process: com.example.lenovo.musicplayer, PID: 31100 
java.lang.SecurityException: External path: /storage/emulated/0/Android/data/com.android.providers.media/albumthumbs/1460104607336: Neither user 10294 nor current process has android.permission.WRITE_EXTERNAL_STORAGE.  
at android.os.Parcel.readException(Parcel.java:1555)  
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:190) 
at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:153) 
at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:691) 
at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1170) 
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:994) 
at android.content.ContentResolver.openInputStream(ContentResolver.java:719) 
at android.provider.MediaStore$Images$Media.getBitmap(MediaStore.java:1110) 
at com.example.lenovo.musicplayer.Adapter.getView(Adapter.java:119) 
at android.widget.AbsListView.obtainView(AbsListView.java:2571) 
at android.widget.ListView.makeAndAddView(ListView.java:1894) 
at android.widget.ListView.fillDown(ListView.java:710) 
at android.widget.ListView.fillGap(ListView.java:674) 
at android.widget.AbsListView.trackMotionScroll(AbsListView.java:5900) 
at android.widget.AbsListView$FlingRunnable.run(AbsListView.java:5378) 
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:825) 
at android.view.Choreographer.doCallbacks(Choreographer.java:619) 
at android.view.Choreographer.doFrame(Choreographer.java:578) 
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:811) 
at android.os.Handler.handleCallback(Handler.java:815) 
at android.os.Handler.dispatchMessage(Handler.java:104) 
at android.os.Looper.loop(Looper.java:214) 
at android.app.ActivityThread.main(ActivityThread.java:6102) 
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:1028) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823) 

这个问题就解决了,我给写权限清单文件,但我不明白的是为什么是当我没有写任何类型的存储时,请求WriteExternalStoragePermission。 据我了解,音乐播放器不需要写入外部存储权限。

这里是在这条线

bitmap = MediaStore.Images.Media.getBitmap(ctx.getContentResolver(), uri);

在这段代码中我越来越专辑封面相应MP3文件的歌曲列表活动

public class ActivitySongsList extends AppCompatActivity { 
public static ArrayList<MusicBean>songsList; 
    ListView listView; 
    Toolbar toolbar; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_songs_list); 
     toolbar= (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 
     listView= (ListView) findViewById(R.id.lv_songs); 
     songsList=getAudioList(); 
     Adapter adapter=new Adapter(this,songsList); 
     listView.setAdapter(adapter); 
     getSupportActionBar().setTitle("Songs"); 
     toolbar.setTitleTextColor(Color.parseColor("#ffffff")); 
     listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
      @Override 
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
       Intent intent=new Intent(ActivitySongsList.this,ActivityMusicDetails.class); 
       intent.putExtra("song",songsList.get(position)); 
       intent.putExtra("position",String.valueOf(position)); 
       startActivity(intent); 
      } 
     }); 
    } 
    private ArrayList<MusicBean> getAudioList() { 
     ArrayList<MusicBean> musicBeanArrayList=new ArrayList<>(); 
     try { 
      final Cursor mCursor = getContentResolver().query(
        MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, 
        new String[]{MediaStore.Audio.Media.DISPLAY_NAME, MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.ALBUM_ID,MediaStore.Audio.Media.ARTIST,MediaStore.Audio.Media.TITLE}, null, null, 
        "LOWER(" + MediaStore.Audio.Media.TITLE + ") ASC"); 

     int count = mCursor.getCount(); 

     int i = 0; 
     if (mCursor.moveToFirst()) { 
      do { 
       String song=mCursor.getString(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE)); 
       String path=mCursor.getString(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA)); 
       long album_id=mCursor.getLong(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID)); 
       String artist=mCursor.getString(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST)); 
       Uri sArtworkUri = Uri 
         .parse("content://media/external/audio/albumart"); 
       Uri albumArtUri = ContentUris.withAppendedId(sArtworkUri, album_id); 
       musicBeanArrayList.add(new MusicBean(song,path,albumArtUri.toString(),String.valueOf(album_id),artist)); 
       /*songs[i] = mCursor.getString(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME)); 
       mAudioPath[i] = mCursor.getString(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));*/ 
       i++; 
      } while (mCursor.moveToNext()); 
     } 

     mCursor.close(); 
     }catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
     return musicBeanArrayList; 
    } 
} 

代码它崩溃不同之处。 但是这段代码也是从外部存储器读取的,因此这也不会要求写权限,因为我只读位图而不是写它。

回答

9

the MediaProvider code,如果没有找到文件,该文件处理 “/媒体/外部/音频/ albumart”

openFile(Uri uri, String mode)

try { 
    pfd = openFileAndEnforcePathPermissionsHelper(newUri, mode); 
} catch (FileNotFoundException ex) { 
    // That didn't work, now try to get it from the specific file 
    pfd = getThumb(database, db, audiopath, albumid, null); 
} 

所以,它调用getThumb

getThumb电话makeThumbInternal

然后在某些条件下,它调用

writeAlbumArt(need_to_recompress, out, compressed, bm); 

在最新版本中,writeAlbumArt写作,这是应该解决的问题之前调用

final long identity = Binder.clearCallingIdentity(); 

。但是修复是在2015年8月27日进行的,所以只有棉花糖才有机会获得修复。

+1

我可以调试吗? –

-1

中声明如下清单文件的权限:

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


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

你读的问题或只是标题? –

+0

是的,我正确地阅读这个问题,你必须给至少android.permission.READ_EXTERNAL_STORAGE –

+0

我已经给出,这就是为什么我得到歌曲列表 –

0

这是必要的,因为MediaStore需要它,没有只读的; MediaStore根据您的行为访问外部文件,因此您正在阅读。

+0

,但不写 –