Download manager does not work on LG devices - android

I try to perform downloading the file using DownloadManager. Everything works fine except LG devices. Here is my code:
private void downloadFile(FileInfo fileInfo) {
private DownloadManager manager = (DownloadManager) MyApp.getSingleton().
getApplicationContext().getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse("https://"
+ MyPreference.getInstance().getBaseUrl()
+ "/api/v3/files/"
+ fileId
+ "/get"));
request.setDescription(MyApp.getSingleton().getApplicationContext().getString(R.string.downloading));
request.setTitle(fileInfo.getmName());
request.addRequestHeader("Authorization", "Bearer " + MyPreference.getInstance().getAuthToken());
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
File dir = new File(FileUtil.getInstance().getDownloadedFilesDir());
if(!dir.exists()){
dir.mkdirs();
}
request.setDestinationUri(Uri.fromFile(new File(FileUtil.getInstance().getDownloadedFilesDir() + File.separator + fileInfo.getmName())));
downloadId = manager.enqueue(request);
new Thread(() -> {
boolean downloading = true;
while (downloading) {
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downloadId);
Cursor cursor = manager.query(q);
cursor.moveToFirst();
int bytes_downloaded = 0;
long bytes_total = 0;
try {
bytes_downloaded = cursor.getInt(cursor
.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
bytes_total = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
} catch (CursorIndexOutOfBoundsException e) {
e.printStackTrace();
cursor.close();
break;
} catch (IllegalArgumentException e){
e.printStackTrace();
cursor.close();
break;
}
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_FAILED) {
downloading = false;
cursor.close();
onDownloadFail();
break;
} else if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
downloading = false;
cursor.close();
break;
}
if (bytes_total > 0) {
final int dl_progress = (int) ((bytes_downloaded * 100L) / bytes_total);
onProgress(dl_progress);
}
cursor.close();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
On LG devices line
bytes_total = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
returns -1.
Download notification appears in notification bar and disappears immediately after few milliseconds. No one exception, no one enter this code section
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_FAILED) {
downloading = false;
cursor.close();
onDownloadFail();
break;
}
else if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
downloading = false;
cursor.close();
break;
}
Just nothing. So internal while() cycle work forever.
Tested on devices LG D802 and LG G3 S. Both devices show the same behavior.

I faced the same issue and found the solution for this. You need to make sure all the directories exists before init Download Manager.
Example: in my case the path to my File is
/storage/emulated/0/MyFolder/n.jpeg
so I have to make sure MyFolder directory exists before init Download Manager.

Related

DownloadManager.remove(download_id) crash app

I am trying to cancel downloading task with id.
I get id from
DownloadManager manager = (DownloadManager) getApplicationContext().getSystemService(Context.DOWNLOAD_SERVICE);
downloadId = manager.enqueue(req);
I want to stop download when on user button click, but I tested to stop download after 10% of being downloaded in this test code.
the code "manager.remove(downloadId);" is working perfect to clear downloading noti and stopping the task with requested ID. But it also stop the app too, app error also occur after that code. please how can I solve the problem.
new Thread(new Runnable() {
#Override
public void run() {
boolean downloading = true;
while (downloading) {
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downloadId);
cursor = manager.query(q);
cursor.moveToFirst();
int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
final int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
downloading = false;
}
final int dl_progress = (int) ((bytes_downloaded * 100l) / bytes_total);
String finalDl_size;
int dl_size = (int) (bytes_total/(1024*1024));
finalDl_size = Integer.toString(dl_size)+" MB";
if(dl_size>1000){dl_size=(int) (bytes_total/(1024*1024*1024));
finalDl_size = Integer.toString(dl_size)+" GB";}
final String finalDl_size1 = finalDl_size;
runOnUiThread(new Runnable() {
#Override
public void run() {
btndownload.setText("Downloading "+Integer.toString(dl_progress)+"% , "+ finalDl_size1);
if(dl_progress==100){
btndownload.setBackgroundColor(Color.GREEN);
btndownload.setText("Download Completed");
}
else if(dl_progress>10){
try{
manager.remove(downloadId); ///// Stop after 10%
}
catch (Exception e){}
}
}
});
cursor.close();
}
}
}).start();
Logcat Output
Please Kindly help me. Thank you in advance.
Try this
if (cursor.getCount() > 0)
manager.remove(downloadId); ///// Stop after 10%

Scanning internal storage in android for all images

