more fixes for apk packages

pull/1112/head
deniscerri 7 months ago
parent 61b6a6f4ce
commit df63aa6ecb
No known key found for this signature in database
GPG Key ID: 95C43D517D830350

@ -6,7 +6,7 @@ object Aria2c : PackageBase() {
override val bundledZipName: String get() = "libaria2c.zip.so"
override val canUninstall: Boolean = false
override val bundledVersion: String get() = "v1.37.0"
override val githubRepo: String get() = "deniscerri/ytdlnis-plugins"
override val githubRepo: String get() = "deniscerri/ytdlnis-packages"
override val githubPackageName: String get() = "aria2c"
override val apkPackage: String get() = "com.deniscerri.ytdl.aria2c"
}

@ -6,7 +6,7 @@ object FFmpeg : PackageBase() {
override val bundledZipName: String get() = "libffmpeg.zip.so"
override val canUninstall: Boolean = false
override val bundledVersion: String get() = "v7.0.1"
override val githubRepo: String get() = "deniscerri/ytdlnis-plugins"
override val githubRepo: String get() = "deniscerri/ytdlnis-packages"
override val githubPackageName: String get() = "ffmpeg"
override val apkPackage: String get() = "com.deniscerri.ytdl.ffmpeg"
}

@ -6,7 +6,7 @@ object NodeJS : PackageBase() {
override val bundledZipName: String get() = "libnode.zip.so"
override val canUninstall: Boolean = true
override val bundledVersion: String get() = ""
override val githubRepo: String get() = "deniscerri/ytdlnis-plugins"
override val githubRepo: String get() = "deniscerri/ytdlnis-packages"
override val githubPackageName: String get() = "nodejs"
override val apkPackage: String get() = "com.deniscerri.ytdl.nodejs"
}

