mirror of
https://github.com/YTVanced/VancedManager
synced 2024-11-27 05:23:00 +00:00
Fix Bug With Install when youtube is not pre installed in system and added code check, and returns error message on install if there is one
This commit is contained in:
parent
042a6a72a1
commit
f2cb0e4307
2 changed files with 156 additions and 76 deletions
|
@ -10,6 +10,10 @@ import androidx.annotation.Nullable
|
|||
import androidx.annotation.WorkerThread
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import com.topjohnwu.superuser.io.SuFile
|
||||
import com.topjohnwu.superuser.io.SuFileInputStream
|
||||
import com.topjohnwu.superuser.io.SuFileOutputStream
|
||||
import com.vanced.manager.BuildConfig
|
||||
import com.vanced.manager.ui.fragments.HomeFragment
|
||||
import com.vanced.manager.utils.AppUtils.sendFailure
|
||||
import com.vanced.manager.utils.FileInfo
|
||||
|
@ -20,12 +24,14 @@ import kotlinx.coroutines.Dispatchers
|
|||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
|
||||
class RootSplitInstallerService: Service() {
|
||||
|
||||
private var vancedVersionCode: Int = 0
|
||||
|
@ -33,43 +39,55 @@ class RootSplitInstallerService: Service() {
|
|||
|
||||
private val localBroadcastManager by lazy { LocalBroadcastManager.getInstance(this) }
|
||||
|
||||
|
||||
suspend fun getVer()
|
||||
{
|
||||
vancedVersionCode = getJsonInt("vanced.json","versionCode", application)
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
logDebug("RunBlockBefore");
|
||||
|
||||
Shell.enableVerboseLogging = BuildConfig.DEBUG
|
||||
Shell.setDefaultBuilder(
|
||||
Shell.Builder.create()
|
||||
.setFlags(Shell.FLAG_REDIRECT_STDERR)
|
||||
.setTimeout(10)
|
||||
)
|
||||
|
||||
runBlocking { getVer() }
|
||||
logDebug("RunBlockAfter");
|
||||
Shell.getShell {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
var job = CoroutineScope(Dispatchers.IO).launch{
|
||||
val apkFilesPath = getExternalFilesDir("apks")?.path
|
||||
val fileInfoList = apkFilesPath?.let { it1 -> getFileInfoList(it1) }
|
||||
logDebug("GotFileInfoList")
|
||||
if (fileInfoList != null) {
|
||||
var modApk: FileInfo? = null
|
||||
logDebug("FileInfoListIsNotEmpty")
|
||||
for (fil in fileInfoList)
|
||||
{
|
||||
logDebug(fil.name)
|
||||
if(fil.name == "dark.apk" || fil.name == "black.apk")
|
||||
{
|
||||
logDebug("found " + fil.name)
|
||||
modApk = fil
|
||||
}
|
||||
}
|
||||
logDebug("Before modApk Check")
|
||||
if (modApk != null) {
|
||||
logDebug("modApkCheck Passed")
|
||||
overwriteBase(modApk, fileInfoList,vancedVersionCode)
|
||||
logDebug("Finished Patching")
|
||||
if(overwriteBase(modApk, fileInfoList,vancedVersionCode))
|
||||
{
|
||||
with(localBroadcastManager) {
|
||||
sendBroadcast(Intent(HomeFragment.REFRESH_HOME))
|
||||
sendBroadcast(Intent(HomeFragment.VANCED_INSTALLED))
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw IllegalArgumentException("modApk Is Null Cause Missing (dark.apk/black.apk) In apks Folder")
|
||||
sendFailure(listOf("Install Failed").toMutableList(), applicationContext)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sendFailure(listOf("modApk Is Null Missing (dark.apk/black.apk) In apks Folder").toMutableList(), applicationContext)
|
||||
}
|
||||
//installSplitApkFiles(fileInfoList)
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,12 +96,9 @@ class RootSplitInstallerService: Service() {
|
|||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
private fun logDebug(s: String) {
|
||||
Log.d("ZLog", s)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun installSplitApkFiles(apkFiles: ArrayList<FileInfo>) {
|
||||
private fun installSplitApkFiles(apkFiles: ArrayList<FileInfo>) : Boolean {
|
||||
var sessionId: Int?
|
||||
Log.d("AppLog", "installing split apk files:$apkFiles")
|
||||
run {
|
||||
|
@ -116,12 +131,10 @@ class RootSplitInstallerService: Service() {
|
|||
Log.d("AppLog", "committing...")
|
||||
val installResult = Shell.su("pm install-commit $sessionId").exec()
|
||||
if (installResult.isSuccess) {
|
||||
with(localBroadcastManager) {
|
||||
sendBroadcast(Intent(HomeFragment.REFRESH_HOME))
|
||||
sendBroadcast(Intent(HomeFragment.VANCED_INSTALLED))
|
||||
}
|
||||
return true
|
||||
} else
|
||||
sendFailure(installResult.out, this)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun SimpleDateFormat.tryParse(str: String) = try {
|
||||
|
@ -176,60 +189,63 @@ class RootSplitInstallerService: Service() {
|
|||
|
||||
|
||||
|
||||
private fun overwriteBase(apkFile: FileInfo, baseApkFiles: ArrayList<FileInfo>, versionCode: Int)
|
||||
private fun overwriteBase(apkFile: FileInfo, baseApkFiles: ArrayList<FileInfo>, versionCode: Int): Boolean
|
||||
{
|
||||
if(checkVersion(versionCode,baseApkFiles))
|
||||
{
|
||||
logDebug("check version")
|
||||
checkVersion(versionCode,baseApkFiles)
|
||||
logDebug("Version Check Done, next getting apk path")
|
||||
var path = getVPath()
|
||||
logDebug("Path: $path")
|
||||
apkFile.file?.let {
|
||||
var apath = it.absolutePath
|
||||
logDebug("Moving $apath to: $path")
|
||||
moveAPK(apath, path)
|
||||
logDebug("Move done setting chConv $path")
|
||||
chConV(path)
|
||||
logDebug("Done with chConv $path")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun checkVersion(versionCode: Int, baseApkFiles: ArrayList<FileInfo>) {
|
||||
val path = getVPath()
|
||||
logDebug("checking if path is in /data/app")
|
||||
apkFile.file?.let {
|
||||
val apath = it.absolutePath
|
||||
if(path?.let { it1 -> moveAPK(apath, it1) }!!)
|
||||
{
|
||||
return chConV(path)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun checkVersion(versionCode: Int, baseApkFiles: ArrayList<FileInfo>): Boolean {
|
||||
val path = getVPath()
|
||||
if (path != null) {
|
||||
if(path.contains("/data/app/"))
|
||||
{
|
||||
logDebug("Path is in /data/app: $path" )
|
||||
when(compareVersion(getPkgVerCode(yPkg),versionCode))
|
||||
when(getPkgVerCode(yPkg)?.let { compareVersion(it,versionCode) })
|
||||
{
|
||||
1 -> {fixHigherVer(baseApkFiles);logDebug("higher version uninstalling then installing base + patched");}
|
||||
-1 -> {fixLowerVer(baseApkFiles);logDebug("Lower Version installing base + patched");}
|
||||
1 -> {return fixHigherVer(baseApkFiles) }
|
||||
-1 -> {return fixLowerVer(baseApkFiles) }
|
||||
}
|
||||
return true
|
||||
}
|
||||
else
|
||||
{
|
||||
logDebug("No install in /data/app/ now installing")
|
||||
fixNoInstall(baseApkFiles)
|
||||
return fixNoInstall(baseApkFiles)
|
||||
}
|
||||
}
|
||||
return fixNoInstall(baseApkFiles)
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun getPkgVerCode(pkg: String): Int {
|
||||
private fun getPkgVerCode(pkg: String): Int? {
|
||||
val pm = packageManager
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
|
||||
pm.getPackageInfo(pkg, 0).longVersionCode.and(0xFFFFFFFF).toInt()
|
||||
pm.getPackageInfo(pkg, 0)?.longVersionCode?.and(0xFFFFFFFF)?.toInt()
|
||||
else
|
||||
pm.getPackageInfo(pkg, 0).versionCode
|
||||
pm.getPackageInfo(pkg, 0)?.versionCode
|
||||
|
||||
}
|
||||
|
||||
private fun getPkgInfo(pkg: String): PackageInfo
|
||||
private fun getPkgInfo(pkg: String): PackageInfo?
|
||||
{
|
||||
return try {
|
||||
val m = packageManager
|
||||
val p: PackageInfo = m.getPackageInfo(pkg, 0)
|
||||
return p
|
||||
val info = m.getPackageInfo(pkg, 0)
|
||||
info
|
||||
} catch (e:Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun compareVersion(pkgVerCode: Int, versionCode: Int): Int
|
||||
|
@ -242,33 +258,88 @@ class RootSplitInstallerService: Service() {
|
|||
0
|
||||
}
|
||||
|
||||
private fun fixHigherVer(apkFiles: ArrayList<FileInfo>) {
|
||||
private fun fixHigherVer(apkFiles: ArrayList<FileInfo>) : Boolean {
|
||||
|
||||
PackageHelper.uninstallApk(yPkg, applicationContext)
|
||||
installSplitApkFiles(apkFiles)
|
||||
if(PackageHelper.uninstallApk(yPkg, applicationContext))
|
||||
{
|
||||
return installSplitApkFiles(apkFiles)
|
||||
}
|
||||
with(localBroadcastManager) {sendFailure(listOf("Failed Uninstall Of Installed Version, Try Manually").toMutableList(), applicationContext)}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun fixLowerVer(apkFiles: ArrayList<FileInfo>) {
|
||||
installSplitApkFiles(apkFiles)
|
||||
private fun fixLowerVer(apkFiles: ArrayList<FileInfo>): Boolean {
|
||||
return installSplitApkFiles(apkFiles)
|
||||
}
|
||||
|
||||
private fun fixNoInstall(baseApkFiles: ArrayList<FileInfo>) {
|
||||
installSplitApkFiles(baseApkFiles)
|
||||
private fun fixNoInstall(baseApkFiles: ArrayList<FileInfo>): Boolean {
|
||||
return installSplitApkFiles(baseApkFiles)
|
||||
}
|
||||
|
||||
private fun chConV(path: String) {
|
||||
Shell.su("chcon -R u:object_r:system_file:s0 $path").exec()
|
||||
private fun chConV(path: String): Boolean {
|
||||
val response = Shell.su("chcon -R u:object_r:system_file:s0 $path").exec()
|
||||
return if(response.isSuccess) {
|
||||
true
|
||||
} else {
|
||||
sendFailure(response.out, applicationContext)
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun moveAPK(apkFile: String, path: String) {
|
||||
Shell.su("cp $apkFile $path").exec()
|
||||
Shell.su("chmod 644 $path").exec()
|
||||
private fun moveAPK(apkFile: String, path: String) : Boolean {
|
||||
|
||||
val apkinF = SuFile.open(apkFile)
|
||||
val apkoutF = SuFile.open(path)
|
||||
|
||||
if(apkinF.exists())
|
||||
{
|
||||
try {
|
||||
copy(apkinF,apkoutF)
|
||||
}
|
||||
catch (e: IOException)
|
||||
{
|
||||
sendFailure(listOf("${e.message}").toMutableList(), applicationContext)
|
||||
}
|
||||
}
|
||||
else {
|
||||
sendFailure(listOf("Input File Missing").toMutableList(), applicationContext)
|
||||
return false
|
||||
}
|
||||
|
||||
val resultmv = Shell.su("mv $apkFile $path").exec().isSuccess
|
||||
return if(resultmv) {
|
||||
Shell.su("chmod 644 $path").exec().isSuccess
|
||||
} else {
|
||||
sendFailure(listOf("Failed To Apply Mod").toMutableList(), applicationContext)
|
||||
false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun getVPath(): String {
|
||||
@Throws(IOException::class)
|
||||
fun copy(src: File?, dst: File?) {
|
||||
val finputStrem: InputStream = SuFileInputStream(src)
|
||||
finputStrem.use { finputStrem ->
|
||||
val out: OutputStream = SuFileOutputStream(dst)
|
||||
out.use { out ->
|
||||
// Transfer bytes from in to out
|
||||
val buf = ByteArray(1024)
|
||||
var len: Int
|
||||
while (finputStrem.read(buf).also { len = it } > 0) {
|
||||
out.write(buf, 0, len)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private fun getVPath(): String? {
|
||||
return try {
|
||||
val p = getPkgInfo(yPkg)
|
||||
return p.applicationInfo.sourceDir
|
||||
p?.applicationInfo?.sourceDir
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -6,6 +6,7 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import com.vanced.manager.core.installer.AppUninstallerService
|
||||
import java.lang.Exception
|
||||
|
||||
object PackageHelper {
|
||||
|
||||
|
@ -32,10 +33,18 @@ object PackageHelper {
|
|||
activity.packageManager.packageInstaller.uninstall(pkg, pendingIntent.intentSender)
|
||||
}
|
||||
|
||||
fun uninstallApk(pkg: String, applicationContext: Context) {
|
||||
fun uninstallApk(pkg: String, applicationContext: Context): Boolean {
|
||||
val callbackIntent = Intent(applicationContext, AppUninstallerService::class.java)
|
||||
callbackIntent.putExtra("pkg", pkg)
|
||||
val pendingIntent = PendingIntent.getService(applicationContext, 0, callbackIntent, 0)
|
||||
try {
|
||||
applicationContext.packageManager.packageInstaller.uninstall(pkg, pendingIntent.intentSender)
|
||||
return true
|
||||
}
|
||||
catch (e: Exception)
|
||||
{
|
||||
e.printStackTrace()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue