在运行Android11+的设备上使用应用程序的开发者必须使用范围存储,以给用户更好的访问控制他们的设备存储。要在5月5日之后在Android 11或更新版本上发布应用程序,您必须:
更新您的应用程序以使用更隐私友好的最佳实践,如存储访问框架或媒体存储API更新您的应用程序以声明清单文件中的所有文件访问(MANAGE_EXTERNAL_STORACTA)权限,并从5开始在播放控制台中完成所有文件访问权限声明。对于针对Android 11的应用程序,将完全从您的应用程序中删除所有文件访问权限,requestLegacyExternalStorage标志将被忽略。必须使用所有文件访问权限才能保留广泛访问权限。
未经允许使用而请求访问所有文件访问权限的应用程序将从Google Play中删除,您将无法发布更新。
Manifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:resizeableActivity="false"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.YMusic">
<activity android:name="com.developer_ashu.ymusic.PlaySong"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:parentActivityName="com.developer_ashu.ymusic.MainActivity">
</activity>
<activity android:name="com.developer_ashu.ymusic.MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".Notification.NotificationReceiver"/>
</application>
</manifest>
MainActivity.java
public class MainActivity extends AppCompatActivity {
ListView listView;
MediaPlayer mediaPlayer;
ArrayList<song_info> listSongs = new ArrayList<song_info>();
private MySongAdapter mySongAdapter ;
private String[] itemsAll;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.listView);
Dexter.withContext(this)
.withPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
.withListener(new PermissionListener() {
@Override public void onPermissionGranted(PermissionGrantedResponse response) {
loadSongs();
}
@Override public void onPermissionDenied(PermissionDeniedResponse response) {
}
@Override public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
token.continuePermissionRequest();
}
}).check();
}
private void loadSongs(){
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC + "!=0";
Cursor cursor = getContentResolver().query(uri,null,selection,null,null);
if (cursor != null){
while(cursor.moveToNext()){
String url = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
String author = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
listSongs.add(new song_info(title,author,url));
}
}
mySongAdapter = new MySongAdapter(listSongs);
listView.setAdapter(mySongAdapter);
}
private class MySongAdapter extends BaseAdapter {
ArrayList<song_info> myListSongs;
public MySongAdapter(ArrayList<song_info> myListSongs) {
this.myListSongs = myListSongs;
}
@Override
public int getCount() {
return myListSongs.size();
}
@Override
public Object getItem(int position) {
return myListSongs.get(position);
}
@Override
public long getItemId(int position) {
return (long) position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView textView,textView1;
Button button;
LayoutInflater inflater = LayoutInflater.from(getApplicationContext());
View view = inflater.inflate(R.layout.my_layout,parent,false);
song_info song = myListSongs.get(position);
textView = view.findViewById(R.id.textView1);
textView1 = view.findViewById(R.id.textView2);
button = view.findViewById(R.id.button);
textView.setText(song.Title);
textView1.setText(song.Author);
button.setOnClickListener(v -> {
if ( button.getText().equals("STOP")){
mediaPlayer.stop();
mediaPlayer.release();
button.setText("PLAY");
}
else {
mediaPlayer = new MediaPlayer();
try {
Log.v("MainActivity.this",song.songUrl);
mediaPlayer.setDataSource(song.songUrl);
// After this line it throws an error if I remove requestLegacyStorage from manifest
// Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied) -- this is the error
mediaPlayer.prepare();
mediaPlayer.start();
button.setText("STOP");
}catch (Exception e){
Toast.makeText(getApplicationContext(), "Error in playingSong", Toast.LENGTH_SHORT).show();
}
}
});
return view;
}
}
}
song_info.java
public class song_info {
String Title = null;
String Author = null;
String songUrl = null;
public song_info(String title, String author, String songUrl) {
Title = title;
Author = author;
this.songUrl = songUrl;
}
}
如果您的targetSdk不是30,您可以继续使用该标志Android:RequestLegacyExternalStorage=“true”
,您不必做任何事情。但是开发人员应该在11月达到targetSdk=30。
我分享了来自谷歌的答案:
“您可以在5月5日之后继续使用requestLegacyExternalStorage,因为您的目标不是Android 11。您不需要在5月5日之前做任何事情。”
在我们的应用程序中,targetSdk=29,我们使用RequestLegacyExternalStorage。如果你处于同样的状况,你现在不必做任何事情。
问题内容: 操作系统 :debian 8.0.0-amd64,ubuntu-15.04,16.04 码头工人 :1.xx 程序: 我更改为添加一个私有Docker注册表,然后重新启动了docker服务,最后尝试提取一些映像。 一个输出显示一无所知DOCKER_OPTS环境变种。 题: 根据Docker文档,使用私有注册表的方式是通过中的DOCKER_OPTS进行。为什么这样做之后在这种环境下不生效
当我在Google Play上提出我的应用程序时,这向我展示了问题 您的应用程序当前以API级别25为目标,并且必须至少以API级别26为目标,以确保其基于针对安全性和性能优化的最新API构建。将应用程序的目标API级别更改为至少26 注意,我使用Unity 您已将sdk更新为最新版本 请帮助我如何在Unity中将API级别更改为至少26 谢啦
问题内容: 使用JNA的文档说: 使目标库可用于Java程序。有两种方法可以执行此操作:首选方法是将系统属性设置为目标库的路径。此属性类似于但仅适用于JNA加载的库。 这到底是什么意思?如何设置系统属性?我的应用程序需要参考 谢谢 问题答案: 在命令行上调用Java虚拟机时,可以使用参数“ -D”来设置系统属性: 当从例如配置文件中读取代码时,也可以在应用程序启动时在代码中以编程方式进行设置: 我
我收到了一个用于为嵌入式linux设备构建c /c应用程序的SDK。这对我来说都是新的,所以我的一些术语可能是错误的。 我按照他们的指示和SDK安装在我的linux(ubuntu)系统在 /opt/.他们使用的编译器似乎是arm-poky-linux-gnueabi-gcc。SDK的一部分设置了一些环境变量,如用于编译C/C的$CC和CPP。环境变量运行类似arm-poky-linux-gnuea
我有一个作为字符串接收的HTML文档,然后使用jSoup解析它。此HTML文档(字符串形式)包含
是否可以使用JavaFX更改应用程序图标,还是必须使用Swing来完成?