Skip to content

Commit 0cb203e

Browse files
Added: Init repo
1 parent a04c386 commit 0cb203e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1908
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: Attach APK To Release
2+
3+
on:
4+
release:
5+
types:
6+
- published
7+
8+
jobs:
9+
attach-apk:
10+
runs-on: ubuntu-latest
11+
env:
12+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
13+
steps:
14+
- name: Clone repository
15+
uses: actions/checkout@v2
16+
with:
17+
ref: ${{ env.GITHUB_REF }}
18+
19+
- name: Generate keystore properties
20+
run: |
21+
if [ ! -z "${{ secrets.KEYSTORE }}" ]; then
22+
echo storeFile='keystore.jks' > keystore.properties
23+
echo storePassword='${{ secrets.STORE_PASSWORD }}' >> keystore.properties
24+
echo keyAlias='${{ secrets.KEY_ALIAS }}' >> keystore.properties
25+
echo keyPassword='${{ secrets.KEY_PASSWORD }}' >> keystore.properties
26+
echo ${{ secrets.KEYSTORE }} | base64 --decode > keystore.jks # Generated with `base64 -w 0 keystore.jks > keystore.base64`
27+
fi
28+
29+
- name: Build and attach APK to release
30+
shell: bash {0}
31+
run: |
32+
exit_on_error() {
33+
echo "$1"
34+
echo "Deleting '$RELEASE_VERSION_NAME' release and '$GITHUB_REF' tag"
35+
hub release delete "$RELEASE_VERSION_NAME"
36+
git push --delete origin "$GITHUB_REF"
37+
exit 1
38+
}
39+
40+
echo "Setting vars"
41+
RELEASE_VERSION_NAME="${GITHUB_REF/refs\/tags\//}"
42+
if ! printf "%s" "${RELEASE_VERSION_NAME/v/}" | grep -qP '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'; then
43+
exit_on_error "The versionName '${RELEASE_VERSION_NAME/v/}' is not a valid version as per semantic version '2.0.0' spec in the format 'major.minor.patch(-prerelease)(+buildmetadata)'. https://semver.org/spec/v2.0.0.html."
44+
fi
45+
46+
APK_DIR_PATH="./app/build/outputs/apk/release"
47+
APK_VERSION_TAG="$RELEASE_VERSION_NAME+github-release"
48+
APK_BASENAME_PREFIX="XLogcatManager_$APK_VERSION_TAG"
49+
50+
echo "Building APK for '$RELEASE_VERSION_NAME' release"
51+
export XLOGCATMANAGER_APK_VERSION_TAG="$APK_VERSION_TAG" # Used by app/build.gradle
52+
if ! ./gradlew assembleRelease; then
53+
exit_on_error "Build failed for '$RELEASE_VERSION_NAME' release."
54+
fi
55+
56+
echo "Validating APK"
57+
if ! test -f "$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk"; then
58+
files_found="$(ls "$APK_DIR_PATH")"
59+
exit_on_error "Failed to find built APK at '$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk'. Files found: "$'\n'"$files_found"
60+
fi
61+
62+
echo "Generating sha25sums file"
63+
if ! (cd "$APK_DIR_PATH"; sha256sum "${APK_BASENAME_PREFIX}.apk" > sha256sums); then
64+
exit_on_error "Generate sha25sums failed for '$RELEASE_VERSION_NAME' release."
65+
fi
66+
67+
echo "Attaching APK to github release"
68+
if ! hub release edit \
69+
-m "" \
70+
-a "$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk" \
71+
-a "$APK_DIR_PATH/sha256sums" \
72+
"$RELEASE_VERSION_NAME"; then
73+
exit_on_error "Attach APK to release failed for '$RELEASE_VERSION_NAME' release."
74+
fi

