Android partial download http - android

In my application I download media from server via HTTP connection. While downloading if connection is break anyhow (say, no n/w, permission revoke), File get downloaded partially.
Earlier we are deleting the file and downloading it from the scratch.
Now, the requirement is changed. I have to continue from where I left (like in WhatsApp).
So what I am doing is checking the file existence and if file exist skip the stream. Please find the below code snip.
InputStream is = con.getInputStream();
File file = new File(targetPath);
boolean fileExist = file.exists();
if (fileExist) {
long skippedBytes = is.skip(file.length());
}
// opens an output stream to save into file
OutputStream os = new FileOutputStream(targetPath, fileExist);
Its working merely in respect of skipping but actually not working.
Say, file (video) length is 20 sec and in first attempt I downloaded up to 6 sec and rest subsequently. But when I play it just play till 6 sec then after throw the usual Video playback error.

File file = new File(targetPath);
if (file.exists()) {
con.setRequestProperty("Range", "bytes=" + (file.length()) + "-");
} else {
con.setRequestProperty("Range", "bytes=" + 0 + "-");
}

Related

Unable to append bytes at the end of the file in SD card - Lollipop

I am building a downloading manager to download files and save it to my sd card. For API>=23, I have to use FileOutputStream, which help me to resume the file in case downloading fails.
However, in API 21 & API 22 (Lollipop), one can't write in Sd card, but it can be done with the help of DocumentFile. I am able to create files and folders in Lollipop but unable to resume downloading if the file is partially downloaded. My code is as follows:
if (file.exists()) {
downloaded = (int) file.length();
connection.setRequestProperty("Range", "bytes=" + (file.length()) + "-");
String s = file.getPath();
String s1 = getRealPathFromURI(documentFile.getUri());
s = s.replace(s1, "");
Uri uri2 = Uri.parse(documentFile.getUri().toString() + Uri.encode(s));
output = getContentResolver().openOutputStream(uri2);
} else {
connection.setRequestProperty("Range", "bytes=" + downloaded + "-");
DocumentFile tempDocumentFile = documentFile.createFile("video/mp4", "temp/" + downloadsPaths.get(i));
output = getContentResolver().openOutputStream(tempDocumentFile.getUri());
}
It is rewriting the current file. I am looking for handling append mode in DocumentFile. I have provide all the required permissions. Help me out here, thanks in advance.

download manager class crashes when try to download multiple files?

i am trying to download images from the web when my app is connected to the internet through this code
public void downloadimages(String url,String filename)
{
String ur1=url,v1=filename;
downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
Uri Download_Uri = Uri.parse(ur1);
DownloadManager.Request request = new DownloadManager.Request(Download_Uri);
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
request.setAllowedOverRoaming(false);
request.setDescription("Android Data download using DownloadManager.");
request.setDestinationInExternalFilesDir(getApplicationContext(),Environment.DIRECTORY_DOWNLOADS,v1 + ".jpg");
downloadManager.enqueue(request);
}
when i run the app first time downloads happen but the app crashes after that the app did'nt open i am checking for the dowloaded files also:
String path = "/mnt/sdcard/Android/data/com.example.webdata/files/Download/" + extra2 + ".jpg";
tt1.append(path);
File f = new File(path);
if(f.exists())
{
//Toast.makeText(getApplicationContext(), "File already exists....",
// Toast.LENGTH_SHORT).show();
}
else
{
downloadimages(extra,extra2);
}
if the file has been downloaded previously it should not be dowloaded next time ,but i my app crashes and i don't know why any help guys.........
this is my logcat output:-
02-21 18:00:41.547: E/AndroidRuntime(23964): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.webdata/com.example.webdata.MainActivity}: java.lang.IndexOutOfBoundsException: Invalid index 1088, size is 1088
Can you show us the code MainActivity class, because it seems that the error comes from this class.
then the error is a IndexOutOfBoundsException, so have you tried with less image eg 10 or 20? and run later when the first 10 are recovered?

is it possible downloading application from my web site

As you understand, I will download application from my server if user click on the download link. And of course for installing, user will accept in irder to install it. Thus, I wonder ;
Is it possible to download package from my server? If yes how ?
Yes, it is possible. Make sure you have your server configured to use the appropriate mime type.
AddType application/vnd.android.package-archive .apk
OR
Download App
To download the apk in your app, you can use the my open source library here. While it is meant for checking for and downloading updates, you can use it to download other apk files (or any other file at all) as well.
In your Activity add the following code to your onCreate(). If you don't want toast notifications, change the second parameter to false:
UpdateChecker checker = new UpdateChecker(this, true);
Then, use the following to download and install the update. Note that this will show a progress dialog while downloading:
checker.downloadAndInstall("URL with http:// to the location of the update apk");
If the Android framework has downloaded an .apk file it will ask you if you want to install it. Simple as that.
here is the code to download the apk file:
String fileName="yourApk.apk";
try
{
File root = android.os.Environment.getExternalStorageDirectory();
File dir = new File (root.getAbsolutePath()+"/DownloadedApk/");
if(dir.exists()==false)
{
dir.mkdirs();
}
URL url = new URL("http://www.example.com/apk/yourApk.apk");
URLConnection ucon = url.openConnection();
InputStream is = ucon.getInputStream();
FileOutputStream fos = new FileOutputStream(dir+"/"+fileName);
byte data[] = new byte[1024];
long lenghtOfFile=ucon.getContentLength();
int count = 0;
long total = 0;
int progress = 0;
while (((count=is.read(data)) != -1))
{
total += count;
int progress_temp = (int) ((int)total*100/lenghtOfFile);
if(progress_temp%10 == 0 && progress != progress_temp)
{
progress = progress_temp;
publishProgress(progress);
}
fos.write(data, 0, count);
}
is.close();
fos.close();
} catch (Exception e)
{
Log.d("DownloadManager", "Error: " + e);
}

