I have an android app that not on Google play and I want it to get updates using APK on the server. This code is working and checks for updates by searching for APK on Firebase storage with greater version than the current build and ending it to download
private fun checkUpdates(){
val storage = FirebaseStorage.getInstance()
val storageRef = storage.reference
val rootRef = storageRef.root
rootRef.listAll().addOnSuccessListener { listResult ->
for (item in listResult.items) {
// item is a StorageReference for a file
val fileName = item.name
val version = fileName.substring(fileName.indexOf("app_v") + 5, fileName.indexOf(".apk"))
if (version.replace(".", "") > BuildConfig.VERSION_CODE.toString().replace(".", "")) {
val builder = AlertDialog.Builder(this)
builder.setMessage(R.string.new_up_av)
builder.setPositiveButton(R.string.install) { _, _ ->
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_WRITE_STORAGE
)
download(version)
} else {
download(version)
}
}
val dialog = builder.create()
dialog.show()
}
else{
Toast.makeText(this, R.string.no_updates, Toast.LENGTH_LONG).show()
}
}
} .addOnFailureListener{
Toast.makeText(this, "ERROR", Toast.LENGTH_SHORT).show()
}
}
The download
function is this (notice the comment on line 4):
private fun download(version: String) {
Toast.makeText(this, R.string.download_updates, Toast.LENGTH_SHORT).show()
val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val downloadUri = Uri.parse(//url for apk here.)
val request = DownloadManager.Request(downloadUri)
.setTitle(getString(R.string.download_updates))
.setDescription(getString(R.string.app_name))
val downloadId = downloadManager.enqueue(request)
// Check if the download was successful
if (downloadId == -1L) {
// Download failed, show an error message
Toast.makeText(this, "download failed", Toast.LENGTH_SHORT).show()
return
}
// Listen for the download to complete and install the update
val downloadReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
if (downloadId == id) {
installApk(context, "app_v$version.apk")
}
}
}
registerReceiver(downloadReceiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
}
on line 4 i verified it works manually and the problems is showing also with sure-working APKs like WhatsApp.
the installApk
function:
fun installApk(context: Context, fileName: String) {
val file = File(Environment.getExternalStorageDirectory().toString() + "/Download/" + filename)
val fileUri = FileProvider.getUriForFile(context, "${context.packageName}.provider", file)
val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(fileUri, "application/vnd.android.package-archive")
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
}
provider in Manifest
:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android: resource="@xml/provider_paths" />
</provider>
provider_paths.xml
:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="downloads" path="Download/" />
</paths>
The problem: seems like its downloading, starting to install, and than shows an error occurred while parsing the package
message. no logs.
(It works manually)
I have tried many other ways buts I couldn't figure what cussing the problem.
If someone fammiliar with intalling apk programmatically I looking for help.