Unable to request MANAGE_EXTERNAL_STORAGE (android 10) - java

I am testing my app on android 10 and I try to gain r/w access to all files.
I tried to follow this Solution but I still can't get the MANAGE_EXTERNAL_STORAGE permission.
I also tried this Solution 2.
On my manifest I ask for:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
...
<application
android:name=".GlobalVars"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.HangMan">
class Permissions extends Application{
public String Name;
public String ManifestName;
public boolean IsGranted;
Permissions(String name, String manifestName){
Name = name;
ManifestName = manifestName;
IsGranted = false;
}
Permissions(String name, String manifestName, boolean isGranted){
Name = name;
ManifestName = manifestName;
IsGranted = isGranted;
}
}
When the app is create is check the permissions and is the permissions are not granted the user has to accept them.
I use this code:
Define the required permission globally:
public class GlobalVars extends Application {
public static List<Permissions> AppPermissions = Arrays.asList(
new Permissions("MANAGE_EXTERNAL_STORAGE", Manifest.permission.MANAGE_EXTERNAL_STORAGE),
new Permissions("READ_EXTERNAL_STORAGE", Manifest.permission.READ_EXTERNAL_STORAGE),
new Permissions("WRITE_EXTERNAL_STORAGE", Manifest.permission.WRITE_EXTERNAL_STORAGE),
new Permissions("READ_SMS", Manifest.permission.READ_SMS),
new Permissions("SEND_SMS", Manifest.permission.SEND_SMS),
new Permissions("ACCESS_BACKGROUND_LOCATION", Manifest.permission.ACCESS_BACKGROUND_LOCATION),
new Permissions("CAMERA", Manifest.permission.CAMERA),
new Permissions("RECORD_AUDIO", Manifest.permission.RECORD_AUDIO),
new Permissions("WRITE_CONTACTS", Manifest.permission.WRITE_CONTACTS),
new Permissions("READ_CONTACTS", Manifest.permission.READ_CONTACTS),
new Permissions("RECORD_AUDIO", Manifest.permission.READ_CALL_LOG)
);
}
in my MainActivity:
protected void onStart() {
mPermissionResultLauncher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() {
#Override
public void onActivityResult(Map<String, Boolean> result) {
for(Permissions permission: GlobalVars.AppPermissions){
if (result.get(permission.ManifestName) != null) {
permission.IsGranted = result.get(permission.ManifestName);
}
}
}
});
if(Build.VERSION.SDK_INT >= 30) {
if (Environment.isExternalStorageManager()){
}else{
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
Uri uri = Uri.fromParts("package", this.getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
}
requestPermission();
super.onStart();
}
private void requestPermission() {
// A simple check of whether runtime permissions need to be managed
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
List<String> permissionRequest = new ArrayList<String>();
for(Permissions permission: GlobalVars.AppPermissions){
int pp = ContextCompat.checkSelfPermission(MainActivity.this, permission.ManifestName);
int pg = PackageManager.PERMISSION_GRANTED;
if (ContextCompat.checkSelfPermission(MainActivity.this, permission.ManifestName) != PackageManager.PERMISSION_GRANTED) {
permissionRequest.add(permission.ManifestName);
}
}
if (!permissionRequest.isEmpty()){
mPermissionResultLauncher.launch(permissionRequest.toArray(new String[0]));
}
}
}
The above code works well and pops up the required requested permissions if they are nor granted.
However, when I check, e.g.:
int me = ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.MANAGE_EXTERNAL_STORAGE);
int re = ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE);
int we = ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
After granting all the permissions MANAGE_EXTERNAL_STORAGE always return -1.
My app as I noticed has not r/w access to other files, e.g. under /sdcard/downloads/
So how can I add R/W permission for all files?

App below android 10
If you want to write and read any file in the External storage, you can use WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE
For Android 10
you can use requestLegacyExternalStorage=true in the application tag in your manifest. It will provide you the access to write file in External storage.
<application
android:name=".GlobalVars"
android:requestLegacyExternalStorage="true"
But it's a temporary solution. So the best solution is using SAF (Storage Access Framework) storage access framework or Scoped Storage Scoped storage
For android 11, Android system ignores the requestLegacyExternalStorage. So you can either Scoped storage or SAF to write any file into storage.
Also Note: If your app targets Android 11, it cannot access the files in any other app's data directory, even if the other app targets Android 8.1 (API level 27) or lower and has made the files in its data directory world-readable.

MANAGE_EXTERNAL_STORAGE is for Andoid 11+ devices.
For an Android 10 device add requestLegacyExternalStorage to manifest file.

