Reputation: 33
I have a button to download file from localhost. It works for small size file like 1-2 MB but not working for big size file like 10-15 MB. I have attached my code.
pdf_download.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
Uri uri = Uri.parse(base_url+pdf);
DownloadManager.Request request = new DownloadManager.Request(uri);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
Long reference = downloadManager.enqueue(request);
}
});
Upvotes: 1
Views: 1443
Reputation: 358
You can follow the retrofit file saving procedure instead of download manager
https://futurestud.io/tutorials/retrofit-2-how-to-download-files-from-server
Upvotes: 0
Reputation: 1782
I have also used different way to download a file from server.
first one which you already are using as DowanloadManager
2nd one was to use AsyncTask to Download a file.
class DownloadTask : AsyncTask<String, Int, String>() {
lateinit var downloadTaskListener: DownloadTaskListener
lateinit var pm: PowerManager
private var mWakeLock: PowerManager.WakeLock? = null
// private lateinit var mProgressBar: ProgressBar
private var fileName: String? = null
private var fileNameWithoutExtn: String? = null
private val dialog: Dialog? = null
// private var alertDialog: AlertDialog? = null
//lateinit var txtFileSize: TextView
internal var total: Long = 0
private var fileLength: Int = 0
//lateinit var btnCancel: Button
override fun doInBackground(vararg sUrl: String): String? {
var input: InputStream? = null
var output: OutputStream? = null
var connection: HttpURLConnection? = null
var outPutFile: File? = null
try {
val url = URL(sUrl[0])
connection = url.openConnection() as HttpURLConnection
connection.connect()
// expect HTTP 200 OK, so we don't mistakenly save error report
// instead of the file
if (connection.responseCode != HttpURLConnection.HTTP_OK) {
return ("Server returned HTTP " + connection.responseCode
+ " " + connection.responseMessage)
}
// this will be useful to display download percentage
// might be -1: server did not report the length
fileLength = connection.contentLength
// download the file
input = connection.inputStream
fileName = sUrl[0].substring(sUrl[0].lastIndexOf('/') + 1, sUrl[0].length)
fileNameWithoutExtn = fileName!!.substring(0, fileName!!.lastIndexOf('.'))
Log.d("check", "name $fileName without extention $fileNameWithoutExtn")
outPutFile = downloadTaskListener.getFilePath("$fileNameWithoutExtn.apk")
output = FileOutputStream(outPutFile)
val data = ByteArray(4096)
total = 0
var count: Int=input.read(data)
while (count != -1) {
// allow canceling with back button or click on Cancel button
if (isCancelled) {
output.flush()
output.close()
input!!.close()
return null
}
total += count.toLong()
// publishing the progress....
if (fileLength > 0)
// only if total length is known
Log.d("check", total.toString() + "")
publishProgress((total * 100 / fileLength).toInt())
output.write(data, 0, count)
}
} catch (e: Exception) {
return e.toString()
} finally {
try {
output?.close()
input?.close()
// outPutFile!!.setReadable(true, false)
} catch (ignored: IOException) {
}
connection?.disconnect()
}
return null
}
override fun onPreExecute() {
super.onPreExecute()
// take CPU lock to prevent CPU from going off if the user
// presses the power button during download
// val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager
mWakeLock = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
javaClass.name
)
mWakeLock!!.acquire()
//
// val dialogBuilder = AlertDialog.Builder(context)
// // ...Irrelevant code for customizing the buttons and title
// val inflater = LayoutInflater.from(context)
// val customProgress = inflater.inflate(R.layout.custom_progress_dialog, null)
// dialogBuilder.setView(customProgress)
//
// alertDialog = dialogBuilder.create()
// alertDialog!!.setCancelable(false)
//
// mProgressBar = customProgress.findViewById(R.id.downloadProgressBar)
// mProgressBar!!.progressDrawable = context.resources.getDrawable(R.drawable.custom_progress)
// txtFileSize = customProgress.findViewById(R.id.txt_file_size)
// txtFileSize.text = "Downloading is starting ...."
// btnCancel = customProgress.findViewById(R.id.btnCancel)
downloadTaskListener.showDialog()
// txtFileSize= alertDialog!!.txt_file_size
// mProgressBar= alertDialog!!.downloadProgressBar
// btnCancel= alertDialog!!.btnCancel
downloadTaskListener.getCancelButton().setOnClickListener { cancel(true) }
downloadTaskListener.updateDialogData(0,"Downloading is starting ....")
// dialog.show();
// alertDialog!!.show()
downloadTaskListener.showDialog().show()
}
// Display the async tas progress
override fun onProgressUpdate(vararg values: Int?) {
downloadTaskListener.updateDialogData(values[0]!!,"Download progress : " + Utils.bytes2String(total) + "/" + Utils.bytes2String(fileLength.toLong()))
// mProgressBar.progress = values[0]!!
// mProgressBar.setMax(100)
// txtFileSize.text = "Download progress : " + Utils.bytes2String(total) + "/" + Utils.bytes2String(fileLength.toLong())
// downloadTaskListener.showToast("Downloaded ${values[0]} %")
super.onProgressUpdate(values[0])
}
override fun onPostExecute(result: String?) {
mWakeLock!!.release()
//mProgressDialog.dismiss();
//dialog.dismiss();
downloadTaskListener.showDialog()!!.dismiss()
if (result != null)
// Toast.makeText(context, "Download error: $result", Toast.LENGTH_LONG).show()
downloadTaskListener.showToast("Download error: $result")
else {
// Toast.makeText(context, "Apk downloaded", Toast.LENGTH_SHORT).show()
downloadTaskListener.showToast("Apk downloaded")
// txtFileSize.text = "APK Downloaded Completely."
downloadTaskListener.updateDialogData(100,"APK Downloaded Completely.")
// val file = File(Utils.getAbsoluteFile("", context), "$fileNameWithoutExtn.apk")
val file=downloadTaskListener.getFilePath("$fileNameWithoutExtn.apk")
//File file = new File("/sdcard/update.apk");
var fileUri = Uri.fromFile(file)
if (file.exists()) {
Log.d("check", "file exists " + file.absolutePath + fileUri)
} else {
Log.d("check", "file does not exist " + file.absolutePath)
}
if (Build.VERSION.SDK_INT >= 24) {
// fileUri = FileProvider.getUriForFile(
// context,
// context.applicationContext.packageName + ".my.package.name.provider",
// file
// )
}
val intent = Intent(Intent.ACTION_VIEW, fileUri)
intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true)
intent.setDataAndType(fileUri, "application/vnd.android" + ".package-archive")
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
// context.startActivity(intent)
downloadTaskListener.startActivity(intent)
}
}
override fun onCancelled(s: String) {
super.onCancelled(s)
Log.d("TASK TAG", "Cancelled.")
// txtFileSize.text = "Downloading Cancelled"
// Toast.makeText(context, "Downloading Cancelled ", Toast.LENGTH_SHORT).show()
downloadTaskListener.showToast("Downloading Cancelled ")
// mProgressBar!!.progress = 0
//alertDialog!!.dismiss()
downloadTaskListener.updateDialogData(0, "Downloading Cancelled")
downloadTaskListener.showDialog().dismiss()
}
interface DownloadTaskListener{
fun showToast(text: String)
fun startActivity(intent: Intent)
fun getFilePath(fileName:String):File
fun showDialog():AlertDialog
fun updateDialogData(progress:Int,msg:String)
fun getCancelButton():Button
}
}
3rd one which i think is best for large files to download a file usig third party Library Android Networking Library first put the library in gradle
implementation 'com.amitshekhar.android:android-networking:1.0.2'
then write this code
AndroidNetworking.download(url,dirPath,fileName)
.setTag("downloadTest")
.setPriority(Priority.MEDIUM)
.build()
.setDownloadProgressListener(new DownloadProgressListener() {
@Override
public void onProgress(long bytesDownloaded, long totalBytes) {
// do anything with progress
}
})
.startDownload(new DownloadListener() {
@Override
public void onDownloadComplete() {
// do anything after completion
}
@Override
public void onError(ANError error) {
// handle error
}
});
Upvotes: 1
Reputation: 358
To download such a large files, you need to download those in chunks. Either you can use any library that support HTTP range options to allow to pull down a single file in multiple pieces , supporting resume etc.
Or you can split your large file on your server then have a text file with MD5 hash of each file, when you first start to download then get the MD5 file once finish then check that hashes matches the downloaded pieces. If they do not then delete that piece and add it to queue of items to download.
Once all pieces downloaded and MD5 works, you can put the pieces back together as single file.
If you are thinking to download the file in the SD card then FAT32 is the default file system.
Upvotes: 0