I am trying to scan internal storage for all the available images, but getting 0 results, where as, i store one image just before doing the scan, that image is "wallpaper.jpg".
Thanks in advance for any help.
boolean fileFlag= fileExistance("/wallpaper.jpg");
System.out.println(fileFlag); // this returns "true"
initMediaContentLevels(TAG, Images.Media.INTERNAL_CONTENT_URI, CoreConstants.DATATYPE_PHOTO, listener);
protected void initMediaContentLevels(final String tag, final Uri mediaUri, final int dataType, final DataManagerListener listener) {
LOG.i(TAG, "initMediaContentLevels("+tag+","+mediaUri+","+dataType+") mClassItemsTotal="+mClassItemsTotal);
//TODO if the data card is not mounted or missing then this returns 0 .. should test that sd card is available when app starts
String[] projection = {MediaStore.MediaColumns.DATA};
Cursor mediaExtCur = sContext.getContentResolver().query(
mediaUri,
projection,
null,
null,
null);
LOG.d(TAG, "initMediaContentLevels("+tag+","+mediaUri+","+dataType+") mediaExtCur="+mediaExtCur);
if (mediaExtCur!=null) {
int numItems = mediaExtCur.getCount(); //allows for chaining of class for one upload group (row of UI)
LOG.d(TAG, "initMediaContentLevels("+tag+") numItems="+numItems);
try {
if (numItems > 0) {
while (mediaExtCur.moveToNext()) {
String filepath = getString(mediaExtCur, MediaColumns.DATA);
File f = new File(filepath);
if (!f.exists() || !f.canRead()) {
LOG.e(TAG, "initMediaContentLevels("+tag+") file "+f.getAbsolutePath()+" "+(f.exists()?"is not readable":"does not exist"));
continue;
}
long fileSize = f.length();
if (exceedsFileSizeLimit(fileSize)) {
LOG.e(TAG, "initMediaContentLevels("+tag+") file is too large to announce "+filepath+": "+fileSize);
//files larger than the max are not counted
continue;
}
mBytesTotal += fileSize; //db sizes are unreliable
mClassItemsTotal++;
}
LOG.d(TAG, "initMediaContentLevels("+tag+") mBytesTotal="+mBytesTotal+", mClassItemsTotal="+mClassItemsTotal);
}
}
catch (Exception e) {
LOG.e(TAG,"problem getting media count "+e.toString());
}
finally {
if (!mediaExtCur.isClosed()) {
mediaExtCur.close();
}
}
}
LOG.d(TAG, "initMediaContentLevels("+tag+") listener="+listener);
listener.initialiseClassCount(dataType, mClassItemsTotal, mBytesTotal);
LOG.d(TAG, "initMediaContentLevels("+tag+") done");
}

how to pause downloadmanager in android

The question is I have implemented android downloadmanager to download files from internet. how can i pause and resume the download? i have read lots of posts and searched google but could not find a working answer. Thanks
DownloadManager.Request downloadRequest = new DownloadManager.Request(Uri.parse(url + fileName));
downloadRequest.setTitle("Downloading: ");
downloadRequest.setDescription("Description");
downloadRequest.allowScanningByMediaScanner();
downloadRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
downloadRequest.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS,applicationApk);
manager = (DownloadManager) downloadActivity.getSystemService(Context.DOWNLOAD_SERVICE);
downloadId = manager.enqueue(downloadRequest);
new Thread(new Runnable()
{
#Override
public void run()
{
int fileSize = size;
downloadProgress.setProgress(0);
downloadProgress.setMax(fileSize);
sizeInBytes = fileSize * 1024 * 1024;
DownloadManager.Query q = new DownloadManager.Query();
//q.setFilterById(downloadId);
downloading = true;
while (downloading)
{
Cursor cursor = manager.query(q);
if (cursor.moveToFirst())
{
int sizeIndex = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
int downloadedIndex = cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
long size = cursor.getInt(sizeIndex);
long downloaded = cursor.getInt(downloadedIndex);
if (size != -1) dl_progress = downloaded * fileSize / size;
}
downloadProgress.setProgress((int) dl_progress);
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL)
{
downloading = false;
}
cursor.close();
}
}
}).start();

How to find database path in Android 4.4 (API level: 19)?

Trying to read values from the database, that is created in webview using javascript, but unable to get the database path using
getDatabasePath()
Which seems to be deprecated is there is any solution or work around for this.
Thanks in advance
String webviewDBPath = getFilesDir().getParent() + "/"; // getFilesDir().getParent() returns base path of app private data
if (Build.VERSION.SDK_INT <= 18) { // Below kitkat
webviewDBPath += <ur old db folder>;
}
webview.getSettings().setDatabasePath(webviewDBPath);
From kitkat, we can't change webview database path. Default database path is /data/data/{package name}/app_webview/databases/. For below kitkat, we can set database path to any location.
If you want to access database created by websql, then query path of database from Databases.db.
public String getWebViewDBPath() {
if (Build.VERSION.SDK_INT > 18) {
return "app_webview/databases";
} else {
return "{any folder}";
}
}
public String getDBFileName(ZoomRxApp ctx, String dbName) {
String dbFilePath = getFilesDir().getParent() + "/" + getWebViewDBPath() + "/Databases.db";
SQLiteDatabase webSqlDb = SQLiteDatabase.openOrCreateDatabase(dbFilePath, null);
Cursor result = null;
String dbFileName = null;
try {
String query = "select * from Databases where name like '"+dbName+"'";
result = webSqlDb.rawQuery(query, null);
while (result != null && result.moveToNext()) {
String origin = result.getString(result.getColumnIndex("origin"));
if(Build.VERSION.SDK_INT <= 18) {
dbFileName = origin + "/" + result.getString(result.getColumnIndex("path"));
} else {
dbFileName = origin + "/" + result.getString(result.getColumnIndex("id"));
}
break;
}
} catch (RuntimeException e) {
throw e;
} catch (Exception ex) {
ex.printStackTrace();
}
finally {
if(result != null) {
result.close();
}
if(webSqlDb != null) {
webSqlDb.close();
}
}
}

