Android 音乐播放器请求写入外部存储权限?

Android 音乐播放器请求写入外部存储权限?,android,android-mediaplayer,android-permissions,android-securityexception,Android,Android Mediaplayer,Android Permissions,Android Securityexception,我正在用Android创建一个音乐播放器应用程序。它工作得很好,但每当我在歌曲列表中滚动时,它就会开始崩溃,并给出此异常 Process: com.example.lenovo.musicplayer, PID: 31100 java.lang.SecurityException: External path: /storage/emulated/0/Android/data/com.android.providers.media/albumthumbs/1460104607336: Neith

我正在用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
。 据我所知,音乐播放器不需要写外部存储权限

以下是歌曲列表活动的代码

   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;
    }
}
公共类活动SongsList扩展了AppCompativeActivity{
公共静态数组列表;
列表视图列表视图;
工具栏;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity\u歌曲\u列表);
toolbar=(toolbar)findviewbyd(R.id.toolbar);
设置支持操作栏(工具栏);
listView=(listView)findViewById(R.id.lv_歌曲);
songsList=getAudioList();
Adapter Adapter=新适配器(此为songsList);
setAdapter(适配器);
getSupportActionBar().setTitle(“歌曲”);
toolbar.setTitleTextColor(Color.parseColor(“#ffffff”);
setOnItemClickListener(新的AdapterView.OnItemClickListener(){
@凌驾
public void onItemClick(AdapterView父对象、视图、整型位置、长id){
意向意向=新意向(ActivitySongsList.this,ActivityMusicDetails.class);
intent.putExtra(“歌曲”,songsList.get(位置));
intent.putExtra(“位置”,String.valueOf(位置));
星触觉(意向);
}
});
}
私有ArrayList getAudioList(){
ArrayList musicBeanArrayList=新建ArrayList();
试一试{
最终游标mCursor=getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL\u CONTENT\u URI,
新字符串[]{MediaStore.Audio.Media.DISPLAY_NAME,MediaStore.Audio.Media.DATA,MediaStore.Audio.Media.ALBUM_ID,MediaStore.Audio.Media.ARTIST,MediaStore.Audio.Media.TITLE},null,null,
“下(“+MediaStore.Audio.Media.TITLE+”)ASC”);
int count=mCursor.getCount();
int i=0;
if(mCursor.moveToFirst()){
做{
stringsong=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));
stringartist=mCursor.getString(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.artist));
Uri sArtworkUri=Uri
.parse(“content://media/external/audio/albumart");
Uri albumArtUri=ContentUris.withAppendedId(sArtworkUri,album_id);
添加(新的MusicBean(歌曲,路径,albumArtUri.toString(),String.valueOf(album_id),艺术家));
/*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();
}捕获(例外e)
{
e、 printStackTrace();
}
返回musicBeanArrayList;
}
}
它在这一行崩溃,但有一个例外

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

在这段代码中,我得到了相应mp3文件的相册艺术。
但此代码也仅从外部存储器读取,因此这也不应要求写入权限,因为我只读取位图而不写入它。

在清单文件中声明权限,如下所示:

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


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

之所以需要它,是因为MediaStore需要它,没有只读;MediaStore正在您的计算机上访问外部文件,因此您正在进行读取。

From,它处理“/media/external/audio/albumart”

内部
openFile(Uri,字符串模式)

所以,如果找不到文件,它将调用
getThumb

getThumb
调用
makeThumbInternal

然后在一定条件下,它调用

writeAlbumArt(need_to_recompress, out, compressed, bm);
在最新版本中,writeAlbumArt调用

final long identity = Binder.clearCallingIdentity();

在写之前,这应该能解决问题。但是修复是在2015年8月27日提交的,所以只有棉花糖有机会得到修复。

你可以使用福林链接,这是为你提供帮助。

是的,我正确地阅读了这个问题,你必须至少给android.permission.read\u EXTERNAL\u storage我已经给出了,这就是为什么我得到了我调试的songsCan列表??
final long identity = Binder.clearCallingIdentity();