.github/workflows/debug_build.yml

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: Build
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
branches:
9+
- master
10+
11+
jobs:
12+
build:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Clone repository
16+
uses: actions/checkout@v2
17+
18+
- name: Build APK
19+
shell: bash {0}
20+
run: |
21+
exit_on_error() { echo "$1"; exit 1; }
22+
23+
echo "Setting vars"
24+
# Set RELEASE_VERSION_NAME to "<CURRENT_VERSION_NAME>+<last_commit_hash>"
25+
CURRENT_VERSION_NAME_REGEX='\s+versionName "([^"]+)"$'
26+
CURRENT_VERSION_NAME="$(grep -m 1 -E "$CURRENT_VERSION_NAME_REGEX" ./app/build.gradle | sed -r "s/$CURRENT_VERSION_NAME_REGEX/\1/")"
27+
RELEASE_VERSION_NAME="v$CURRENT_VERSION_NAME+${GITHUB_SHA:0:7}" # The "+" is necessary so that versioning precedence is not affected
28+
if ! printf "%s" "${RELEASE_VERSION_NAME/v/}" | grep -qP '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'; then
29+
exit_on_error "The versionName '${RELEASE_VERSION_NAME/v/}' is not a valid version as per semantic version '2.0.0' spec in the format 'major.minor.patch(-prerelease)(+buildmetadata)'. https://semver.org/spec/v2.0.0.html."
30+
fi
31+
32+
APK_DIR_PATH="./app/build/outputs/apk/debug"
33+
APK_VERSION_TAG="$RELEASE_VERSION_NAME-github-debug" # Note the "-", GITHUB_SHA will already have "+" before it
34+
APK_BASENAME_PREFIX="XLogcatManager_$APK_VERSION_TAG"
35+
36+
# Used by attachment steps later
37+
echo "APK_DIR_PATH=$APK_DIR_PATH" >> $GITHUB_ENV
38+
echo "APK_VERSION_TAG=$APK_VERSION_TAG" >> $GITHUB_ENV
39+
echo "APK_BASENAME_PREFIX=$APK_BASENAME_PREFIX" >> $GITHUB_ENV
40+
41+
echo "Building APK for '$RELEASE_VERSION_NAME' build"
42+
export XLOGCATMANAGER_APP_VERSION_NAME="${RELEASE_VERSION_NAME/v/}" # Used by app/build.gradle
43+
export XLOGCATMANAGER_APK_VERSION_TAG="$APK_VERSION_TAG" # Used by app/build.gradle
44+
if ! ./gradlew assembleDebug; then
45+
exit_on_error "Build failed for '$RELEASE_VERSION_NAME' build."
46+
fi
47+
48+
echo "Validating APK"
49+
if ! test -f "$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk"; then
50+
files_found="$(ls "$APK_DIR_PATH")"
51+
exit_on_error "Failed to find built APK at '$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk'. Files found: "$'\n'"$files_found"
52+
fi
53+
54+
echo "Generating sha25sums file"
55+
if ! (cd "$APK_DIR_PATH"; sha256sum "${APK_BASENAME_PREFIX}.apk" > sha256sums); then
56+
exit_on_error "Generate sha25sums failed for '$RELEASE_VERSION_NAME' release."
57+
fi
58+
59+
- name: Attach files
60+
uses: actions/upload-artifact@v2
61+
with:
62+
name: ${{ env.APK_BASENAME_PREFIX }}
63+
path: |
64+
${{ env.APK_DIR_PATH }}/${{ env.APK_BASENAME_PREFIX }}.apk
65+
${{ env.APK_DIR_PATH }}/sha256sums
66+
${{ env.APK_DIR_PATH }}/output-metadata.json

.gitignore

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
*.iml
2+
.idea/
3+
4+
.gradle/
5+
6+
build/
7+
captures/
8+
.externalNativeBuild/
9+
.cxx/
10+
11+
/local.properties
12+
13+
/keystore.properties
14+
/keystore.jks
15+
/keystore.base64
16+
17+
.DS_Store

