mirror of https://github.com/termux/termux-app
* Changed the download directory to /com.termux/cache/pkg/.
* Improved notification management. * Implemented downloading from the Google Play Store.
This commit is contained in:
parent
f6c3b6f38a
commit
8d83a39a85
|
@ -4,7 +4,6 @@ import android.app.NotificationManager
|
|||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.StatFs
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.termux.R
|
||||
import com.termux.app.PackageInstaller.Companion.log
|
||||
|
@ -15,10 +14,7 @@ import kotlinx.coroutines.launch
|
|||
import java.io.File
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.FileOutputStream
|
||||
import java.net.ConnectException
|
||||
import java.net.URL
|
||||
import java.net.URLConnection
|
||||
import java.net.UnknownHostException
|
||||
import java.net.*
|
||||
|
||||
|
||||
// Download status constants
|
||||
|
@ -70,6 +66,11 @@ class PackageDownloader(val context: Context) {
|
|||
notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
builder = NotificationCompat.Builder(context, "termux_notification_channel").setChannelId(NOTIFICATION_CHANNEL_ID)
|
||||
|
||||
File(TERMUX_CACHE_PKG_DIRECTORY).let {
|
||||
if (!it.exists()) {
|
||||
it.mkdir()
|
||||
}
|
||||
}
|
||||
|
||||
var isStartNotified = false
|
||||
|
||||
|
@ -78,15 +79,15 @@ class PackageDownloader(val context: Context) {
|
|||
var percent60 = false
|
||||
var percent80 = false
|
||||
|
||||
//val fileUrl = "https://termux.net/apks/$packageName.apk"
|
||||
// val fileUrl = "https://termux.net/apks/$packageName.apk"
|
||||
val fileUrl = "https://staging.termux-mirror.ml/android-10/$packageName.apk"
|
||||
"URL -> $fileUrl".log()
|
||||
try {
|
||||
downloadingJob = GlobalScope.launch(Dispatchers.IO) {
|
||||
val downloadData = DownloadData(packageName, 0, 0, 0, ENTERED)
|
||||
try {
|
||||
val downloadData = DownloadData(packageName, 0, 0, 0, ENTERED)
|
||||
showNotification(downloadData)
|
||||
val downloadFile = File("${TermuxService.FILES_PATH}/${packageName}.apk")
|
||||
val downloadFile = File("${TERMUX_CACHE_PKG_DIRECTORY}/${packageName}.apk")
|
||||
deleteFileIfExists(downloadFile)
|
||||
"Fetching the file size...".log()
|
||||
val url = URL(fileUrl)
|
||||
|
@ -122,23 +123,20 @@ class PackageDownloader(val context: Context) {
|
|||
downloadData.progressPercent = percent
|
||||
progressListener.onProgress(downloadData)
|
||||
}
|
||||
updateNotification(downloadData)
|
||||
if (percent % 20 == 0 && total != lengthOfFile) {
|
||||
// Can be simplified
|
||||
percent.let {
|
||||
if (it == 20 && !percent20) {
|
||||
updateNotification(downloadData)
|
||||
percent20 = true
|
||||
updateProgress(it)
|
||||
} else if (it == 40 && !percent40) {
|
||||
updateNotification(downloadData)
|
||||
percent40 = true
|
||||
updateProgress(it)
|
||||
} else if (it == 60 && !percent60) {
|
||||
updateNotification(downloadData)
|
||||
percent60 = true
|
||||
updateProgress(it)
|
||||
} else if (it == 80 && !percent80) {
|
||||
updateNotification(downloadData)
|
||||
percent80 = true
|
||||
updateProgress(it)
|
||||
}
|
||||
|
@ -159,54 +157,43 @@ class PackageDownloader(val context: Context) {
|
|||
}
|
||||
|
||||
} catch (e: FileNotFoundException) {
|
||||
packageName.clearThingsUp()
|
||||
errorListener.onError(ErrorData(packageName = packageName, Status = ERROR, error = "Package $packageName does not exists!"))
|
||||
val errorData = ErrorData(packageName = packageName, Status = ERROR, error = "Package $packageName does not exists!", notificationID = downloadData.notificationID)
|
||||
packageName.clearThingsUp(errorData)
|
||||
errorListener.onError(errorData)
|
||||
} catch (e: UnknownHostException) {
|
||||
packageName.clearThingsUp()
|
||||
errorListener.onError(ErrorData(packageName = packageName, Status = ERROR, error = "Cannot connect to internet or server unavailable. Aborting the installation."))
|
||||
val errorData = ErrorData(packageName = packageName, Status = ERROR, error = "Cannot connect to internet or server unavailable. Aborting the installation.", notificationID = downloadData.notificationID)
|
||||
packageName.clearThingsUp(errorData)
|
||||
errorListener.onError(errorData)
|
||||
} catch (e: SocketException) {
|
||||
val errorData = ErrorData(packageName = packageName, Status = ERROR, error = "Cannot connect to internet or server unavailable. Aborting the installation.", notificationID = downloadData.notificationID)
|
||||
packageName.clearThingsUp(errorData)
|
||||
errorListener.onError(errorData)
|
||||
} catch (e: ConnectException) {
|
||||
packageName.clearThingsUp()
|
||||
errorListener.onError(ErrorData(packageName = packageName, Status = ERROR, error = "Cannot connect to internet or server unavailable. Aborting the installation."))
|
||||
val errorData = ErrorData(packageName = packageName, Status = ERROR, error = "Cannot connect to internet or server unavailable. Aborting the installation.", notificationID = downloadData.notificationID)
|
||||
packageName.clearThingsUp(errorData)
|
||||
errorListener.onError(errorData)
|
||||
} catch (e: InsufficientStorageException) {
|
||||
packageName.clearThingsUp()
|
||||
errorListener.onError(ErrorData(packageName = packageName, Status = ERROR, error = "Insufficient Storage. Please clear some data before installing."))
|
||||
val errorData = ErrorData(packageName = packageName, Status = ERROR, error = "Insufficient Storage. Please clear some data before installing.", notificationID = downloadData.notificationID)
|
||||
errorListener.onError(ErrorData(packageName = packageName, Status = ERROR, error = ""))
|
||||
packageName.clearThingsUp(errorData)
|
||||
errorListener.onError(errorData)
|
||||
} catch (e: Exception) {
|
||||
packageName.clearThingsUp()
|
||||
Log.e("termux", "Error installing $packageName", e)
|
||||
if (this@PackageDownloader::downloadingJob.isInitialized) {
|
||||
if (downloadingJob.isActive) {
|
||||
downloadingJob.cancel()
|
||||
}
|
||||
}
|
||||
errorListener.onError(ErrorData(packageName = packageName, Status = ERROR, error = e.toString()))
|
||||
"Error installing $packageName $e".log()
|
||||
val errorData = ErrorData(packageName = packageName, Status = ERROR, error = e.toString(), notificationID = downloadData.notificationID)
|
||||
packageName.clearThingsUp(errorData)
|
||||
errorListener.onError(errorData)
|
||||
}
|
||||
}
|
||||
|
||||
} catch (e: FileNotFoundException) {
|
||||
packageName.clearThingsUp()
|
||||
errorListener.onError(ErrorData(packageName = packageName, Status = ERROR, error = "Package $packageName does not exists!"))
|
||||
} catch (e: ConnectException) {
|
||||
packageName.clearThingsUp()
|
||||
errorListener.onError(ErrorData(packageName = packageName, Status = ERROR, error = "Cannot connect to internet or server unavailable. Aborting the installation."))
|
||||
|
||||
} catch (e: UnknownHostException) {
|
||||
packageName.clearThingsUp()
|
||||
errorListener.onError(ErrorData(packageName = packageName, Status = ERROR, error = "Cannot connect to internet. Aborting the installation."))
|
||||
} catch (e: InsufficientStorageException) {
|
||||
packageName.clearThingsUp()
|
||||
errorListener.onError(ErrorData(packageName = packageName, Status = ERROR, error = "Insufficient Storage. Please clear some data before installing."))
|
||||
} catch (e: Exception) {
|
||||
packageName.clearThingsUp()
|
||||
Log.e("termux", "Error installing $packageName", e)
|
||||
if (this::downloadingJob.isInitialized) {
|
||||
if (downloadingJob.isActive) {
|
||||
downloadingJob.cancel()
|
||||
}
|
||||
}
|
||||
errorListener.onError(ErrorData(packageName = packageName, Status = ERROR, error = e.toString()))
|
||||
"Error installing $packageName $e".log()
|
||||
val errorData = ErrorData(packageName = packageName, Status = ERROR, error = e.toString())
|
||||
packageName.clearThingsUp(errorData)
|
||||
errorListener.onError(errorData)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun getFreeSpace(): Long {
|
||||
val path = context.dataDir
|
||||
val stat = StatFs(path.path)
|
||||
|
@ -228,10 +215,17 @@ class PackageDownloader(val context: Context) {
|
|||
return (this * 0.001).toLong()
|
||||
}
|
||||
|
||||
private fun String.clearThingsUp() {
|
||||
val downloadFile = File("${TermuxService.FILES_PATH}/${this}.apk")
|
||||
private fun String.clearThingsUp(errorData: ErrorData) {
|
||||
if (this@PackageDownloader::downloadingJob.isInitialized) {
|
||||
if (downloadingJob.isActive) {
|
||||
downloadingJob.cancel()
|
||||
}
|
||||
}
|
||||
val downloadFile = File("${TERMUX_CACHE_PKG_DIRECTORY}/${this}.apk")
|
||||
deleteFileIfExists(downloadFile)
|
||||
notificationManager.cancelAll()
|
||||
if (errorData.notificationID != 0) {
|
||||
notificationManager.cancel(errorData.notificationID)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -294,4 +288,4 @@ data class DownloadData(
|
|||
)
|
||||
|
||||
class InsufficientStorageException(message: String) : Exception(message)
|
||||
data class ErrorData(var packageName: String, var error: String, var extraLogs: String = "", var Status: Int)
|
||||
data class ErrorData(var packageName: String, var error: String, var extraLogs: String = "", var Status: Int, var notificationID: Int = 0)
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
package com.termux.app
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.*
|
||||
import android.content.pm.PackageInstaller
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
|
@ -20,6 +17,7 @@ import java.io.IOException
|
|||
import java.io.OutputStream
|
||||
|
||||
const val PACKAGE_INSTALLED_ACTION = "com.termux.SESSION_API_PACKAGE_INSTALLED"
|
||||
const val TERMUX_CACHE_PKG_DIRECTORY = "/data/data/com.termux/cache/pkg"
|
||||
|
||||
class PackageInstaller(val context: Context) : PackageDownloader.ErrorListener, PackageDownloader.ProgressListener, PackageDownloader.StartListener, PackageDownloader.CompleteListener {
|
||||
|
||||
|
@ -140,7 +138,7 @@ class PackageInstaller(val context: Context) : PackageDownloader.ErrorListener,
|
|||
|
||||
private fun addApkToInstallSession(session: PackageInstaller.Session,
|
||||
packageName: String) {
|
||||
val file = File("${TermuxService.FILES_PATH}/$packageName.apk")
|
||||
val file = File("${TERMUX_CACHE_PKG_DIRECTORY}/$packageName.apk")
|
||||
val packageInSession: OutputStream = session.openWrite(packageName, 0, -1)
|
||||
val inputStream = FileInputStream(file)
|
||||
try {
|
||||
|
@ -225,7 +223,7 @@ class PackageInstaller(val context: Context) : PackageDownloader.ErrorListener,
|
|||
downloadHashMap.forEach { (packageName) ->
|
||||
//Setting up a default response
|
||||
installationResponseHashMap[packageName] = "the request package was either not downloaded or just doesn't exist!"
|
||||
val apkFileToBeInstalled = File("${TermuxService.FILES_PATH}/$packageName.apk")
|
||||
val apkFileToBeInstalled = File("${TERMUX_CACHE_PKG_DIRECTORY}/$packageName.apk")
|
||||
if (apkFileToBeInstalled.exists()) {
|
||||
packagesToInstall.add(packageName)
|
||||
}
|
||||
|
@ -269,8 +267,24 @@ class PackageInstaller(val context: Context) : PackageDownloader.ErrorListener,
|
|||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------- Play Store Download -----------------------------------------*/
|
||||
|
||||
fun downloadFromPlayStore(packageList: Array<String>) {
|
||||
|
||||
/*Opening multiple package links at once in Google Play will be anything but user-friendly. There's no way to prevent this but to just start a transparent
|
||||
* activity and monitor the lifecycle, but that's not a great idea in itself. */
|
||||
|
||||
fun openStoreLink(packageName: String) {
|
||||
try {
|
||||
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=net.termux.$packageName")).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=net.termux.$packageName")).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
|
||||
}
|
||||
}
|
||||
packageList.forEachIndexed { _, packageName ->
|
||||
openStoreLink(packageName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
data class LocalDownloadData(var packageName: String, var isDownloaded: Boolean?, var extraLogs: String = "")
|
||||
|
|
|
@ -130,11 +130,18 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
|||
stopSelf();
|
||||
} else if (ACTION_INSTALL_PACKAGES.equals(action)) {
|
||||
String[] packages = intent.getStringArrayExtra("packages");
|
||||
System.out.println(intent.getExtras());
|
||||
String source = intent.getStringExtra("source");
|
||||
System.out.println("Source " + source);
|
||||
if (packages == null || packages.length == 0) {
|
||||
Log.e(EmulatorDebug.LOG_TAG, ACTION_INSTALL_PACKAGES + " called without packages");
|
||||
} else {
|
||||
PackageInstaller downloaderTest = new PackageInstaller(this);
|
||||
downloaderTest.initDownloader(packages);
|
||||
PackageInstaller packageInstaller = new PackageInstaller(this);
|
||||
if (source == null || source.isEmpty()) {
|
||||
packageInstaller.initDownloader(packages);
|
||||
} else {
|
||||
packageInstaller.downloadFromPlayStore(packages);
|
||||
}
|
||||
}
|
||||
} else if (ACTION_LIST_PACKAGES.equals(action)) {
|
||||
PackageLister packageLister = new PackageLister(this);
|
||||
|
|
Loading…
Reference in New Issue