@ -143,33 +143,37 @@ abstract class PackageBase {
}
fun getLocation(context: Context, baseDir: File): PackageLocation {
val mainNativeDir = context.applicationInfo.nativeLibraryDir
//downloaded apk location
var packageBinDir: String? = null
if (apkPackage.isNotBlank()) {
try {
packageBinDir = context.packageManager.getApplicationInfo(apkPackage, 0).nativeLibraryDir
} catch (e: Exception) {}
}
val downloadedBinDir = File(packageBinDir ?: "")
val downloadedLDDir = getDownloadedDir(context)
val downloadedExe = File(packageBinDir, "lib$executableName.so")
//bundled location
val bundledBinDir = File(context.applicationInfo.nativeLibraryDir)
val bundledLDDir = File(File(baseDir, packagesRoot), packageFolderName)
val bundledExe = File(bundledBinDir, "lib$executableName.so")
val packageExe = if (packageBinDir != null) File(packageBinDir, "lib$executableName.so") else null
val isPackageActive = packageExe?.exists() == true
var isBundleActive = false
val isPackageActive = downloadedExe.exists()
val isBundleActive = bundledExe.exists()
val finalExe: File
val binDir: File
val ldDir: File
if (isPackageActive) {
finalExe = packageExe
binDir = File(packageBinDir!!)
ldDir = getDownloadedDir(context)
finalExe = downloadedExe
binDir = downloadedBinDir
ldDir = downloadedLDDir
} else {
val bundledDir = File(baseDir, packagesRoot)
binDir = File(context.applicationInfo.nativeLibraryDir)
ldDir = File(bundledDir, packageFolderName)
finalExe = File(binDir, "lib$executableName.so")
isBundleActive = finalExe.exists()
finalExe = bundledExe
binDir = bundledBinDir
ldDir = bundledLDDir
}
return PackageLocation(
@ -183,10 +187,10 @@ abstract class PackageBase {
)
}
suspend fun downloadRelease(context: Context, release: PackageRelease, onProgress: (Int) -> Unit) : Result<DocumentFile> {
suspend fun downloadReleaseApk(context: Context, release: PackageRelease, onProgress: (Int) -> Unit) : Result<DocumentFile> {
return withContext(Dispatchers.IO) {
try {
val tempZipFile = File(context.cacheDir, "${packageFolderName}_tmp.zip")
val tempApk = File(context.cacheDir, "${packageFolderName}_${release.version.replace(".", "")}.apk")
//download
val request = Request.Builder()
@ -203,7 +207,7 @@ abstract class PackageBase {
var bytesDownloaded = 0L
body.byteStream().use { inputStream ->
tempZipFile.outputStream().use { outputStream ->
tempApk.outputStream().use { outputStream ->
val buffer = ByteArray(8192) // 8KB buffer
var bytesRead: Int
@ -220,47 +224,13 @@ abstract class PackageBase {
}
}
Result.success(DocumentFile.fromFile(tempZipFile))
Result.success(DocumentFile.fromFile(tempApk))
} catch (e: Exception) {
Result.failure(e)
}
}
}
fun installFromZip(context: Context, zipFile: DocumentFile, versionTag: String? = null) : Result<String> {
return kotlin.runCatching {
val runtimeDir = getDownloadedDir(context)
FileUtils.deleteQuietly(runtimeDir)
runtimeDir.mkdirs()
// 3. Unzip the main Bundle (contains libnode.so and libnode.zip.so)
context.contentResolver.openInputStream(zipFile.uri).use { inputStream ->
ZipUtils.unzip(inputStream, runtimeDir)
}
// 4. Handle the Bootstrap Zip (Double Unzip)
// Look for any .zip.so file in the extracted directory
runtimeDir.listFiles()?.forEach { file ->
if (file.name.endsWith(".zip.so")) {
ZipUtils.unzip(file, runtimeDir)
file.delete() // Remove the internal zip to save space
}
}
applyExecutablePermissions(runtimeDir)
// 6. Save installation state
val version = versionTag ?: "IMPORTED"
saveState(context, version)
if (versionTag != null) {
zipFile.delete()
}
Result.success(version)
}.getOrElse {
Result.failure(it)
}
}
fun uninstallDownloadedRuntimeDir(context: Context): Result<Unit> {
return kotlin.runCatching {
val runtimeDir = getDownloadedDir(context)

@ -4,9 +4,9 @@ object Python : PackageBase() {
override val executableName: String get() = "python"
override val packageFolderName: String get() = "python"
override val bundledZipName: String get() = "libpython.zip.so"
override val bundledVersion: String get() = "v3.12"
override val bundledVersion: String get() = "v3.12.11"
override val canUninstall: Boolean = false
override val githubRepo: String get() = "deniscerri/ytdlnis-plugins"
override val githubRepo: String get() = "deniscerri/ytdlnis-packages"
override val githubPackageName: String get() = "python"
override val apkPackage: String get() = "com.deniscerri.ytdl.python"
}

@ -105,17 +105,6 @@ class PackagesFragment : Fragment(), PackagesAdapter.OnItemClickListener, Packag
sheet.setContentView(R.layout.plugin_releases_bottom_sheet)
sheet.findViewById<TextView>(R.id.bottom_sheet_subtitle)?.text = item.title
sheet.findViewById<Button>(R.id.bottomsheet_import_zip)?.setOnClickListener {
sheet.dismiss()
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "application/zip"
}
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
importPluginZipLauncher.launch(intent)
}
val loader = sheet.findViewById<CircularProgressIndicator>(R.id.loader)
val noResults = sheet.findViewById<View>(R.id.no_results)
@ -161,33 +150,7 @@ class PackagesFragment : Fragment(), PackagesAdapter.OnItemClickListener, Packag
bottomSheet = sheet
}
private var importPluginZipLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
result.data?.data?.let {
activity?.contentResolver?.takePersistableUriPermission(
it,
Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
tmpItem?.let { item ->
DocumentFile.fromSingleUri(requireContext(), it)?.apply {
val instance = item.getInstance()
val result = instance.installFromZip(requireContext(), this)
if (result.isSuccess) {
bottomSheet?.dismiss()
listAdapter.notifyDataSetChanged()
RuntimeManager.reInit(requireContext())
}
}
}
}
}
}
val uninstallLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
private var uninstallLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (tmpInstance?.isPackageAppInstalled(requireContext()) == false) {
val resp = tmpInstance?.uninstallDownloadedRuntimeDir(requireContext())
resp?.onFailure {
@ -216,7 +179,9 @@ class PackagesFragment : Fragment(), PackagesAdapter.OnItemClickListener, Packag
) {
val instance = item.getInstance()
tmpInstance = instance
val intent = Intent(Intent.ACTION_DELETE, "package:${instance.apkPackage}".toUri())
val intent = Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
data = Uri.parse("package:${instance.apkPackage}")
}
uninstallLauncher.launch(intent)
}
}
@ -252,7 +217,7 @@ class PackagesFragment : Fragment(), PackagesAdapter.OnItemClickListener, Packag
tmpDownloadJob = lifecycleScope.launch {
val instance = tmpItem!!.getInstance()
val fileResp = instance.downloadRelease(requireContext(), item) { progress ->
val fileResp = instance.downloadReleaseApk(requireContext(), item) { progress ->
lifecycleScope.launch {
withContext(Dispatchers.Main) {
positiveButton.text = "$progress%"
@ -269,26 +234,10 @@ class PackagesFragment : Fragment(), PackagesAdapter.OnItemClickListener, Packag
}
}
fileResp.onSuccess { file ->
val resp = instance.installFromZip(requireContext(), file, "v${item.version}")
resp.onFailure {
lifecycleScope.launch {
withContext(Dispatchers.Main) {
bottomSheet?.dismiss()
view.dismiss()
Snackbar.make(requireView(), it.message ?: getString(R.string.errored), Snackbar.LENGTH_LONG).show()
}
}
}
resp.onSuccess {
lifecycleScope.launch {
withContext(Dispatchers.Main) {
bottomSheet?.dismiss()
view.dismiss()
listAdapter.notifyDataSetChanged()
RuntimeManager.reInit(requireContext())
}
}
}
val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(file.uri, "application/vnd.android.package-archive");
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
}
}

@ -30,7 +30,7 @@
android:singleLine="false"
android:textSize="20sp"
android:text="@string/packages"
app:layout_constraintEnd_toStartOf="@+id/bottomsheet_import_zip"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@ -42,26 +42,11 @@
android:textSize="12sp"
android:textStyle="bold"
tools:text="Python"
app:layout_constraintEnd_toStartOf="@+id/bottomsheet_import_zip"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/bottom_sheet_title" />
<Button
android:id="@+id/bottomsheet_import_zip"
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:autoLink="all"
android:outlineProvider="none"
android:stateListAnimator="@null"
android:text="@string/import_zip"
app:icon="@drawable/baseline_folder_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView

@ -512,6 +512,5 @@
<string name="sponsorblock_hook">Hook/Greetings</string>
<string name="packages">Packages</string>
<string name="not_installed">Not installed</string>
<string name="import_zip">Import ZIP</string>
<string name="bundled">Bundled</string>
</resources>

Loading…
Cancel
Save