Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: merge dev to main #1573

Merged
merged 23 commits into from
Dec 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
aa91abb
docs(readme): Correct grammar mistake (#1569)
festry0 Dec 14, 2023
dcaf1f5
build(gradle): bump Gradle to v8.5
validcube Dec 17, 2023
c06d15d
docs: Improve troubleshooting solutions (#1543)
raxod502 Dec 22, 2023
f8d086a
feat: dialogs correctly follows Material 3 specifications (#1560)
validcube Dec 22, 2023
8b28a33
ci(security): resolve arbitrary code execution
validcube Dec 22, 2023
c23275f
feat: Improve installation robustness (#1528)
TheAabedKhan Dec 23, 2023
c56c445
fix: migration latest changes to native buttons
validcube Dec 23, 2023
a0b673c
refactor: apply suggestions from analyser
validcube Dec 23, 2023
2ae8d49
fix: exported logs patch selection (#1535)
BenjaminHalko Dec 23, 2023
8a1ab47
fix: Prevent crash by escaping string correctly
oSumAtrIX Dec 23, 2023
5b1c89a
perf: Reduce amount of shell commands
oSumAtrIX Dec 23, 2023
9680f0c
refactor: Remove unnecessary quotation marks
oSumAtrIX Dec 23, 2023
48a739c
refactor: Simplify `uninstallApp` code
oSumAtrIX Dec 23, 2023
7a1ba9d
fix: Add missing confirmation dialog
oSumAtrIX Dec 23, 2023
69b6ef0
feat: Improve dialog text clarity
oSumAtrIX Dec 23, 2023
11a8f31
feat: Clarify non root installation button
oSumAtrIX Dec 23, 2023
7426f54
fix: Update home screen after installation
oSumAtrIX Dec 23, 2023
1928b15
fix: Use correct installation type labels
oSumAtrIX Dec 23, 2023
1298a96
fix: Update the progress properly until installation finishes success…
oSumAtrIX Dec 23, 2023
a141ec8
fix: Correct update message
oSumAtrIX Dec 23, 2023
ca95e32
chore: Ignore autogenerated project file
oSumAtrIX Dec 23, 2023
850bdc4
fix: Reset progress if patch was cancelled
oSumAtrIX Dec 23, 2023
85c8006
build: Bump version to `v1.18.0`
oSumAtrIX Dec 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/pr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ jobs:
env:
GH_TOKEN: ${{ github.token }}
run: |
gh repo clone ${{ github.repository }}
gh repo clone "${{ github.repository }}"
cd revanced-manager
gh repo set-default ${{ github.repository }}
gh pr checkout ${{ inputs.pr-number }}
gh repo set-default "${{ github.repository }}"
gh pr checkout "${{ inputs.pr-number }}"

echo "DATETIME=$( TZ='UTC+0' date --rfc-email )" >> $GITHUB_ENV
echo "COMMIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
Expand Down Expand Up @@ -83,7 +83,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
flutter build apk --${{ inputs.app-flavour }};
flutter build apk --"${{ inputs.app-flavour }}";

- name: Prepare to comment
run: |
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
.buildlog/
.history
.svn/
local.properties

# IntelliJ related
*.iml
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ ReVanced Manager is an Android application that uses ReVanced Patcher to add, re

## 💪 Features

We provide the some of the features are:
Some of the features we provide are:

* 📱 **Portable**: ReVanced Patcher that fit in your pocket;
* 🤗 **Intuitive UI**: Help you manage your patched applications with easy-to-use interface;
Expand Down
33 changes: 25 additions & 8 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"/>
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ExportSettingsActivity"
android:exported="true">
</activity>
<activity
android:name=".ExportSettingsActivity"
android:exported="true">
</activity>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
Expand All @@ -55,5 +55,22 @@
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>

<receiver
android:name=".utils.packageInstaller.InstallerReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="APP_INSTALL_ACTION" />
</intent-filter>
</receiver>
<receiver
android:name=".utils.packageInstaller.UninstallerReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="APP_UNINSTALL_ACTION" />
</intent-filter>
</receiver>
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package app.revanced.manager.flutter

import android.app.PendingIntent
import android.app.SearchManager
import android.content.Intent
import android.content.pm.PackageInstaller
import android.os.Build
import android.os.Handler
import android.os.Looper
import app.revanced.manager.flutter.utils.Aapt
import app.revanced.manager.flutter.utils.aligning.ZipAligner
import app.revanced.manager.flutter.utils.packageInstaller.InstallerReceiver
import app.revanced.manager.flutter.utils.packageInstaller.UninstallerReceiver
import app.revanced.manager.flutter.utils.signing.Signer
import app.revanced.manager.flutter.utils.zip.ZipFile
import app.revanced.manager.flutter.utils.zip.structures.ZipEntry
Expand Down Expand Up @@ -184,12 +189,24 @@ class MainActivity : FlutterActivity() {
}.toString().let(result::success)
}

"installApk" -> {
val apkPath = call.argument<String>("apkPath")!!
PackageInstallerManager.result = result
installApk(apkPath)
}

"uninstallApp" -> {
val packageName = call.argument<String>("packageName")!!
uninstallApp(packageName)
PackageInstallerManager.result = result
}

else -> result.notImplemented()
}
}
}

fun openBrowser(query: String?) {
private fun openBrowser(query: String?) {
val intent = Intent(Intent.ACTION_WEB_SEARCH).apply {
putExtra(SearchManager.QUERY, query)
}
Expand Down Expand Up @@ -349,7 +366,7 @@ class MainActivity : FlutterActivity() {
return@Thread
}

updateProgress(0.8, "Building...", "")
updateProgress(0.75, "Building...", "")

val res = patcher.get()
patcher.close()
Expand Down Expand Up @@ -382,7 +399,7 @@ class MainActivity : FlutterActivity() {
return@Thread
}

updateProgress(0.9, "Signing...", "Signing APK")
updateProgress(0.8, "Signing...", "Signing APK")

try {
Signer("ReVanced", keystorePassword)
Expand All @@ -392,7 +409,7 @@ class MainActivity : FlutterActivity() {
e.printStackTrace()
}

updateProgress(1.0, "Patched", "Patched")
updateProgress(.85, "Patched", "Patched APK")
} catch (ex: Throwable) {
if (!cancel) {
val stack = ex.stackTraceToString()
Expand All @@ -407,4 +424,44 @@ class MainActivity : FlutterActivity() {
handler.post { result.success(null) }
}.start()
}

private fun installApk(apkPath: String) {
val packageInstaller: PackageInstaller = applicationContext.packageManager.packageInstaller
val sessionParams = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
val sessionId: Int = packageInstaller.createSession(sessionParams)
val session: PackageInstaller.Session = packageInstaller.openSession(sessionId)
session.use { activeSession ->
val sessionOutputStream = activeSession.openWrite(applicationContext.packageName, 0, -1)
sessionOutputStream.use { outputStream ->
val apkFile = File(apkPath)
apkFile.inputStream().use { inputStream ->
inputStream.copyTo(outputStream)
}
}
}
val receiverIntent = Intent(applicationContext, InstallerReceiver::class.java).apply {
action = "APP_INSTALL_ACTION"
}
val receiverPendingIntent = PendingIntent.getBroadcast(context, sessionId, receiverIntent, PackageInstallerManager.flags)
session.commit(receiverPendingIntent.intentSender)
session.close()
}

private fun uninstallApp(packageName: String) {
val packageInstaller: PackageInstaller = applicationContext.packageManager.packageInstaller
val receiverIntent = Intent(applicationContext, UninstallerReceiver::class.java).apply {
action = "APP_UNINSTALL_ACTION"
}
val receiverPendingIntent = PendingIntent.getBroadcast(context, 0, receiverIntent, PackageInstallerManager.flags)
packageInstaller.uninstall(packageName, receiverPendingIntent.intentSender)
}

object PackageInstallerManager {
var result: MethodChannel.Result? = null
val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
} else {
PendingIntent.FLAG_UPDATE_CURRENT
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package app.revanced.manager.flutter.utils.packageInstaller

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.pm.PackageInstaller
import app.revanced.manager.flutter.MainActivity

class InstallerReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when (val status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -1)) {
PackageInstaller.STATUS_PENDING_USER_ACTION -> {
val confirmationIntent = intent.getParcelableExtra<Intent>(Intent.EXTRA_INTENT)
if (confirmationIntent != null) {
context.startActivity(confirmationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
}
}

else -> {
val packageName = intent.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME)
val message = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE)
val otherPackageName = intent.getStringExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME)
MainActivity.PackageInstallerManager.result!!.success(mapOf(
"status" to status,
"packageName" to packageName,
"message" to message,
"otherPackageName" to otherPackageName
))
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package app.revanced.manager.flutter.utils.packageInstaller

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.pm.PackageInstaller
import app.revanced.manager.flutter.MainActivity

class UninstallerReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when (val status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -1)) {
PackageInstaller.STATUS_PENDING_USER_ACTION -> {
val confirmationIntent = intent.getParcelableExtra<Intent>(Intent.EXTRA_INTENT)
if (confirmationIntent != null) {
context.startActivity(confirmationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
}
}

else -> {
MainActivity.PackageInstallerManager.result!!.success(status)
}
}
}
}
4 changes: 3 additions & 1 deletion android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
distributionSha256Sum=9d926787066a081739e8200858338b4a69e837c3a821a33aca9db09dd4a41026
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
42 changes: 37 additions & 5 deletions assets/i18n/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@

"installButton": "Install",
"installRootType": "Mount",
"installNonRootType": "Normal",
"installNonRootType": "Regular",

"warning": "Disable auto updates for the patched app to avoid unexpected issues.",

"pressBackAgain": "Press back again to cancel",
"openButton": "Open",
Expand Down Expand Up @@ -302,16 +304,17 @@
"widgetTitle": "App info",
"openButton": "Open",
"uninstallButton": "Uninstall",
"unpatchButton": "Unpatch",
"unmountButton": "Unmount",
"rootDialogTitle": "Error",

"unpatchDialogText": "Are you sure you want to unpatch this app?",
"unmountDialogText": "Are you sure you want to unmount this app?",
"uninstallDialogText": "Are you sure you want to uninstall this app?",
"rootDialogText": "App was installed with superuser permissions, but currently ReVanced Manager has no permissions.\nPlease grant superuser permissions first.",

"packageNameLabel": "Package name",
"installTypeLabel": "Installation type",
"rootTypeLabel": "Root",
"nonRootTypeLabel": "Non-root",
"mountTypeLabel": "Mount",
"regularTypeLabel": "Regular",
"patchedDateLabel": "Patched date",
"appliedPatchesLabel": "Applied patches",

Expand All @@ -327,5 +330,34 @@
"integrationsContributors": "Integrations contributors",
"cliContributors": "CLI contributors",
"managerContributors": "Manager contributors"
},
"installErrorDialog": {
"mount_version_mismatch": "Version mismatch",
"mount_no_root": "No root access",
"mount_missing_installation": "Installation not found",

"status_failure_blocked": "Installation blocked",
"install_failed_verification_failure": "Verification failed",
"status_failure_invalid": "Installation invalid",
"install_failed_version_downgrade": "Can't downgrade",
"status_failure_conflict": "Installation conflict",
"status_failure_storage": "Installation storage issue",
"status_failure_incompatible": "Installation incompatible",
"status_failure_timeout": "Installation timeout",
"status_unknown": "Installation failed",

"mount_version_mismatch_description": "The installation failed due to the installed app being a different version than the patched app.\n\nInstall the version of the app you are mounting and try again.",
"mount_no_root_description": "The installation failed due to root access not being granted.\n\nGrant root access to ReVanced Manager and try again.",
"mount_missing_installation_description": "The installation failed due to the unpatched app not being installed on this device in order to mount over it.\n\nInstall the unpatched app before mounting and try again.",

"status_failure_timeout_description": "The installation took too long to finish.\n\nWould you like to try again?",
"status_failure_storage_description": "The installation failed due to insufficient storage.\n\nFree up some space and try again.",
"status_failure_invalid_description": "The installation failed due to the patched app being invalid.\n\nUninstall the app and try again?",
"status_failure_incompatible_description": "The app is incompatible with this device.\n\nContact the developer of the app and ask for support.",
"status_failure_conflict_description": "The installation was prevented by an existing installation of the app.\n\nUninstall the installed app and try again?",
"status_failure_blocked_description": "The installation was blocked by {packageName}.\n\nAdjust your security settings and try again.",
"install_failed_verification_failure_description": "The installation failed due to a verification issue.\n\nAdjust your security settings and try again.",
"install_failed_version_downgrade_description": "The installation failed due to the patched app being a lower version than the installed app.\n\nUninstall the app and try again?",
"status_unknown_description": "The installation failed due to an unknown reason. Please try again."
}
}
10 changes: 7 additions & 3 deletions docs/3_troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ In case you encounter any issues while using ReVanced Manager, please refer to t
- 💉 Patching fails with an error