Stop saving photos using Android native camera

I am using native Android camera and save file to my application data folder (/mnt/sdcard/Android/data/com.company.app/files/Pictures/). At the same time anther copy of photo is saved to DCIM folder.
This is my code:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String formattedImageName = getDateString() + ".jpg";
File image_file = new File(this.getExternalFilesDir(Environment.DIRECTORY_PICTURES), formattedImageName);
Uri imageUri = Uri.fromFile(image_file);
intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);
startActivityForResult(intent, REQUEST_FROM_CAMERA);
How can I prevent saving additional copy of image to DCIM folder?
Many Thanks
You can use the following :
First we get the last saved image by checking which was the last modified image. Then check if last modified time is in the last few seconds. You may also have to check the exact location of where camera stores the image.
private boolean deleteLastFromDCIM() {
boolean success = false;
try {
File[] images = new File(Environment.getExternalStorageDirectory()
+ File.separator + "DCIM/Camera").listFiles();
File latestSavedImage = images[0];
for (int i = 1; i < images.length; ++i) {
if (images[i].lastModified() > latestSavedImage.lastModified()) {
latestSavedImage = images[i];
}
}
// OR JUST Use success = latestSavedImage.delete();
success = new File(Environment.getExternalStorageDirectory()
+ File.separator + "DCIM/Camera/"
+ latestSavedImage.getAbsoluteFile()).delete();
return success;
} catch (Exception e) {
e.printStackTrace();
return success;
}
}
Unfortunately, some smart phones save images in another folder such as DCIM/100MEDIA. So can't rely to these solution. I prefer use this way:
String[] projection = new String[] {
MediaStore.Images.ImageColumns._ID,
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.MIME_TYPE};
final Cursor cursor = managedQuery(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,projection, null, null,
MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");
if(cursor != null){
cursor.moveToFirst();
// you will find the last taken picture here and can delete that
}
I tried to find out if a second copy exists and delete the copy. I used the above code to find the last taken picture.
Notice: Don't use cursor.close(); after using managedQuery, Leave the cursor for the Android system to manage and don't call that. You can see managedQuery()
Notice2: The managedQuery method is deprecated and it should be avoided, implement CursorLoaders instead.
check this code..
private void FillPhotoList() {
// initialize the list!
GalleryList.clear();
String[] projection = { MediaStore.Images.ImageColumns.DISPLAY_NAME };
for(int i=0;i<projection.length;i++)
Log.i("InfoLog","projection "+projection[0].toString());
// intialize the Uri and the Cursor, and the current expected size.
Cursor c = null;
Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Log.i("InfoLog","FillPhoto Uri u "+u.toString());
// Query the Uri to get the data path. Only if the Uri is valid.
if (u != null)
{
c = managedQuery(u, projection, null, null, null);
}
// If we found the cursor and found a record in it (we also have the id).
if ((c != null) && (c.moveToFirst()))
{
do
{
// Loop each and add to the list.
GalleryList.add(c.getString(0)); // adding all the images sotred in the mobile phone(Internal and SD card)
}
while (c.moveToNext());
}
Log.i(INFOLOG,"gallery size "+ GalleryList.size());
}
and this is where the method is doing all magic
/** Method will check all the photo is the gallery and delete last captured and move it to the required folder.
*/
public void movingCapturedImageFromDCIMtoMerchandising()
{
// This is ##### ridiculous. Some versions of Android save
// to the MediaStore as well. Not sure why! We don't know what
// name Android will give either, so we get to search for this
// manually and remove it.
String[] projection = { MediaStore.Images.ImageColumns.SIZE,
MediaStore.Images.ImageColumns.DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATA,
BaseColumns._ID,};
// intialize the Uri and the Cursor, and the current expected size.
for(int i=0;i<projection.length;i++)
Log.i("InfoLog","on activityresult projection "+projection[i]);
//+" "+projection[1]+" "+projection[2]+" "+projection[3] this will be needed if u remove the for loop
Cursor c = null;
Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Log.i("InfoLog","on activityresult Uri u "+u.toString());
if (CurrentFile != null)
{
// Query the Uri to get the data path. Only if the Uri is valid,
// and we had a valid size to be searching for.
if ((u != null) && (CurrentFile.length() > 0))
{
//****u is the place from data will come and projection is the specified data what we want
c = managedQuery(u, projection, null, null, null);
}
// If we found the cursor and found a record in it (we also have the size).
if ((c != null) && (c.moveToFirst()))
{
do
{
// Check each area in the gallery we built before.
boolean bFound = false;
for (String sGallery : GalleryList)
{
if (sGallery.equalsIgnoreCase(c.getString(1)))
{
bFound = true;
Log.i("InfoLog","c.getString(1) "+c.getString(1));
break;
}
}
// To here we looped the full gallery.
if (!bFound) //the file which is newly created and it has to be deleted from the gallery
{
// This is the NEW image. If the size is bigger, copy it.
// Then delete it!
File f = new File(c.getString(2));
// Ensure it's there, check size, and delete!
if ((f.exists()) && (CurrentFile.length() < c.getLong(0)) && (CurrentFile.delete()))
{
// Finally we can stop the copy.
try
{
CurrentFile.createNewFile();
FileChannel source = null;
FileChannel destination = null;
try
{
source = new FileInputStream(f).getChannel();
destination = new FileOutputStream(CurrentFile).getChannel();
destination.transferFrom(source, 0, source.size());
}
finally
{
if (source != null)
{
source.close();
}
if (destination != null)
{
destination.close();
}
}
}
catch (IOException e)
{
// Could not copy the file over.
ToastMaker.makeToast(this, "Error Occured", 0);
}
}
//****deleting the file which is in the gallery
Log.i(INFOLOG,"imagePreORNext1 "+imagePreORNext);
Handler handler = new Handler();
//handler.postDelayed(runnable,300);
Log.i(INFOLOG,"imagePreORNext2 "+imagePreORNext);
ContentResolver cr = getContentResolver();
cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, BaseColumns._ID + "=" + c.getString(3), null);
break;
}
}
while (c.moveToNext());
}
}
}
A nice solution by Parth. But it's good for Samsungs that keep images in DCIM/Camera. Some phones - Sony Ericssons, HTCs keep them in folders like DCIM/100MEDIA, DCIM/100ANDRO so I have slightly modified the code:
private boolean deleteLastFromDCIM() {
boolean success = false;
try {
//Samsungs:
File folder = new File(Environment.getExternalStorageDirectory() + File.separator + "DCIM/Camera");
if(!folder.exists()){ //other phones:
File[] subfolders = new File(Environment.getExternalStorageDirectory() + File.separator + "DCIM").listFiles();
for(File subfolder : subfolders){
if(subfolder.getAbsolutePath().contains("100")){
folder = subfolder;
break;
}
}
if(!folder.exists())
return false;
}
File[] images = folder.listFiles();
File latestSavedImage = images[0];
for (int i = 1; i < images.length; ++i) {
if (images[i].lastModified() > latestSavedImage.lastModified()) {
latestSavedImage = images[i];
}
}
success = latestSavedImage.delete();
return success;
} catch (Exception e) {
e.printStackTrace();
return success;
}
}
I am encountering a similar problem with the Moto Z Force (7.1.1). I have the MediaStore.EXTRA_OUTPUT defined on the intent, but a duplicate file is still created in the camera directory.
I need to test on other devices, but here's an approach I took regarding this issue. Rather than trying to find the specific camera directory, I'm using the MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME location.
Here's my code snippet:
private void removeCameraDuplicate() {
String[] proj = {
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns._ID };
String selection = MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME + " = ? ";
String[] selectionArgs = new String[] { "Camera" };
Cursor cursor = mActivity.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, proj, selection, selectionArgs, MediaStore.Images.ImageColumns.DATE_TAKEN + " desc");
if (cursor != null) {
int idxPath = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
if (cursor.getCount() > 0 && idxPath > -1 && cursor.moveToFirst()) {
File original = new File(mMediaPath);
File cameraDupe = new File(cursor.getString(idxPath));
if (original.exists() && cameraDupe.exists()) {
LogUtils.LOGE("***> camera", "original " + original.length());
LogUtils.LOGE("***> camera", "original " + original.lastModified());
LogUtils.LOGE("***> camera", "duplicate " + cameraDupe.length());
LogUtils.LOGE("***> camera", "duplicate " + cameraDupe.lastModified());
if (original.length() == cameraDupe.length() && original.lastModified() == cameraDupe.lastModified()) {
if (cameraDupe.delete()) {
LogUtils.LOGE("***> camera", "duplicate deleted");
}
}
}
}
cursor.close();
}
}

Categories

Resources