README.md

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# XLogcatManager
2+
3+
[![Build status](https://github.com/agnostic-apollo/XLogcatManager/workflows/Build/badge.svg)](https://github.com/agnostic-apollo/XLogcatManager/actions)
4+
5+
XLogcatManager is an Android app to improve [`LogcatManager`](https://cs.android.com/android/platform/superproject/+/android-13.0.0_r3:frameworks/base/services/core/java/com/android/server/logcat) added in Android 13 using Xposed hooks. The app requires a **rooted device** to work.
6+
7+
Android `13` added [`LogcatManager`](https://cs.android.com/android/platform/superproject/+/android-13.0.0_r3:frameworks/base/services/core/java/com/android/server/logcat) which shows a dialog when an app runs `logcat` command that has `READ_LOGS` permission before it is allowed to read system wide logs and access is only allowed for the next `60s`, after which approval is required again. Access dialog will only be shown if the app is on the top, even if it has a foreground service, and access will be denied for all other background apps automatically. On previous android versions, the app only needed to be granted `READ_LOGS` permission once with `adb` or `root` and then could read logs whenever it wanted.
8+
9+
This affects automation apps like [Tasker](https://tasker.joaoapps.com) and terminal apps like [Termux](https://github.com/termux/termux-app) which won't be able to run `logcat` commands with ease anymore, unless granted `adb` or `root` access to run `logcat` commands, which doesn't show the dialog and access is automatically granted. The tasker app in its [recent beta `v6.1.3-beta`](https://www.reddit.com/r/tasker/comments/wqvt5b/dev_tasker_613beta_progress_bar_dialog_change/) has added support to use `adb` or `root` for `logcat` commands, like run for `Logcat Entry` event, because of issues with current design.
10+
11+
The `XLogcatManager` xposed module was created to allow rooted users to not have to grant `adb` or `root` access to apps that shouldn't require it just to read logs by solving `LogcatManager` design issues and some bugs.
12+
13+
**Check the issuetracker at https://issuetracker.google.com/issues/243904932 for more details of the `LogcatManager` design and current bugs.**
14+
15+
Other related links are
16+
17+
- https://issuetracker.google.com/issues/232206670
18+
19+
- https://www.reddit.com/r/tasker/comments/wpt39b/dev_warning_if_you_update_to_android_13_the
20+
21+
- https://twitter.com/MishaalRahman/status/1559930174598270976
22+
23+
The module is based on currently latest Android 13 avd and pixel builds for `July/Aug 2022` and may break depending on changes or fixups made in future builds, **so use at your own risk** and keep checking the github repo for updates. If you get into a bootloop, check [magisk guide](https://topjohnwu.github.io/Magisk/faq.html#q-i-installed-a-module-and-it-bootlooped-my-device-help) for how to disable modules.
24+
##
25+
26+
27+
28+
### Contents
29+
- [Installation](#installation)
30+
- [Usage](#Usage)
31+
- [Features](#features)
32+
##
33+
34+
35+
36+
### Installation
37+
38+
Latest version is `v0.0.0`.
39+
40+
The APK files of different sources are signed with different signature keys. Do not attempt to mix them together, i.e do not try to install the app from `Github Releases` and then from a different source like `Github Actions`. Android Package Manager will also normally not allow installation of APKs with different signatures and you will get errors on installation like `App not installed`, `Failed to install due to an unknown error`, `INSTALL_FAILED_UPDATE_INCOMPATIBLE`, `INSTALL_FAILED_SHARED_USER_INCOMPATIBLE`, `signatures do not match previously installed version`, etc. This restriction can be bypassed with root or with custom roms.
41+
42+
If you wish to install from a different source, then you must **uninstall the existing XLogcatManager APK** from your device first, then install APK from the new source.
43+
44+
### Github Releases
45+
46+
`XLogcatManager` application official releases can be obtained from [`Github Releases`](https://github.com/agnostic-apollo/XLogcatManager/releases).
47+
48+
The APKs for `Github Releases` will be listed under `Assets` drop-down of a release. These are automatically attached when a new version is released.
49+
50+
### Github Actions
51+
52+
`XLogcatManager` application beta releases can be obtained from [`Github Build`](https://github.com/agnostic-apollo/XLogcatManager/actions/workflows/debug_build.yml) action workflows.
53+
54+
The APKs for `Github Build` action workflows will be listed under `Artifacts` section of a workflow run. These are created for each commit/push done to the repository and can be used by users who don't want to wait for releases and want to try out the latest features immediately or want to test their pull requests. Note that for action workflows, you need to be [**logged into a `Github` account**](https://github.com/login) for the `Artifacts` links to be enabled/clickable. If you are using the [`Github` app](https://github.com/mobile), then make sure to open workflow link in a browser like Chrome or Firefox that has your Github account logged in since the in-app browser may not be logged in.
55+
56+
The APKs are [`debuggable`](https://developer.android.com/studio/debug).
57+
##
58+
59+
60+
### Usage
61+
62+
- Root device with [`Magisk`](https://github.com/topjohnwu/Magisk). Optionally enable [zygisk](https://topjohnwu.github.io/Magisk/guides.html#zygisk) in its settings.
63+
64+
- Install [`LSPosed`](https://github.com/LSPosed/LSPosed#install). [`EdXposed`](https://github.com/ElderDrivers/EdXposed#install) is untested. `EdXposed` and other implementations will not work if they don't have `XposedBridge.deoptimizeMethod()` method implemented, check [`LSPosed/LSPosed#1123`](https://github.com/LSPosed/LSPosed/issues/1123) and [`XposedModule.deoptimizeMethod()`](https://github.com/agnostic-apollo/XLogcatManager/blob/v0.1.0/app/src/main/java/dev/agnosticapollo/xlogcatmanager/xposed/XposedModule.java#L71) for details.
65+
66+
- [Install `XLogcatManager`](#installation) apk and enable it in `LSPosed` modules list. Only Android `System Framework` needs to enabled for module scope. For running on Android `avd`, check [`XposedModule` class javadocs](https://github.com/agnostic-apollo/XLogcatManager/blob/v0.1.0/app/src/main/java/dev/agnosticapollo/xlogcatmanager/xposed/XposedModule.java#L30).
67+
68+
- Reboot device. Rebooting will be required whenever module is installed/updated for changes to take effect.
69+
70+
- If module does not work or to debug issues, check [`logcat`](https://developer.android.com/studio/command-line/logcat). Take `logcat` dump by running `adb logcat -d > logcat.txt` from a PC over `ADB` or `su -c 'logcat -d > /sdcard/logcat.txt'` in an app granted `root` access, like [`Termux`](https://github.com/termux/termux-app). Hooking is done during boot time, so run `logcat` right after boot completes to get related log entries.
71+
##
72+
73+
74+
75+
### Features
76+
77+
Current features are listed below. Further configuration options can be added in future when I get time.
78+
79+
- Allows access till next reboot to the app if users selects allow button in the allow access dialog instead of just for the next `60s`.
80+
- No `60s` timeout to reshow dialog if access was (accidentally) denied by user.
81+
- The dialog will also show for apps with foreground service instead of just top apps.
82+
- Fixes the bugs mentioned in the [issuetracker issue](https://issuetracker.google.com/issues/243904932) based on the solutions provided, but implementation is slightly different in some cases due to method hooking limitations. The main classes that do the hooking are [`XLogcatManagerService.java`](https://github.com/agnostic-apollo/XLogcatManager/blob/master/app/src/main/java/dev/agnosticapollo/xlogcatmanager/xposed/logcat/XLogcatManagerService.java) and [`XLogAccessDialogActivity.java`](https://github.com/agnostic-apollo/XLogcatManager/blob/master/app/src/main/java/dev/agnosticapollo/xlogcatmanager/xposed/logcat/XLogAccessDialogActivity.java).
83+
##

app/build.gradle

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
apply plugin: 'com.android.application'
2+
3+
android {
4+
compileSdkVersion project.properties.compileSdkVersion.toInteger()
5+
6+
def appApkLabel = "XLogcatManager"
7+
def appVersionName = System.getenv("XLOGCATMANAGER_APP_VERSION_NAME") ?: ""
8+
def apkVersionTag = System.getenv("XLOGCATMANAGER_APK_VERSION_TAG") ?: ""
9+
10+
// Load keystore.properties file that contains info of the signing key for release build apks
11+
// The keystore.properties file should exist in the root directory of the project (not app directory)
12+
// It must have the following 4 values in the format:
13+
// storeFile=<path to store keystore.jks>
14+
// storePassword=<store password>
15+
// keyAlias=<key alias>
16+
// keyPassword=<key password>
17+
def keystorePropertiesFile = rootProject.file("keystore.properties")
18+
def keystoreProperties = new Properties()
19+
if (keystorePropertiesFile.exists()) {
20+
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
21+
}
22+
23+
defaultConfig {
24+
applicationId "dev.agnosticapollo.xlogcatmanager"
25+
minSdkVersion project.properties.minSdkVersion.toInteger()
26+
targetSdkVersion project.properties.targetSdkVersion.toInteger()
27+
versionCode 0
28+
versionName "0.0.0"
29+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
30+
31+
if (appVersionName) versionName = appVersionName
32+
validateVersionName(versionName)
33+
34+
manifestPlaceholders.APP_PACKAGE_NAME = applicationId
35+
}
36+
37+
signingConfigs {
38+
release {
39+
if (!keystoreProperties.isEmpty()) {
40+
storeFile rootProject.file(keystoreProperties['storeFile'])
41+
storePassword keystoreProperties['storePassword']
42+
keyAlias keystoreProperties['keyAlias']
43+
keyPassword keystoreProperties['keyPassword']
44+
}
45+
}
46+
47+
debug {
48+
storeFile file('dev_keystore.jks')
49+
storePassword 'android'
50+
keyAlias 'debug'
51+
keyPassword 'android'
52+
}
53+
}
54+
55+
buildTypes {
56+
release {
57+
minifyEnabled true
58+
shrinkResources false // Reproducible builds
59+
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
60+
signingConfig signingConfigs.release
61+
}
62+
63+
debug {
64+
signingConfig signingConfigs.debug
65+
}
66+
}
67+
68+
compileOptions {
69+
sourceCompatibility JavaVersion.VERSION_1_8
70+
targetCompatibility JavaVersion.VERSION_1_8
71+
}
72+
73+
packagingOptions {
74+
// Remove terminal-emulator and termux-shared JNI libs added via termux-shared dependency
75+
exclude 'lib/*/libtermux.so'
76+
exclude 'lib/*/liblocal-socket.so'
77+
}
78+
79+
applicationVariants.all { variant ->
80+
variant.outputs.all { output ->
81+
if (variant.buildType.name == "debug") {
82+
outputFileName = new File(appApkLabel + "_" + (apkVersionTag ? apkVersionTag : "debug") + ".apk")
83+
} else if (variant.buildType.name == "release") {
84+
outputFileName = new File(appApkLabel + "_" + (apkVersionTag ? apkVersionTag : "release") + ".apk")
85+
}
86+
}
87+
}
88+
}
89+
90+
dependencies {
91+
implementation fileTree(dir: 'libs', include: ['*.jar'])
92+
93+
testImplementation "junit:junit:4.13.2"
94+
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
95+
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
96+
97+
implementation 'com.google.android.material:material:1.6.1'
98+
implementation 'androidx.appcompat:appcompat:1.5.0'
99+
compileOnly 'de.robv.android.xposed:api:82'
100+
//compileOnly 'de.robv.android.xposed:api:82:sources'
101+
102+
implementation 'com.github.termux.termux-app:termux-shared:211340781b'
103+
// Use if below libraries are published locally by termux-app with `./gradlew publishReleasePublicationToMavenLocal` and used with `mavenLocal()`.
104+
// If updates are done, republish there and sync project with gradle files here
105+
// https://github.com/termux/termux-app/wiki/Termux-Libraries
106+
// implementation 'com.termux:termux-shared:0.118.0'
107+
108+
implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
109+
}
110+
111+
task versionName {
112+
doLast {
113+
print android.defaultConfig.versionName
114+
}
115+
}
116+
117+
static def validateVersionName(String versionName) {
118+
// https://semver.org/spec/v2.0.0.html#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
119+
// ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
120+
if (!java.util.regex.Pattern.matches("^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?\$", versionName))
121+
throw new IllegalArgumentException("The versionName '" + versionName + "' is not a valid version as per semantic version '2.0.0' spec in the format 'major.minor.patch(-prerelease)(+buildmetadata)'. https://semver.org/spec/v2.0.0.html.")
122+
}

app/dev_keystore.jks

4.18 KB
Binary file not shown.

0 commit comments

Comments
 (0)