I found the solution after some more research:
I ended up doing this:
Add this to manifest file:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- <uses-permission android:name="android.permission.WRITE_SETTINGS" /> -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Define the required permission to ask for:
public static List<Permissions> AppPermissions = Arrays.asList(
new Permissions("MANAGE_EXTERNAL_STORAGE", Manifest.permission.MANAGE_EXTERNAL_STORAGE),
new Permissions("READ_EXTERNAL_STORAGE", Manifest.permission.READ_EXTERNAL_STORAGE),
new Permissions("WRITE_EXTERNAL_STORAGE", Manifest.permission.WRITE_EXTERNAL_STORAGE),
new Permissions("READ_SMS", Manifest.permission.READ_SMS),
new Permissions("SEND_SMS", Manifest.permission.SEND_SMS),
new Permissions("ACCESS_BACKGROUND_LOCATION", Manifest.permission.ACCESS_BACKGROUND_LOCATION),
new Permissions("CAMERA", Manifest.permission.CAMERA),
new Permissions("RECORD_AUDIO", Manifest.permission.RECORD_AUDIO),
new Permissions("WRITE_CONTACTS", Manifest.permission.WRITE_CONTACTS),
new Permissions("READ_CONTACTS", Manifest.permission.READ_CONTACTS),
new Permissions("RECORD_AUDIO", Manifest.permission.READ_CALL_LOG)
);
Require those permission in mainActivity:
ActivityResultLauncher<String[]> mPermissionResultLauncher;
#Override
protected void onStart() {
mPermissionResultLauncher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() {
#Override
public void onActivityResult(Map<String, Boolean> result) {
for(Permissions permission: GlobalVars.AppPermissions){
if (result.get(permission.ManifestName) != null) {
permission.IsGranted = result.get(permission.ManifestName);
}
}
}
});
if(Build.VERSION.SDK_INT >= 30) {
if (Environment.isExternalStorageManager()){
}else{
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
//intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
Uri uri = Uri.fromParts("package", this.getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
}
requestPermission();
super.onStart();
}
private void requestPermission() {
// A simple check of whether runtime permissions need to be managed
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
List<String> permissionRequest = new ArrayList<String>();
for(Permissions permission: GlobalVars.AppPermissions){
int pp = ContextCompat.checkSelfPermission(MainActivity.this, permission.ManifestName);
int pg = PackageManager.PERMISSION_GRANTED;
if (ContextCompat.checkSelfPermission(MainActivity.this, permission.ManifestName) != PackageManager.PERMISSION_GRANTED) {
permissionRequest.add(permission.ManifestName);
}
}
if (!permissionRequest.isEmpty()){
mPermissionResultLauncher.launch(permissionRequest.toArray(new String[0]));
}
}
}

Related

Download File from FirebaseStorage using the file's downloadUrl. (Android, Java)

How do I download a specific file from the FirebaseStorage using its downloadURL?
(e.g. https://firebasestorage.googleapis.com/v0/b/smart-edubox-90c5d.appspot.com/o/uploaded_files%2Fpdf_files%2F08-11-2022_15%3A43%3A02_dummy.pdf?alt=media&token=f68e7403-0cb7-4c86-9799-1c47fffd9cb5 )
I load the image, pdf, and text file into a RecyclerView. When I tap on a CardView (in the RecyclerView) I will be redirected to the file's corresponding download url in a browser. How should I do it so that instead of opening it in a web browser, the file would be downloaded to a specific folder in the user's phone.
Any help is appreciated. Thanks!
To download any file from Url you can simply use the Download Manager of Android
this is code to download file from URL
String[] PERMISSIONS = {
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
android.Manifest.permission.READ_EXTERNAL_STORAGE,
};
if (!hasPermissions(activity.this, PERMISSIONS)) {
String url = "https://firebasestorage.googleapis.com/v0/b/smart-edubox-90c5d.appspot.com/o/uploaded_files%2Fpdf_files%2F08-11-2022_15%3A43%3A02_dummy.pdf?alt=media&token=f68e7403-0cb7-4c86-9799-1c47fffd9cb5";
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("Some descrition");
request.setTitle("Some title");
// in order for this if to run, you must use the android 3.2 to compile your app
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "name-of-the-file.pdf");
// get download service and enqueue file
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
}
this is permission for Storage
public static boolean hasPermissions(Context context, String... permissions) {
if (context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
and your manifest permissions will be
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

new File("/storage/").ListFile() return null on android 11

my app search on /storage folder to find external sd cards. its work on android phone < sdk 30.
but on android 30, I have problem when call line below:
new File("/storage").listFiles();
I wrote permissions for android 11:
in manifest:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
and in code:
if (!Environment.isExternalStorageManager()) {
try {
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.addCategory("android.intent.category.DEFAULT");
intent.setData(Uri.parse(String.format("package:%s", getApplicationContext().getPackageName())));
startActivityForResult(intent, ACTION_MANAGE_STORAGE_PERMISSION_REQUEST_CODE);
} catch (Exception e) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivityForResult(intent, ACTION_MANAGE_STORAGE_PERMISSION_REQUEST_CODE);
}
}
else
StartApp();
everything is OK but 'new File("/storage").listFiles()' return null

Phone not making calls with Intent Android_Call

I'm having some trouble with Intent Action_Call. I put the permission in Manifest, but it doesn't work. I press the button to Call and nothing happens. The app that I'm making is an app that does multiple Intents so the code isn't in MainActivity. I don't know if it helps, but I'm using API 28.
Thanks for reading.
MANIFEST:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.intentsimplicitas">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".SmsActivity"></activity>
<activity android:name=".DialActivity" />
<activity android:name=".WaysActivity" />
<activity android:name=".MapActivity" />
<activity android:name=".PageActivity" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
JAVA (DialActivity.java)
public class DialActivity extends Activity {
Button btnDial;
EditText edtPhone;
String phone;
Intent it;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dial);
btnDial = (Button)findViewById(R.id.btnDial);
edtPhone = (EditText)findViewById(R.id.edtPhone);
}
public void dialClick (View v) {
phone = edtPhone.getText().toString();
Uri uri = Uri.parse("tel: " + phone);
it = new Intent(Intent.ACTION_CALL);
it.setData(uri);
startActivity(it);
}
}
From https://developer.android.com/training/permissions/requesting:
Requesting permission:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.CALL_PHONE)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed; request the permission
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.CALL_PHONE},
MY_PERMISSIONS_REQUEST_CALL_PHONE);
// MY_PERMISSIONS_REQUEST_CALL_PHONE is an
// app-defined int constant. The callback method gets the
// result of the request.
}
} else {
// Permission has already been granted
}
Verifying:
#Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_CALL_PHONE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request.
}
}
You can do via Intent
public void dialClick (View v) {
phone = edtPhone.getText().toString();
Uri uri = Uri.parse("tel: " + phone);
it = new Intent(Intent.ACTION_DIAL);
it.setData(uri);
startActivity(it);
}
You need to add the permissions at run time to be able to make the call, I recommend the following library, since it is much easier to implement the permissions in time of execution.
https://github.com/Karumi/Dexter

