permission denied write with USB pen drive - java

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" />

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" />

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.

java.io.FileNotFoundException open failed: EEXIST (File exists) Android 11

I was trying to download an image from a server and save it in the external memory, but in Android 11 it gives me an error when I try to create the file.
I have granted permission to access the external storage.
i searched a bit on the internet and they suggested me to put this code in the manifest, but it didn't work for android 11
android:requestLegacyExternalStorage="true"
manifest
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
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.TestDwonloadImgApp"
android:usesCleartextTraffic="true">
<activity android:name=".MainActivity2">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity">
</activity>
</application>
MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageView img = findViewById(R.id.img);
ImmagineInterface ii = RetrofitManager.retrofit.create(ImmagineInterface.class);
Call<ResponseBody> call = ii.downloadFile("/immaginimusei/arte-scienza.jpg");
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.code() == 200) {
boolean result = writeResponseBody(response.body(), "/immaginimusei/arte-scienza.jpg");
if(result) {
Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString() + "/ArtHunter/immaginimusei/arte-scienza.jpg");
img.setImageBitmap(bitmap);
}
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString() + "/ArtHunter/immaginimusei/arte-scienza.jpg");
img.setImageBitmap(bitmap);
}
});
}
}
writeResponseBody
public static boolean writeResponseBody(ResponseBody body, String dir1) {
try {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// todo change the file location/name according to your needs
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString() + "/ArtHunter";
String path1 = path + dir1;
File f = new File(path1);
String path2 = f.getPath();
String nome = f.getName();
path2 = path2.replaceAll("/" + nome, "");
File directory = new File(path2);
if (!directory.exists())
directory.mkdirs();
File img = new File(path2, nome);
if (img.exists())
return true;
img.createNewFile();
InputStream inputStream = null;
FileOutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
inputStream = body.byteStream();
outputStream = new FileOutputStream(img); //error here!
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
}
outputStream.flush();
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
}
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
error
/System.err: java.io.FileNotFoundException: /storage/emulated/0/Download/ArtHunter/immaginimusei/arte-scienza.jpg: open failed: EEXIST (File exists)
W/System.err: at libcore.io.IoBridge.open(IoBridge.java:492)
at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
at com.theapplegeek.testdwonloadimgapp.MainActivity.writeResponseBody(MainActivity.java:93)
at com.theapplegeek.testdwonloadimgapp.MainActivity$1.onResponse(MainActivity.java:47)
at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1.lambda$onResponse$0$DefaultCallAdapterFactory$ExecutorCallbackCall$1(DefaultCallAdapterFactory.java:89)
at retrofit2.-$$Lambda$DefaultCallAdapterFactory$ExecutorCallbackCall$1$hVGjmafRi6VitDIrPNdoFizVAdk.run(Unknown Source:6)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:245)
at android.app.ActivityThread.main(ActivityThread.java:8004)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:631)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:978)
Caused by: android.system.ErrnoException: open failed: EEXIST (File exists)
at libcore.io.Linux.open(Native Method)
at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
W/System.err: at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7865)
at libcore.io.IoBridge.open(IoBridge.java:478)
... 13 more
In Android 11 android:requestLegacyExternalStorage="true" will simply be ignored, since it was an ad-hoc solution for Android < 11 to not break old apps.
Now, you must use
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
Also you could just use SAF to avoid all this 'permissions' hassle. This is what Google recommends for apps that do not need to manage most internal storage data. Refer to:
https://developer.android.com/guide/topics/providers/document-provider
However, if you don't want to break you app and lose all your hard work, consider
if(Environment.isExternalStorageManager())
{
internal = new File("/sdcard");
internalContents = internal.listFiles();
}
else
{
Intent permissionIntent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivity(permissionIntent);
}
This will bring up a settings page where you will be able to give storage access to your app. If the app already has permission, then you will be able to access the directory. Place this at the very beginning of onCreate() method after setting layout resource.
It's best not to do this for any future apps you build.
Go to your mobile setting -> apps -> select your app -> permissions -> storage -> select Allow managment of all files
It works for me.
Android has become too complex when it comes to creating folders.
If you want to avoid so many problems and not use things like android:requestLegacyExternalStorage="true" and adding many permissions like MANAGE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE which can be a nightmare, even when it comes to publishing your app to the marketplace.
In addition to that, from Android version 30 onwards, you ca NOT extend android:requestLegacyExternalStorage="true". So you will have problems again.
What is recommended is to start to save your recordings inside applications dedicated folder, because in the future Android will no longer let you create folders anymore, even with legacy methods. You can use standard directories in which to place any file like DIRECTORY_MUSIC, DIRECTORY_PICTURES, etc.
For instance, I created my own method for saving audio recording in Android 33 and it works perfectly. I don't need to add anything to my Manifest.
override fun startRecording(): Boolean {
try {
val recordingStoragePath = "${app.getExternalFilesDir(Environment.DIRECTORY_MUSIC)}"
recordingFilePath = "$recordingStoragePath/${fileRecordingUtils.generateFileName()}"
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC)
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
// Audio Quality Normal
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
mediaRecorder.setAudioSamplingRate(8000)
// Set path
mediaRecorder.setOutputFile(recordingFilePath)
mediaRecorder.prepare()
mediaRecorder.start()
Toast.makeText(app, "Recording Started", Toast.LENGTH_SHORT).show()
} catch (e: IOException) {
Toast.makeText(app, "Recording Failed. Problem accessing storage.", Toast.LENGTH_SHORT).show()
mediaRecorder.reset()
return false
} catch (e: Exception) {
mediaRecorder.reset()
return false
}
return true
}

Update android debug app causes "app is not installed" (no google play)

I am trying to make possible for users to update ann app from device. We have a server where from user can download apk file with new version of an app.
Here is the code which starts after button pressed:
Handler handler = new Handler(Looper.getMainLooper());
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
File folder = new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString());
File file = new File(folder.getAbsolutePath(), "localdb.apk");
final Uri uri = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) ?
FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider", file) :
Uri.fromFile(file);
if (file.exists())
file.delete();
//url to get app from server
String url = Names.UPDATE_URL;
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL sUrl = new URL(url);
connection = (HttpURLConnection) sUrl.openConnection();
connection.connect();
// download the file
input = connection.getInputStream();
output = new FileOutputStream(file);
byte data[] = new byte[4096];
int count;
while ((count = input.read(data)) != -1) {
// allow canceling with back button
output.write(data, 0, count);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
handler.post(new Runnable() {
#Override
public void run() {
Intent install = new Intent(Intent.ACTION_INSTALL_PACKAGE)
.setData(uri)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(install);
}
});
}
});
thread.start();
Here is what i have in manifest:
...<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET" />
<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.QUICKBOOT_POWERON" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
...
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="ru.mob.myapp.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
...
and finally an xml file provider_paths:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
</paths>
So, everything works fine, I download apk with new version, it is named same as already installed,
system asks me to install (update) my application, but when everything is almoust done I get "App is not installed" message without any details.
Does anyone have a solution, hint, adviŅe?

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.

Categories

Resources