Download Multiple Images and Change Extension After Downloading - android

My requirement is to download multiple images in a loop in activity or AsycTask doinBackground method with download manager(I just need to initialize the download but it continue to download images even after app get closed) and store all the images inside sd card within my application folder (eg MyAppFolder) because I need to share image path with another Application and after downloaded
I need to change the extension of images so that it is not visible in gallery folder.

public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
String root_sd = Environment.getExternalStorageDirectory().toString();
// Set the URL to download image
String PhotoPictureDownLoadPath= "http://test.com/test.jpg";
String photoPictureDirectoryPath = root_sd + "/DownloadImages/";
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Call this method in a loop to DOwnLoad Multiple Images.
new DownloadImages(MainActivity.this,PhotoPictureDownLoadPath,photoPictureDirectoryPath);
}
}
// Class to download Images
public class DownloadImages {
Context myContext;
String myDownlaodURL;
String mySdCardSaveImagePath;
public DownloadImages(Context theContext, String theUrl, String thePath) {
myContext = theContext;
myDownlaodURL = theUrl;
mySdCardSaveImagePath = thePath;
String PhotoPictureName = getFilename(myDownlaodURL);
File PhotoPictureSavePath = new File(mySdCardSaveImagePath + "/" + PhotoPictureName);
if (PhotoPictureSavePath.exists()) {
return;
}
if (!PhotoPictureSavePath.exists()) {
download();
}
}
public String getFilename(String theFileName) {
String filename = theFileName.substring(theFileName.lastIndexOf("/") + 1, theFileName.length());
return filename;
}
public void download() {
Uri Download_Uri = Uri.parse(myDownlaodURL);
DownloadManager downloadManager = (DownloadManager) myContext.getSystemService(myContext.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Download_Uri);
//Restrict the types of networks over which this download may proceed.
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
//Set whether this download may proceed over a roaming connection.
request.setAllowedOverRoaming(true);
//Set the local destination for the downloaded file to a path within the application's external files directory
//request.setDestinationInExternalFilesDir(myContext, mySdCardSaveImagePath, split[split.length - 1]);
//request.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES, split[split.length-1]);
String[] split = myDownlaodURL.split("/");
//Set the local destination for the downloaded file to the folder specified by user.
File destinationFile = new File(mySdCardSaveImagePath, split[split.length - 1]);
request.setDestinationUri(Uri.fromFile(destinationFile));
//Set the title of this download, to be displayed in notifications (if enabled).
request.setTitle(split[split.length - 1]);
//Set a description of this download, to be displayed in notifications (if enabled)
request.setDescription(mySdCardSaveImagePath);
request.setVisibleInDownloadsUi(true);
//Enqueue a new download and get the reference Id
long downloadReference = downloadManager.enqueue(request);
}
}
//change the extension of image after downloading
public class DownloadBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
long downloadId = intent.getLongExtra(
DownloadManager.EXTRA_DOWNLOAD_ID, 0);
DownloadManager myDownloadManager = (DownloadManager) context.getSystemService(context.DOWNLOAD_SERVICE);
Cursor c = myDownloadManager.query(new DownloadManager.Query().setFilterById(downloadId));
if (c.moveToFirst()) {
int columnIndex = c
.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == c
.getInt(columnIndex)) {
int filenameIndex = c.getColumnIndex(DownloadManager.COLUMN_TITLE);
String filename = c.getString(filenameIndex);
int filePathIndex = c.getColumnIndex(DownloadManager.COLUMN_DESCRIPTION);
String filePath = c.getString(filePathIndex);
if (!filename.isEmpty()) {
int dotposition = filename.lastIndexOf(".");
String filename_Without_Ext = filename.substring(0, dotposition);
String Ext = filename.substring(dotposition + 1, filename.length());
String newFileName = filename_Without_Ext + ".change" + Ext;
boolean success = new File(filePath + "/" + filename).
renameTo(new File(filePath + "/" + newFileName));
//Log.d("Log", "" + success);
}
}
}
}
}
}
//use bellow premissions
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<!-- Register Receiver in Manifest-->
<receiver android:name=".DownloadBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
</intent-filter>
</receiver>

