mirror of
https://github.com/YTVanced/VancedManager
synced 2024-11-30 15:03:02 +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.annotation.WorkerThread
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||||
import com.topjohnwu.superuser.Shell
|
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.ui.fragments.HomeFragment
|
||||||
import com.vanced.manager.utils.AppUtils.sendFailure
|
import com.vanced.manager.utils.AppUtils.sendFailure
|
||||||
import com.vanced.manager.utils.FileInfo
|
import com.vanced.manager.utils.FileInfo
|
||||||
|
@ -20,12 +24,14 @@ import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.io.OutputStream
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
|
|
||||||
class RootSplitInstallerService: Service() {
|
class RootSplitInstallerService: Service() {
|
||||||
|
|
||||||
private var vancedVersionCode: Int = 0
|
private var vancedVersionCode: Int = 0
|
||||||
|
@ -33,43 +39,55 @@ class RootSplitInstallerService: Service() {
|
||||||
|
|
||||||
private val localBroadcastManager by lazy { LocalBroadcastManager.getInstance(this) }
|
private val localBroadcastManager by lazy { LocalBroadcastManager.getInstance(this) }
|
||||||
|
|
||||||
|
|
||||||
suspend fun getVer()
|
suspend fun getVer()
|
||||||
{
|
{
|
||||||
vancedVersionCode = getJsonInt("vanced.json","versionCode", application)
|
vancedVersionCode = getJsonInt("vanced.json","versionCode", application)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
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() }
|
runBlocking { getVer() }
|
||||||
logDebug("RunBlockAfter");
|
|
||||||
Shell.getShell {
|
Shell.getShell {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
var job = CoroutineScope(Dispatchers.IO).launch{
|
||||||
val apkFilesPath = getExternalFilesDir("apks")?.path
|
val apkFilesPath = getExternalFilesDir("apks")?.path
|
||||||
val fileInfoList = apkFilesPath?.let { it1 -> getFileInfoList(it1) }
|
val fileInfoList = apkFilesPath?.let { it1 -> getFileInfoList(it1) }
|
||||||
logDebug("GotFileInfoList")
|
|
||||||
if (fileInfoList != null) {
|
if (fileInfoList != null) {
|
||||||
var modApk: FileInfo? = null
|
var modApk: FileInfo? = null
|
||||||
logDebug("FileInfoListIsNotEmpty")
|
|
||||||
for (fil in fileInfoList)
|
for (fil in fileInfoList)
|
||||||
{
|
{
|
||||||
logDebug(fil.name)
|
|
||||||
if(fil.name == "dark.apk" || fil.name == "black.apk")
|
if(fil.name == "dark.apk" || fil.name == "black.apk")
|
||||||
{
|
{
|
||||||
logDebug("found " + fil.name)
|
|
||||||
modApk = fil
|
modApk = fil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logDebug("Before modApk Check")
|
|
||||||
if (modApk != null) {
|
if (modApk != null) {
|
||||||
logDebug("modApkCheck Passed")
|
if(overwriteBase(modApk, fileInfoList,vancedVersionCode))
|
||||||
overwriteBase(modApk, fileInfoList,vancedVersionCode)
|
{
|
||||||
logDebug("Finished Patching")
|
with(localBroadcastManager) {
|
||||||
|
sendBroadcast(Intent(HomeFragment.REFRESH_HOME))
|
||||||
|
sendBroadcast(Intent(HomeFragment.VANCED_INSTALLED))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
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)
|
//installSplitApkFiles(fileInfoList)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,12 +96,9 @@ class RootSplitInstallerService: Service() {
|
||||||
return START_NOT_STICKY
|
return START_NOT_STICKY
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun logDebug(s: String) {
|
|
||||||
Log.d("ZLog", s)
|
|
||||||
}
|
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
private fun installSplitApkFiles(apkFiles: ArrayList<FileInfo>) {
|
private fun installSplitApkFiles(apkFiles: ArrayList<FileInfo>) : Boolean {
|
||||||
var sessionId: Int?
|
var sessionId: Int?
|
||||||
Log.d("AppLog", "installing split apk files:$apkFiles")
|
Log.d("AppLog", "installing split apk files:$apkFiles")
|
||||||
run {
|
run {
|
||||||
|
@ -116,12 +131,10 @@ class RootSplitInstallerService: Service() {
|
||||||
Log.d("AppLog", "committing...")
|
Log.d("AppLog", "committing...")
|
||||||
val installResult = Shell.su("pm install-commit $sessionId").exec()
|
val installResult = Shell.su("pm install-commit $sessionId").exec()
|
||||||
if (installResult.isSuccess) {
|
if (installResult.isSuccess) {
|
||||||
with(localBroadcastManager) {
|
return true
|
||||||
sendBroadcast(Intent(HomeFragment.REFRESH_HOME))
|
|
||||||
sendBroadcast(Intent(HomeFragment.VANCED_INSTALLED))
|
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
sendFailure(installResult.out, this)
|
sendFailure(installResult.out, this)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun SimpleDateFormat.tryParse(str: String) = try {
|
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()
|
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/"))
|
if(path.contains("/data/app/"))
|
||||||
{
|
{
|
||||||
logDebug("Path is in /data/app: $path" )
|
when(getPkgVerCode(yPkg)?.let { compareVersion(it,versionCode) })
|
||||||
when(compareVersion(getPkgVerCode(yPkg),versionCode))
|
|
||||||
{
|
{
|
||||||
1 -> {fixHigherVer(baseApkFiles);logDebug("higher version uninstalling then installing base + patched");}
|
1 -> {return fixHigherVer(baseApkFiles) }
|
||||||
-1 -> {fixLowerVer(baseApkFiles);logDebug("Lower Version installing base + patched");}
|
-1 -> {return fixLowerVer(baseApkFiles) }
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logDebug("No install in /data/app/ now installing")
|
return fixNoInstall(baseApkFiles)
|
||||||
fixNoInstall(baseApkFiles)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return fixNoInstall(baseApkFiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private fun getPkgVerCode(pkg: String): Int {
|
private fun getPkgVerCode(pkg: String): Int? {
|
||||||
val pm = packageManager
|
val pm = packageManager
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
|
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
|
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 m = packageManager
|
||||||
val p: PackageInfo = m.getPackageInfo(pkg, 0)
|
val info = m.getPackageInfo(pkg, 0)
|
||||||
return p
|
info
|
||||||
|
} catch (e:Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun compareVersion(pkgVerCode: Int, versionCode: Int): Int
|
private fun compareVersion(pkgVerCode: Int, versionCode: Int): Int
|
||||||
|
@ -242,33 +258,88 @@ class RootSplitInstallerService: Service() {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fixHigherVer(apkFiles: ArrayList<FileInfo>) {
|
private fun fixHigherVer(apkFiles: ArrayList<FileInfo>) : Boolean {
|
||||||
|
|
||||||
PackageHelper.uninstallApk(yPkg, applicationContext)
|
if(PackageHelper.uninstallApk(yPkg, applicationContext))
|
||||||
installSplitApkFiles(apkFiles)
|
{
|
||||||
|
return installSplitApkFiles(apkFiles)
|
||||||
|
}
|
||||||
|
with(localBroadcastManager) {sendFailure(listOf("Failed Uninstall Of Installed Version, Try Manually").toMutableList(), applicationContext)}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fixLowerVer(apkFiles: ArrayList<FileInfo>) {
|
private fun fixLowerVer(apkFiles: ArrayList<FileInfo>): Boolean {
|
||||||
installSplitApkFiles(apkFiles)
|
return installSplitApkFiles(apkFiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fixNoInstall(baseApkFiles: ArrayList<FileInfo>) {
|
private fun fixNoInstall(baseApkFiles: ArrayList<FileInfo>): Boolean {
|
||||||
installSplitApkFiles(baseApkFiles)
|
return installSplitApkFiles(baseApkFiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun chConV(path: String) {
|
private fun chConV(path: String): Boolean {
|
||||||
Shell.su("chcon -R u:object_r:system_file:s0 $path").exec()
|
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) {
|
private fun moveAPK(apkFile: String, path: String) : Boolean {
|
||||||
Shell.su("cp $apkFile $path").exec()
|
|
||||||
Shell.su("chmod 644 $path").exec()
|
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)
|
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.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import com.vanced.manager.core.installer.AppUninstallerService
|
import com.vanced.manager.core.installer.AppUninstallerService
|
||||||
|
import java.lang.Exception
|
||||||
|
|
||||||
object PackageHelper {
|
object PackageHelper {
|
||||||
|
|
||||||
|
@ -32,10 +33,18 @@ object PackageHelper {
|
||||||
activity.packageManager.packageInstaller.uninstall(pkg, pendingIntent.intentSender)
|
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)
|
val callbackIntent = Intent(applicationContext, AppUninstallerService::class.java)
|
||||||
callbackIntent.putExtra("pkg", pkg)
|
callbackIntent.putExtra("pkg", pkg)
|
||||||
val pendingIntent = PendingIntent.getService(applicationContext, 0, callbackIntent, 0)
|
val pendingIntent = PendingIntent.getService(applicationContext, 0, callbackIntent, 0)
|
||||||
|
try {
|
||||||
applicationContext.packageManager.packageInstaller.uninstall(pkg, pendingIntent.intentSender)
|
applicationContext.packageManager.packageInstaller.uninstall(pkg, pendingIntent.intentSender)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
catch (e: Exception)
|
||||||
|
{
|
||||||
|
e.printStackTrace()
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue