Download File from FirebaseStorage using the file's downloadUrl. (Android, Java) - 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" />

Related

Unable to request MANAGE_EXTERNAL_STORAGE (android 10)

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]));
}
}
}

saving a captured image to external storage failed

I want to save my captured images to a specific directory (/sdcard/DCIM/FokusStacker) with the following method. I have tried different Locations, but none of them worked.
private void capturePicture(){
File dir = new File("/sdcard/DCIM/FokusStacker");
String fileName = "IMG_"+ System.currentTimeMillis();
File file = new File(dir,fileName);
Log.d(TAG, "capturePicture: DIRECTORY: "+dir.getAbsolutePath());
ImageCapture.OutputFileOptions outputFileOptions =
new ImageCapture.OutputFileOptions.Builder(file).build();
imageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() {
#Override
public void onImageSaved(#NonNull ImageCapture.OutputFileResults outputFileResults) {
Log.d(TAG, "onImageSaved: SAVED");
return;
}
#Override
public void onError(#NonNull ImageCaptureException exception) {
Log.d(TAG, "onError: FAILED");
return;
}
});
}
These are the Permission i've included:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
And i also tried saving it to the internal storage.
Code Snippet for to get the local directoryof the App for the file:
File dir = getApplicationContext().getFilesDir();
Can anyone please guide me how to do this?
I am a little new to android so please, I would appreciate if I can have a detailed procedure.

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.

How can I delete an external folder with Android?

I have been searching for it but theres no any answer to my problem. I am programming an app and I want to delete an external folder. For example /storage/emulated/0/MyFolder, there is a lot of ways to create and read files from a internal app folder and an external app folder, but I dont know how to acces to files in "/storage/emulated/0/...".
Thanks.
public static void deleteDir(Context ctx) {
try {
File myFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
+ File.separator
+ "MyFolder");
}
if (myFile.exists()) {
deleteRecursive(myFile);
}
}catch (Exception ignored){
Log.e("Delete error File: %s",ignored.getMessage());
}
}
private static void deleteRecursive(File myFile) {
if (myFile.isDirectory())
for (File child : myFile.listFiles())
deleteRecursive(child);
Log.e("MyFolder Files Deleted!!! : %s", myFile.delete());
}
Add this lines to app manifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Update
- As mentioned by CommonsWare runtime permission request needed for Android 6+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 101);
} else {
deleteDir(context);
}
Your Activity
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case 101:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
deleteDir(context);
}
}
}
new File("/storage/emulated/0/MyFolder").delete();
# your manifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Update: As mentioned by CommonsWare hardcoded filesystem paths might be invalid for some versions of Android.
new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/MyFolder").delete();

permission denied write with USB pen drive

this is my AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.abc2"
android:versionCode="1"
android:versionName="1.1.8" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
and i m trying to copy the apps's database to USB pendrive, last time are using SD card, it is working fine, but after i have change the SD card path to /mnt/sda/sda2 it is error permission denied, /mnt/sda/sda2 is the USB pendrive path
this is the copy file function to copy the database to pendrive
private void copyFile(String inputPath, String inputFile, String outputPath) {
InputStream in = null;
OutputStream out = null;
try {
//create output directory if it doesn't exist
File dir = new File (outputPath);
if (!dir.exists())
{
dir.mkdirs();
}
in = new FileInputStream(inputPath + inputFile);
out = new FileOutputStream(outputPath + inputFile);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
in = null;
// write the output file (You have now copied the file)
out.flush();
out.close();
out = null;
Toast.makeText(UltilityActivity.this, "Export successful!", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException fnfe1) {
Log.e("tag", fnfe1.getMessage());
Toast.makeText(UltilityActivity.this, "Export failed", Toast.LENGTH_SHORT).show();
}
catch (Exception e) {
Log.e("tag", e.getMessage());
Toast.makeText(UltilityActivity.this, "Export failed", Toast.LENGTH_SHORT).show();
}
}
}
this is how i call the copyfile function
copyFile("/data/data/com.example.abc2/databases/","DB_BusData","/mnt/sda/sda2/");
last time is copied to SD card , with this code
copyFile("/data/data/com.example.abc2/databases/","DB_BusData","/mnt/sdcard/");
copied to SD card are working, but USB pendrive errror with :-
03-10 10:58:13.204: D/MainActivity(1832): open failed: EACCES (Permission denied)
03-10 10:58:13.204: D/MainActivity(1832): java.io.IOException: open failed: EACCES (Permission denied)
it is need to mount USB drive? can i mount in programmatically ? how? please give me an example?
in Android OS, Usually USB pendrive will know as SD card,
But, the permission in Androidmanifest.xml need to declare different permission,
USB external storage need media enable permission like below :-
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />

Categories

Resources