Related

Download Speed is slow in Android

I have a list of PDFs that I need to download all PDFs in one click. I have implemented a foreground service to do the task. In this service I am enqueuing the list of PDFs in the Android DownloadManager's request to handle the downloads.
For the enqueue of request, I am inserting 6 PDF's in request for the first time and further when any one download completed I am inserting next PDF in the request list.
In this implementation the whole process is taking around 1-2 mins for the 91 PDFs(roughly size of 40MB in total). Is there any way, so we can speed up the download process.
This is the function to start Download queue
private void startDownloadQueue()
{
for(int i=0;i<6;i++){
if(i<hashMap.size()) {
listIndex++;
initiateDownload(documentList.get(i), positionList.get(i), hashMap.size());
}
}
}
private void initiateDownload(DocumentJsonModel.Document doc, int pos, int listSize)
{
if (doc != null && isDownloading) {
String position = String.valueOf(pos);
String docId = doc.id;
String docFile = doc.file;
String docName = doc.name;
String docDescription = doc.description;
boolean isJustView = false;
isFromSearch = false;
long id = downloadFile(doc, docId, docFile, docName, docDescription, position, isJustView, listSize);
if (id != 0) {
setProgressUpdate(id, Integer.parseInt(position), Integer.parseInt(docId), isJustView, doc, listSize);
} else if (isJustView) {
Intent intent1 = new Intent(INTENT_FILTER_ACTION_OPEN_DOC);
intent1.putExtra("docID",docId);
intent1.putExtra("position",pos);
intent1.putExtra("fromDownloadAll", true);
intent1.putExtra("docId", docId);
sendBroadcast(intent1);
stopForeground(true);
stopSelf();
} else if (isFromSearch) {
Intent intent1 = new Intent(INTENT_FILTER_ACTION_OPEN_DOC_FROM_SEARCH);
intent1.putExtra("fromDownloadAll", true);
intent1.putExtra("position", pos);
intent1.putExtra("docId", docId);
sendBroadcast(intent1);
stopForeground(true);
stopSelf();
}
}
}
Method to enqueue PDFs in download manager request queue -
public long downloadFile(DocumentJsonModel.Document doc,String docId, String docFile, String docName, String description, String position, boolean isJustView, int listSize) {
long downloadReference = 0;
String root = "/twoway/saved_documents/";
String BASE_DIR = getExternalFilesDir(null).getPath();
File dir = new File(BASE_DIR + root);
File file = new File(dir, docId + "_" + docFile);
if(!isCancelledButtonPressed) {
if (!file.exists()) {
String fileUrl = DOCUMENT_URL + docFile;
fileUrl = fileUrl.replaceAll(" ", "%20");
Uri fileUri = Uri.parse(fileUrl);
//Create request for android download manager
DownloadManager downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(fileUri);
//set title for download
request.setTitle(docName);
request.setVisibleInDownloadsUi(false);
//request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION);
//Setting description of request
request.setDescription(description);
request.setDestinationInExternalFilesDir(this, null, "/twoway/saved_documents/"
+ docId + "_" + docFile);
//Enqueue download and save into referenceId
downloadReference = downloadManager.enqueue(request);
}
}}

Why does Environment.getExternalStorageDirectory() create direcotory in Cache folder