Writing permission on android filesystems

I should generate a .pdf file inside the android data folder to use the Java code below, with the permissions enabled in the XML manifest file. But when I run the code I have the following exception. The application has different permissions within the manifest, It should all be configured correctly, I state that the application I'm testing on an old Android 4. How can I solve this? and what is it due to?
Exception: error: java. I. FileNotFoundException: /data/my.pdf:
open failed: EACCES (Permission denied)
Code:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE " />
public static Boolean GeneratePDF(String base64) {
Boolean ret = true;
try {
String direttorio=""+Environment.getDataDirectory().getAbsolutePath();
final File dwldsPath = new File(direttorio + "/" + "my.pdf");
byte[] pdfAsBytes = Base64.decode(base64, 0);
FileOutputStream os;
os = new FileOutputStream(dwldsPath, false);
os.write(pdfAsBytes);
os.flush();
os.close();
} catch (Exception ex) {
System.out.println("\n Errore Generazione File: "+ex);
ret = false;
}
return ret;
}
you have to give Write permission at run time.
It can be achieved something as following...
public class MainActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback{
private static final int REQUEST_WRITE_PERMISSION = 111;
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_WRITE_PERMISSION && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
GeneratePDF("your String name");
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestPermission();
}
private void requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_PERMISSION);
} else {
GeneratePDF("your String name");
}
}
}
Replace this line
String direttorio=""+Environment.getDataDirectory().getAbsolutePath();
To:
String direttorio= Environment.getExternalStorageDirectory().getAbsolutePath();
final File dwldsPath = new File(direttorio + "/" + my.pdf");
if you're using Android 6.0 and above,
there could be 2 ways:
1 if you're making only for demo purpose you can manually give permission to app
by going in settings->apps->permissions. Then allow all permission which are
required.
2 you've to implement runtime permissions so that user can allow it runtime.

Android Wear: Wi-Fi Scan No Results

Whenever I try to use a Wi-Fi Scan for Android Wear, I always get no results from the scan. The code that I use works for my mobile device, but with Android Wear, it always returns an empty list. Code is as follows:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setAmbientEnabled();
mContainerView = (BoxInsetLayout) findViewById(R.id.container);
mTextView = (TextView) findViewById(R.id.text);
mClockView = (TextView) findViewById(R.id.clock);
test = (WifiManager) getSystemService(Context.WIFI_SERVICE);
mTextView.setVisibility(View.VISIBLE);
if (test.isWifiEnabled() == false)
{
test.setWifiEnabled(true);
}
registerReceiver(new BroadcastReceiver()
{
#Override
public void onReceive(Context c, Intent intent)
{
Log.w("myApp", "received");
List<ScanResult> results = test.getScanResults();
int j = 0;
int myArray1[] = new int[results.size()];
String myArray2[] = new String[results.size()];
for (ScanResult result : results) {
//toPrint+= " " + result.BSSID + " " + result.level + "\n";
myArray1[j] = result.level;
myArray2[j] = result.BSSID;
j++;
if (j > 20) {
break;
}
}
Button test2;
test2 = (Button) findViewById(R.id.tLight);
test2.setText("Test: " + Integer.toString(results.size()));
}
}, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
if (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 0x12345);
}
test.startScan();
}
The following permissions are also enabled in the manifest file:
<uses-feature android:name="android.hardware.type.watch" />
<uses-feature android:name="android.hardware.wifi" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

Categories

Resources