I'm just playing around with Android Studio and I'm trying to figure out how to Download a file into /system.
I understand I need root for this and I already got that part working, the only trouble I'm having is with
request.setDestinationInExternalPublicDir("/system/", "test.jpg");
The goal is to download a file and save it to /system with the file name being test.jpg.
So the end is the file is located at /system/test.jpg.
The issue with this is that DownloadManager is saving it to internal storage and is creating a new folder named 'system'.
I can tell it has something to do with setDestinationInExternalPublicDir but I'm just not sure what to change it to.
Thanks again
What I did is that:
(It's a part in one of my projects)
/*****DOWNLOAD FILE*****/
DownloadManager.Request request = new DownloadManager.Request(Uri.parse("https://github.com/pelya/android-keyboard-gadget/blob/master/hid-gadget-test/hid-gadget-test?raw=true"));
request.setDescription("hid-gadget-test");
request.setTitle("hid-gadget-test");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
}
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "hid-gadget-test"); /*****SAVE TO DOWNLOAD FOLDER*****/
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
File mvfile = new File("/sdcard/"+Environment.DIRECTORY_DOWNLOADS+"/hid-gadget-test");
while (!mvfile.exists()) {} /*****WAIT UNTIL DOWNLOAD COMPLETE*****/
try {
Thread.sleep(5000);
} catch (InterruptedException ignored) {}
try { /*****RUN MV-COMMAND TO MOVE TO ROOT DIR*****/
Process su = Runtime.getRuntime().exec("su");
DataOutputStream outputStream = new DataOutputStream(su.getOutputStream());
outputStream.writeBytes("mv /sdcard/"+Environment.DIRECTORY_DOWNLOADS+"/hid-gadget-test /data/local/tmp/hid-gadget-test\n");
outputStream.flush();
outputStream.writeBytes("exit\n");
outputStream.flush();
su.waitFor();
} catch (IOException e) {
Toast.makeText(getApplicationContext(), "IOException", Toast.LENGTH_SHORT).show();
} catch (InterruptedException e) {
Toast.makeText(getApplicationContext(), "InterruptedException", Toast.LENGTH_SHORT).show();
}
The wait-until-download-complete-thingy is a bit hacky, I found it here. It will maybe not work with files that take more than 5 seconds to download
Related
I am trying to write an app that allows me to connect to my Olympus camera through wifi, and use it's built-in server to pull my raw images from it. My problem is that, when I'm on the camera's wifi, downloadManager doesn't seem to work, only when I connect my phone to the web. Am I missing something here, or is this tool really not fit for this task?
My DownloadManager:
public void getImage(String imageName, Context context) {
File file = new File(Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString(), imageName);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse("http://192.168.0.10/DCIM/100OLYMP/" + imageName))
.setTitle(imageName + ": OlyRaw Image")
.setDescription("Downloading")
.setDestinationInExternalFilesDir(context, Environment.DIRECTORY_DCIM, imageName)
.setAllowedOverMetered(true)
.setRequiresCharging(false)
.addRequestHeader("user-agent", "OlympusCameraKit")
.addRequestHeader("host", "192.168.0.10")
.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
Log.d("Response", "http://192.168.0.10/DCIM/100OLYMP/" + imageName);
DownloadManager downloadManager = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE);
try{
downloadId = downloadManager.enqueue(request);
Log.d("Response", String.valueOf(downloadId));
}
catch (Exception e) {
Log.d("Response", e.toString());
}
}
I have the same issue : as soon as I use my mobile as a hotspot, DownloadManager is not working. I get a download failure notification with no additional information.
There is nothing in the intent get in onReceive method of the registered BroadcastReceiver
I works like a charm if the 2 devices are connected to my home WIFI.
I have released App "A". Now I prepare to release App "B" that should load copy database from App "A" to enable users continue writing data.
This code from App "A" save db from internal storage to a file on scoped storage:
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DISPLAY_NAME, "/databasename.db");
values.put(MediaStore.MediaColumns.MIME_TYPE, "application/vnd.sqlite3");
values.put(MediaStore.MediaColumns.RELATIVE_PATH, DIRECTORY_DOWNLOADS);
Uri uri = getContentResolver().insert(MediaStore.Files.getContentUri("external"), values);
if (uri != null) {
OutputStream outputStream = getContentResolver().openOutputStream(uri);
if (outputStream != null) {
outputStream.write("This is menu category data.".getBytes());
outputStream.close();
Toast.makeText(ActivitySettings.this, "File created successfully", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(ActivitySettings.this, "outputStream == null", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(ActivitySettings.this, "uri == null", Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
Toast.makeText(ActivitySettings.this, "Fail to create file", Toast.LENGTH_SHORT).show();
}
This code from App "B" should upload database file that was saved in App "A":
try {
File sd = Environment.getDataDirectory();
File data = Environment.getStorageDirectory();
try {
String currentDBPath = "emulated/0/" + DIRECTORY_DOWNLOADS + "/databasename.db";
String backupDBPath = "/data/com.example.mypackagename/databases/databasename.db";
File currentDB = new File(data, currentDBPath);
File backupDB = new File(sd, backupDBPath);
if (currentDB.exists()) {
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
Toast.makeText(this, R.string.toast_db_loaded_succesfully, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, R.string.toast_db_not_exists, Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Toast.makeText(this, R.string.toast_not_access, Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Log.e("DBError", "exception", e);
Toast.makeText(this, R.string.toast_error_load_db, Toast.LENGTH_LONG).show();
}
It's working as well on Android 10 and below but it's not possible due to new access rules of scoped storage Android 11. With MANAGE_EXTERNAL_STORAGE permission it's possible but in my case Google may reject App "B" due to a policy violation.
SharedUserId is deprecated
Sharing files via FileProvider carried out by Activity with UI and additional user's operations.
But I need way without any additional operations, just load database with one click from App "B". It's possible on Android 11? Maybe there is an alternative to SharedUserId?
Any help/thoughts.
Thanks.
The new security requirements are a welcome change from a security standpoint.
The best solution is to send an upgrade to the existing app A to send the data an external endpoint accessible by app B.
Having App A modify App B data without app B's permission IS a violation of security protocols and should NEVER be allowed.
Unless you are the owner of both app A and app B, what you are asking is impossible and should never be allowed to happen.
So I have this app, but its to big for the play store because it has lots of pdfs, so I decided to use play asset delivery to retrieve the pdfs. I have done everything like it says in google docs, I have created an asset-package, changed everything in the manifest, build.gradle and build a bundle! But the play asset delivery just isn't working! I can't get my pdf files that are on the "pdfs->src->main->assets" !! Can someone please help me? Am I choosing the right package name?
My source code to retrieve the pdf is the following :
mPDFView = (PDFView) findViewById(R.id.pdf);
Context context = null;
try {
context = createPackageContext(getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
AssetManager assetManager = context.getAssets();
try {
InputStream is = assetManager.open("A abóboda.pdf");
mPDFView.fromStream(is).load();
} catch (IOException e) {
e.printStackTrace();
}
I created a recording application, user can upload data to google firebase and also can restore the data. That's it, that's all my app does. Now I tested my restoring process with 600 files (mp3 files), then I saw that when I call download manager then the files start downloading but they download one at a time which makes the process very time-consuming. So is there any way to make Download manager to download all the files simultaneously.
void startDownloading(String DownloadUrl, String DownloadPath, String DownloadName) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(DownloadUrl));
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
request.setTitle("Data");
request.setDescription("Journals");
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
request.setDestinationInExternalPublicDir(DownloadPath, DownloadName);
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
}
So I download the files by sending the link, path, and name of the file into the above method, and then task get added to DownloadManager in android device.
How to allow download Manager to download all of them simultaneously as we do in other browsers.
See if you are downloading using download manager then we can download a single file at a time and it depends on the device actually. Many phones have advance download manager but some have a simple manager who can download a single file at a time.
So solution is here instead of calling the download manager we can use this code to download files, it is awesome and always works fine. It downloads all the files simultaneously.
Here is the code:
void startDownloading
(final String DownloadUrl, String DownloadPath, String DownloadName) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
final File file = new File(StringManager.phoneStorageLocation + "/"
+ DownloadPath + "/" + DownloadName);
if (file.exists()) { // decide what to do
} else {
new Thread(new Runnable() {
#Override
public void run() {
try {
URL url = new URL(DownloadUrl);
ReadableByteChannel rbc = Channels.newChannel(url.openStream());
FileOutputStream fos = new FileOutputStream(file);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
} catch (IOException ignored) {
}
}
}).start();
}
}
The above code will download the file in phone storage, Hope it helps someone.
Hey Guys I did a little App, where I type into a textbox a specific value (height, weight) and save it into a file.
I did this but I do not know, which path I have to use for Android.
Hope you can help :)
public void SaveList(View view) {
//Pf`enter code here`ad, im privaten Speicherbereich
File file = new File("I need this path :)");
try {
OutputStreamWriter fdg = new OutputStreamWriter(new FileOutputStream(file));
fdg.write(""+this.weight);
fdg.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
You can use Environment.getDataDirectory() to get the root directory, if you dont have an SD card.
If you have an SD card, use Environment.getExternalStorageState()
Read more about them in the docs
Thus, change your code as follows
File file = new File(Environment.getDataDirectory()+"/your_folder_name/your_file_name");
This will create a file with name your_file_name in the folder your_folder_name in your internal storage.