When I use Environment.getExternalStorageDirectory()+File.separator+"applicationAsbid"; I expect to create a directory in device's external storage but it is created in Cache folder.
Why?
What happened and what should I do?
UPDATE:
This is my method:
root = Environment.getExternalStorageDirectory().getPath();
myDir = new File(root);
myDir.mkdir();
private void downloadDoc(ProgressBar progressBar, CircularImageView imageView, String name, String link, SendMessageViewModel messageData) {
progressBar.setVisibility(View.VISIBLE);
Uri uri = Uri.parse(link);
DownloadManager downloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(uri);
request.setTitle("در حال دانلود");
request.setDescription("لطفا منتظر بمانید...");
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
request.setDestinationInExternalFilesDir(mContext, root, name);
final long id = downloadManager.enqueue(request);
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(id);
Cursor cursor = downloadManager.query(query);
if (cursor.moveToFirst()) {
long downloadedBytes = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
long totalBytes = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
final int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
final int percent = (int) ((downloadedBytes * 100) / totalBytes);
((Activity) mContext).runOnUiThread(new Runnable() {
#Override
public void run() {
progressBar.setProgress(percent);
if (percent == 100) {
Toast.makeText(mContext, "دانلود با موفقیت انجام شد", Toast.LENGTH_SHORT).show();
timer.purge();
timer.cancel();
for (int item : downloadList) {
if (Integer.parseInt(messageData.getId()) == item) {
imageView.setImageResource(R.drawable.ic_doc3);
imageView.setContentDescription("after");
progressBar.setVisibility(View.GONE);
}
}
}
}
});
}
}
}, 0, 100);
}
At the end I should say this is not my own code and my colleague has written that. We check that and found nothing so I aske here.
We use Downloadmanager in another class and for download something else. That works fine but here it does not work.
Second Update:
I changed my code to this:
root = Environment.getExternalStorageDirectory().getPath() + "/Dehkade/Chat1";
myDir = new File(root);
if (!myDir.exists()) {
if (!myDir.mkdir()) {
Toast.makeText(mContext," ...sorry could not create directory...",Toast.LENGTH_SHORT).show();
return;
}
}
But it does not work too, in fact the Toast is executed. Also I use this code:
request.setDestinationInExternalFilesDir(mContext, null, name);
Instead of this code:
request.setDestinationInExternalFilesDir(mContext, root, name);
But nothing changes.

Speeding up the doinbackground() process

I'm splitting an encrypted video into 4 parts using this code
public class SplitVideoFile {
private static String result;
static ArrayList<String>update=new ArrayList<>();
public static String main(File file) {
try {
// File file = new File("C:/Documents/Despicable Me 2 - Trailer (HD) - YouTube.mp4");//File read from Source folder to Split.
if (file.exists()) {
String videoFileName = file.getName().substring(0, file.getName().lastIndexOf(".")); // Name of the videoFile without extension
// String path = Environment.getDataDirectory().getAbsolutePath().toString() + "/storage/emulated/0/Videointegrity";
String path = "/storage/emulated/0/Videointegrity";
// File myDir = new File(getFile, "folder");
//myDir.mkdir();
File splitFile = new File(path.concat("/").concat(videoFileName));//Destination folder to save.
if (!splitFile.exists()) {
splitFile.mkdirs();
Log.d("Directory Created -> ", splitFile.getAbsolutePath());
}
int i = 01;// Files count starts from 1
InputStream inputStream = new FileInputStream(file);
String videoFile = splitFile.getAbsolutePath() +"/"+ String.format("%02d", i) +"_"+ file.getName();// Location to save the files which are Split from the original file.
OutputStream outputStream = new FileOutputStream(videoFile);
Log.d("File Created Location: ", videoFile);
update.add("File Created Location: ".concat(videoFile));
int totalPartsToSplit =4 ;// Total files to split.
int splitSize = inputStream.available() / totalPartsToSplit;
int streamSize = 0;
int read = 0;
while ((read = inputStream.read()) != -1) {
if (splitSize == streamSize) {
if (i != totalPartsToSplit) {
i++;
String fileCount = String.format("%02d", i); // output will be 1 is 01, 2 is 02
videoFile = splitFile.getAbsolutePath() +"/"+ fileCount +"_"+ file.getName();
outputStream = new FileOutputStream(videoFile);
Log.d("File Created Location: ", videoFile);
streamSize = 0;
}
}
outputStream.write(read);
streamSize++;
}
inputStream.close();
outputStream.close();
Log.d("Total files Split ->", String.valueOf(totalPartsToSplit));
result="success";
} else {
System.err.println(file.getAbsolutePath() +" File Not Found.");
result="failed";
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public ArrayList<String> getUpdate()
{
return update;
}
And in my activity file i call this using async task's doinbackground method like below
protected String doInBackground(Void...arg0) {
Log.d(TAG + " DoINBackGround", "On doInBackground...");
File encvideo=new File(epath.getText().toString());
SplitVideoFile split=new SplitVideoFile();
String result=split.main(encvideo);
publishProgress(1);
return result;
}
Even though it splits the video, it takes too much of time to do the process.
How can I speed them up. As I'm showing a progress bar in preexecute method it looks like the user sees the progress bar for a long time, which I don't want.

PlaceHolder reason for Download Failure using Download Manager in Android

I am using Download Manager to download files of types(.mov, .pdf, .png). When I call download manager, download fails giving reason as Place holder. What does place holder mean and how do I fix this issue? Please help!
My code is as follows:
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadUrlFile))
.setDestinationInExternalFilesDir(context,
(Environment.DIRECTORY_DOWNLOADS), downloadFileName).setNotificationVisibility(visibility);
mEnqueue = downloadManager.enqueue(request);
mDownloadReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "DOWNLOAD_STATUS"+intent.getAction());
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
Query query = new Query();
query.setFilterById(mEnqueue);
Cursor c = downloadManager.query(query);
if (c.moveToFirst()) {
int columnIndex = c .getColumnIndex(DownloadManager.COLUMN_STATUS);
Log.d("getColumnIndex()", "Reason: " + c
.getColumnIndex(DownloadManager.COLUMN_STATUS)+DownloadManager.STATUS_SUCCESSFUL);
if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
Log.d(TAG, "DOWNLOAD_STATUS_SUCCESSFUL");
} else if (DownloadManager.STATUS_FAILED == c.getInt(columnIndex)) {
Log.d("handleData()", "Reason: " + c.getString(c.getColumnIndex(DownloadManager.COLUMN_REASON)));
Log.d(TAG, "DOWNLOAD_STATUS_FAILED");
}
}
}
}
};
The problem is that the column "COLUMN_REASON" is an int and not a String (despite some examples I have seen that imply it is a string).
Hence you should be using:
Log.d("handleData()", "Reason: " + c.getInt(c.getColumnIndex(DownloadManager.COLUMN_REASON)));
The value can be found:
Here
and
here