Download DRM Files on my develop android app

I'm newbe in android development.
I bulid app for automatic downloader,
every downloads work properly and save on my sd card,
but the drm file not open on device.
I explain my self, I try download file with extension dd\dm,
If the regular browser download dd\dm files, the device extract them to dcf extension.
my app not do that... I notied then if my device do restart, every is right,
in fact the device change the extension of this file to dcf, and i can play this song, If i didnt originator restart to device, the files extension stay on .dd.dm
mt content type is: application/vnd.oma.drm.message
Somebody knows how i need care of that??
This Is my code.....
class DownloadFileFromURL extends AsyncTask<String, String, String> {
/**
* Before starting background thread
* Show Progress Bar Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(progress_bar_type);
}
/**
* Downloading file in background thread
* */
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.getContent();
conection.connect();
// getting file length
int lenghtOfFile = conection.getContentLength();
// Insert Information Of File to Array
getCurrentArray()[index].setSizeOfFile(OrangeFile.convertToStringRepresentation(lenghtOfFile));
getCurrentArray()[index].setMimeOfFile(conection.getContentType());
// input stream to read file - with 8k buffer
InputStream input = new BufferedInputStream(url.openStream(), 8192);
// Output stream to write file
OutputStream output = new FileOutputStream(mPath + getCurrentArray()[index].getNameOfFile() + "." + getCurrentArray()[index].getExtOfFile());
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
publishProgress(""+(int)((total*100)/lenghtOfFile));
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
Though its an old question, not sure if you got any answer for this already.
Below is how to overcome this problem.
First of all you cannot download ".dm" & ".dd" files via File Connection API, though you can successfully download them you cannot use it directly.
Check this http://www.developer.nokia.com/Community/Wiki/Saving_and_reading_DRM-protected_files_using_FileConnection_API_and_Mobile_Media_API
".dm" files are converted to ".dcf" automatically when there is a thorough memory scan
of sd card by your device OS. If you just unmount the sd card and remount then also the files are converted without having to restart the device.
So how to actually download these files to be used immediately without restarting the device.
As stated in the above link you can download the protected content only via HTTP (in browser) or MMS.
So create an Intent with url pointing to the ".dm" file on your server and fire it. Browser will catch the url and download the file and convert it to ".dcf" automatically as soon as the download is complete.
Hope this helps.
Edit: You can explicitly invoke the media scanner once you downloaded the file via File Connection API by creating an intent with action "ACTION_MEDIA_SCANNER_SCAN_FILE" and send a broadcast.

Android MediaRecorder Class: Does the setOutputFile() method append data to the existing file?

I am using MediaRecorder in my Android app. I referred to the online documentation for the public void setOutputFile (String path) of the MediaRecorder class but couldn't find information as to whether it overwrites an existing file at the same path or appends to the existing file, if it exists.
So, two questions:
Does public void setOutputFile (String path) overwrite the file at path, if it exists, or it appends to the file at path?
Is there any way to resume an already paused recording which is saved at a particular path?
Thanks in advance.
So far from my finding, I conclude that the Android API currently does not provide an option to resume recording using MediaRecorder.
So manage my target of merging two recorded audio, I went with direct merging of two files by skipping the headers from the second file.
Following is my code for reference:
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
/* If the voiceMessage in consideration is a PAUSED one, then we should
* record at a new alternate path so that earlier recording does not get overwritten, and can be used later for merging */
Log.d(LOG_TAG, "VoiceMessageManager:recordVoiceMessage() - state of voice message - " + voiceMessage.getVoiceMessageState());
mRecorder.setOutputFile(filePath);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mRecorder.prepare();
mRecorder.start();
And my code for combining the two audio files is as follows:
protected Void doInBackground(String... filePaths) {
try {
String originalVoiceMessageRecording = filePaths[0];
String newVoiceMessageRecording = filePaths[1];
File outputFile = new File(originalVoiceMessageRecording);
FileOutputStream fos = new FileOutputStream(outputFile, true); // Second parameter to indicate appending of data
File inputFile = new File(newVoiceMessageRecording);
FileInputStream fis = new FileInputStream(inputFile);
Log.d(LOG_TAG, "Length of outputFile: " + outputFile.length() + " and Length of inputFile: " + inputFile.length() );
byte fileContent[]= new byte[(int)inputFile.length()];
fis.read(fileContent);// Reads the file content as byte from the list.
/* copy the entire file, but not the first 6 bytes */
byte[] headerlessFileContent = new byte[fileContent.length-6];
for(int j=6; j<fileContent.length;j++){
headerlessFileContent[j-6] = fileContent[j];
}
fileContent = headerlessFileContent;
/* Write the byte into the combine file. */
fos.write(fileContent);
/* Delete the new recording as it is no longer required (Save memory!!!) :-) */
File file = new File(newVoiceMessageRecording);
boolean deleted = file.delete();
Log.d(LOG_TAG, "New recording deleted after merging: " + deleted);
Log.d(LOG_TAG, "Successfully merged the two Voice Message Recordings");
Log.d(LOG_TAG, "Length of outputFile after merging: " + outputFile.length());
} catch (Exception ex) {
Log.e(LOG_TAG, "Error while merging audio file: " + ex.getMessage());
}
return null;
}
In short what I am doing is - skipping the headers of the second file (The length of the header in AMR file is 6 bytes).
This worked for me and I tested it on Android version 2.3
Hope this helps others!

Categories

Resources