Make sure ReVanced Manager is up to date by following [🔄 Updating ReVanced Manager](2_3_updating.md) and select the **Default** button when choosing patches.

- 🚫 App not installed as package conflicts with an existing package

An existing installation of the app you're trying to patch is conflicting with the patched app. Uninstall the existing app before installing the patched app.
An existing installation of the app you're trying to patch conflicts with the patched app (i.e., signature mismatch or downgrade). Uninstall the existing app before installing the patched app.

- ❗️ Error code `135`, `139` or `1` when patching the app

Your device is not supported. Refer to the [Prerequisites](0_prerequisites.md) page for supported devices.
You may be trying to patch a split APK[^1]. This may not work under certain circumstances. In such a case, patch a full APK.

Your device may otherwise be unsupported. Please look at the [Prerequisites](0_prerequisites.md) page for supported devices.

Alternatively, you can use [ReVanced CLI](https://github.com/revanced/revanced-cli) to patch the app.

Expand All @@ -25,3 +27,5 @@ In case you encounter any issues while using ReVanced Manager, please refer to t
The next page will teach you how to build ReVanced Manager from source.

Continue: [🔨 Building from source](4_building.md)

[^1]: https://developer.android.com/guide/app-bundle/app-bundle-format
8 changes: 8 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:revanced_manager/services/download_manager.dart';
import 'package:revanced_manager/services/github_api.dart';
import 'package:revanced_manager/services/manager_api.dart';
import 'package:revanced_manager/services/revanced_api.dart';
import 'package:revanced_manager/services/root_api.dart';
import 'package:revanced_manager/ui/theme/dynamic_theme_builder.dart';
import 'package:revanced_manager/ui/views/navigation/navigation_view.dart';
import 'package:shared_preferences/shared_preferences.dart';
Expand All @@ -24,6 +25,13 @@ Future main() async {
final String repoUrl = locator<ManagerAPI>().getRepoUrl();
locator<GithubAPI>().initialize(repoUrl);
tz.initializeTimeZones();

// TODO(aAbed): remove in the future, keep it for now during migration.
final rootAPI = RootAPI();
if (await rootAPI.hasRootPermissions()) {
await rootAPI.removeOrphanedFiles();
}

prefs = await SharedPreferences.getInstance();

runApp(const MyApp());
Expand Down
Loading
Loading