Android DownloadManager - Is there a way to be notified when a user deletes a download from the UI?

I cannot find a way to be notified when a user cancels a download in the system's DownloadManager UI:
I know that it is possible to set a BroadcastReceiver for downloads "completed" or "clicked", via the dedicated intent actions:
DownloadManager.ACTION_DOWNLOAD_COMPLETE
and
DownloadManager.ACTION_NOTIFICATION_CLICKED
I need to know when a running download is cancelled, instead.
As commented above, my solution (thanks to various pages from SO):
// DownloadManager job from the main activity
videoUri = Uri.parse(path.toURI() + composedFilename);
dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
Request request = new Request(Uri.parse(link));
request.setDestinationUri(videoUri);
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
request.setTitle(vfilename);
enqueue = dm.enqueue(request);
Log.d(DEBUG_TAG, "_ID " + enqueue + " enqueued");
fileObserver = new Utils.delFileObserver(path.getAbsolutePath());
fileObserver.startWatching();
// delFileObserver class inside another Utility class
public static class delFileObserver extends FileObserver {
static final String TAG="FileObserver: ";
String rootPath;
static final int mask = (FileObserver.CREATE | FileObserver.DELETE | FileObserver.DELETE_SELF);
public delFileObserver(String root){
super(root, mask);
if (! root.endsWith(File.separator)){
root += File.separator;
}
rootPath = root;
}
public void onEvent(int event, String path) {
if (event == FileObserver.DELETE || event == FileObserver.DELETE_SELF){
Log.d(DEBUG_TAG, TAG + "file " + path + " DELETED");
long id = settings.getLong(path, 0);
Log.d(DEBUG_TAG, TAG + "id: " + id);
// actual job after a file deletion is detected
}
}
public void close(){
super.finalize();
}
}

Categories

Resources