Я также использовал другой способ загрузки файла с сервера.
Первый, который вы уже используете как DowanloadManager
Второй - использовать AsyncTask для загрузки файла.
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
}
}
3-й, который, я думаю, лучше всего подходит для больших файлов, чтобы загрузить файл, используя стороннюю библиотеку. Сетевая библиотека Android сначала поставит библиотеку в gradle
implementation 'com.amitshekhar.android:android-networking:1.0.2'
, затем напишет этот код
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
}
});
Достаточно ли хорош JLS ?
Преобразование приведения применяется к операнду оператора приведения (§15.16): тип выражения операнда должен быть преобразован к типу, явно названному оператором приведения. Контексты приведения позволяют использовать:
- преобразование идентичности (§5.1.1)
- расширяющееся примитивное преобразование (§5.1.2)
- сужающее примитивное преобразование (§5.1.3)
- расширение преобразование ссылки (§5.1.5), необязательно, за которым следует неконтролируемое преобразование (§5.1.9)
- , преобразование сужающей ссылки (§5.1.6), необязательно, за которым следует неконтролируемое преобразование
- преобразование упаковки (§5.1.7) )
- преобразование распаковки (§5.1.8).
На самом деле, может быть эта часть более актуальна: S - это тип класса:
финальным
класс (§8.1.1),
тогда, если существует супертип
X из T и супертип
Y из S , так что оба
X и Y доказуемо
различные параметризованные типы, и что
стирание X и Y
такие же, ошибка времени компиляции
происходит. В противном случае актерский состав всегда
допустимо во время компиляции (потому что даже если
S не реализует T ,
подкласс S might). последний
класс (§8.1.1),
тогда S должен реализовать T ,
или возникает ошибка времени компиляции. Объект
или
происходит ошибка времени компиляции. финал
(§8.1.1),
тогда, если существует супертип
X из T и супертип
Y из S , так что оба
X и Y доказуемо
различные параметризованные типы, и что
стирание X и Y
такие же, ошибка времени компиляции
происходит. В противном случае актерский состав всегда
допустимо во время компиляции (потому что даже если
T не реализует S ,
подкласс T might). final
,
затем: Объект
, затем
возникает ошибка времени компиляции (потому что
Объект
- единственный класс
тип, которому могут быть присвоены массивы).
java.io.Serializable
или
тип Cloneable
,
только интерфейсы, реализованные массивами.
Объект
или тип
java.io.Serializable
или
тип Cloneable
или
переменная типа, которую S может
законно быть преобразованным рекурсивно
применяя эти правила, то приведение
законный (хотя и не отмечен). Теперь совершенно ясно, не так ли? : D
Другими словами, это лучшее, что я могу сделать, не зная подробностей о вашей проблеме.
Вероятная причина mystifcation приведения классов в том, что не только типы должны совпадать, но и загружаться одним и тем же загрузчиком классов.
Вы должны иметь возможность выгружать не только иерархия типов, но также и идентификатор загрузчика классов для каждого класса.
Подобные проблемы не редкость в средах в стиле сервера приложений, где код приложения и код инфраструктуры намеренно изолированы - например, если системные классы случайно включены в JAR приложения, которые вы может иметь две копии «одного и того же» класса в JVM, и жизнь становится запутанной
Приведение утверждает, что тип среды выполнения объекта совместим с заданным статическим типом, и, таким образом, позволяет вызывать методы этого типа для объекта.
Здесь obj - это объект типа Integer, но доступный только через ссылку на объект:
Object obj = new Integer(1);
Приведение позволяет вам снова обрабатывать его как Integer (или некоторый суперкласс Integer):
System.out.println(((Integer) obj).intValue());
ClassCastException occours когда указанный статический тип не соответствует типу среды выполнения объекта:
System.out.println(((Float) obj).intValue()); // runtime error
Вы можете найти тип среды выполнения любого объекта с помощью getClass () и различных методов класса:
System.out.println(obj.getClass()); // prints "class java.lang.Integer"
Другие полезные и авторитетные ссылки можно найти в Спецификации виртуальной машины Java, в частности §2.6.5, «Сужение ссылочных преобразований», и особенно в определении checkcast
инструкция.