()
22 |
23 | private var colorIndex = 0
24 |
25 | private var radius = 0F
26 |
27 | private var strokeWidthWeight = 0.25F
28 |
29 | private var startAngle = 0F
30 |
31 | private var sweepAngle = 0F
32 |
33 | private var ovalBounds = RectF()
34 |
35 | private var rotateStep = 360F
36 |
37 | private var sweepStep = 300F
38 |
39 | private var lastAnimationProgress = 0F
40 |
41 | private var lastStep = 0F
42 |
43 | private val animator = ValueAnimator.ofFloat(0F, 2F).apply {
44 | addUpdateListener(this@ProgressDrawable)
45 | addListener(this@ProgressDrawable)
46 | repeatCount = ValueAnimator.INFINITE
47 | repeatMode = ValueAnimator.RESTART
48 | interpolator = LinearInterpolator()
49 | }
50 |
51 | override fun draw(canvas: Canvas) {
52 | if (colorList.isEmpty() || radius < 1) {
53 | return
54 | }
55 | canvas.drawArc(ovalBounds, startAngle, sweepAngle, false, paint)
56 | }
57 |
58 | override fun onBoundsChange(bounds: Rect) {
59 | super.onBoundsChange(bounds)
60 | radius = min(bounds.width(), bounds.height()) * 0.5F
61 | val strokeWidth = radius * strokeWidthWeight
62 | radius -= strokeWidth * 0.5F
63 | paint.strokeWidth = strokeWidth
64 | val top = bounds.exactCenterY() - radius
65 | val left = bounds.exactCenterX() - radius
66 | val right = bounds.exactCenterX() + radius
67 | val bottom = bounds.exactCenterY() + radius
68 | ovalBounds.set(left, top, right, bottom)
69 | }
70 |
71 | override fun setAlpha(alpha: Int) {
72 | paint.alpha = alpha
73 | }
74 |
75 | override fun getOpacity() = PixelFormat.TRANSPARENT
76 |
77 | override fun setColorFilter(colorFilter: ColorFilter?) {
78 | paint.colorFilter = colorFilter
79 | }
80 |
81 | fun putColor(vararg colors: Int) {
82 | colorList.clear()
83 | for (color in colors) {
84 | colorList.add(color)
85 | }
86 | }
87 |
88 | fun progress(progress: Int, max: Int) {
89 | stop()
90 | paint.color = colorList[0]
91 | startAngle = 0F
92 | sweepAngle = 360F * progress / max
93 | invalidateSelf()
94 | }
95 |
96 | fun animatorDuration(value: Long) {
97 | animator.duration = value
98 | }
99 |
100 | override fun isRunning(): Boolean {
101 | return animator.isRunning
102 | }
103 |
104 | override fun start() {
105 | if (colorList.isEmpty()) {
106 | animator.cancel()
107 | return
108 | }
109 | animator.start()
110 | invalidateSelf()
111 | }
112 |
113 | override fun stop() {
114 | animator.cancel()
115 | }
116 |
117 | override fun onAnimationUpdate(animation: ValueAnimator) {
118 | if (animation == animator) {
119 | val value = animator.animatedValue as Float
120 | val isShrink = value > 1
121 | val sweepValue = if (value > 1) {
122 | 2 - value
123 | } else {
124 | value
125 | }
126 | val sweepLength = sweepStep * sweepValue
127 | val startValue = if (value < lastAnimationProgress) {
128 | 2F - lastAnimationProgress + value
129 | } else {
130 | value - lastAnimationProgress
131 | }
132 | lastAnimationProgress = value
133 |
134 | val step = startValue * rotateStep
135 | startAngle += step
136 | if (step < 1) {
137 | startAngle += lastStep
138 | } else {
139 | lastStep = step
140 | }
141 |
142 | if (isShrink) {
143 | val diff = sweepAngle - sweepLength
144 | startAngle += diff
145 | }
146 | sweepAngle = sweepLength
147 | startAngle %= 360
148 |
149 | invalidateSelf()
150 | }
151 | }
152 |
153 | override fun onAnimationRepeat(animation: Animator) {
154 | colorIndex++
155 | colorIndex %= colorList.size
156 | paint.color = colorList[colorIndex]
157 | }
158 |
159 | override fun onAnimationEnd(animation: Animator) {}
160 |
161 | override fun onAnimationCancel(animation: Animator) {}
162 |
163 | override fun onAnimationStart(animation: Animator) {
164 | colorIndex++
165 | colorIndex %= colorList.size
166 | paint.color = colorList[colorIndex]
167 | }
168 |
169 | }
170 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_icon.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_version_tips.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_app_icon.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
15 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_crash_error.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
21 |
24 |
27 |
30 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/app/src/main/res/drawable/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_attachment_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_auto_mode_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
13 |
16 |
19 |
22 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_bedtime_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_beenhere_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_chevron_right_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_construction_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_delete_forever_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_eject_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_get_app_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_info_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_layers_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_memory_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_play_for_work_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_priority_high_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_security_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_settings_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_silence_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_wb_sunny_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_crash_error.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
17 |
18 |
30 |
31 |
44 |
45 |
50 |
51 |
52 |
53 |
64 |
65 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_activity_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_permission_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_setting_perf.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
18 |
19 |
31 |
32 |
42 |
43 |
49 |
50 |
61 |
62 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_base_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
18 |
19 |
29 |
30 |
39 |
40 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_error.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_input_pkg.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_install_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
19 |
20 |
27 |
28 |
29 |
30 |
38 |
39 |
51 |
52 |
63 |
64 |
80 |
81 |
92 |
93 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_loading.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values-v23/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rCN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | APK安装器
4 | 安装中…
5 | 安装
6 | 设置
7 | 解析中…
8 | 无法解析文件: %s
9 | %s 安装失败
10 | %s 已安装
11 | 开始安装 %s
12 | 应用路径: %s
13 | 应用名称: %s
14 | 应用包名: %s
15 | 已装版本: %s
16 | 安装成功
17 | 安装失败
18 | 静默安装
19 | 无法安装应用
20 | 打开
21 | 自动删除安装包
22 | 自动删除
23 | %s (安装包已删除)
24 | %s 已删除
25 | "应用权限: (%s)"
26 | 应用权限
27 | 显示权限列表
28 | 活动组件: (%s)
29 | 活动组件
30 | 显示Activity列表
31 | 点击输入系统打包安装程序的包名
32 | 当安装器无法调用系统自带安装程序时启用
33 | 完成
34 | 取消
35 | 确定
36 | 不再提示
37 | 卸载
38 | 正在安装旧版本, 某些设备不支持降级安装, 可能导致安装失败!
39 | 旧版本
40 | 新版本
41 | 相同版本
42 | 没有权限!
43 | 安装失败, 是否使用系统打包安装程序进行安装?
44 | 请输入包名
45 | 输入包名
46 | 输入内容为空
47 | 来源: %s
48 | 文件大小: %s
49 | 点击查看详情
50 | APK安装包缓存大小: %s\n点击清理
51 | 清理完成
52 | 取消安装
53 | Version: %s
54 | Author: TOKYONTH
55 | com.android.packageinstaller
56 | 无对应描述
57 | 卸载 - %s 模式
58 | 确定要卸载 %s 吗?
59 | %s 卸载完成!
60 | 卸载失败!
61 | 请给予本软件 Shizuku 权限
62 | 未安装Shizuku!
63 | Shizuku没有运行!
64 | 系统SDK小于等于23无法使用Shizuku
65 | 请给予本软件 IceBox 权限
66 | 未安装冰箱!
67 | 冰箱版本过低
68 | 当前系统版本不支持静默安装
69 | 冰箱不是设备管理员
70 | 未取得权限冰箱权限
71 | 冰箱没有运行
72 | 自动暗色
73 | 跟随系统夜间模式
74 | 安装模式
75 | 选择安装模式
76 | 静默安装
77 | 默认使用静默安装
78 | 未能获取到包名
79 | 使用须知
80 | 软件运行需要储存读写权限, Android11上额外需要 访问所有文件 权限以及 Android/data 访问权限,
81 | 请赋予权限。如果安装失败, 请尝试关闭GooglePlay安全扫描, 定制系统的USB ADB安装监控等。同时非常不建议你卸载或禁用系统安装器, 这是非常危险的!
82 | 打开失败!可尝试在设置中自定义包名
83 | 退出
84 | 需要开启通知权限, 用于静默安装, 通知安装状态
85 | 发生意外错误
86 | 关闭程序
87 | 错误日志
88 | 复制日志
89 | 已复制到剪切板
90 | 32位
91 | 64位
92 | 临时文件
93 | Xposed模块
94 |
95 | - Root
96 | - Shizuku
97 | - IceBox
98 |
99 |
100 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/provider_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
11 |
12 |
15 |
16 |
19 |
20 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/test/java/com/tokyonth/installer/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.tokyonth.installer;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | plugins {
3 | id 'com.android.application' version '7.4.0' apply false
4 | id 'com.android.library' version '7.4.0' apply false
5 | id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
6 | }
7 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | android.enableJetifier=true
15 | android.useAndroidX=true
16 | android.injected.testOnly=false
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Mar 16 11:28:21 CST 2023
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/icebox/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/icebox/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 33
5 |
6 | defaultConfig {
7 | minSdkVersion 21
8 | targetSdkVersion 33
9 | versionCode 6
10 | versionName "1.0.6"
11 | }
12 | buildTypes {
13 | release {
14 | minifyEnabled false
15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
16 | }
17 | }
18 |
19 | lintOptions {
20 | abortOnError false
21 | }
22 | }
23 |
24 | dependencies {
25 | compileOnly 'androidx.annotation:annotation:1.6.0'
26 | }
27 |
--------------------------------------------------------------------------------
/icebox/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/icebox/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/icebox/src/main/java/com/catchingnow/icebox/sdk_client/AppStateUtil.java:
--------------------------------------------------------------------------------
1 | package com.catchingnow.icebox.sdk_client;
2 |
3 | import android.content.Context;
4 | import android.content.pm.ApplicationInfo;
5 | import android.content.pm.PackageManager;
6 | import android.os.Build;
7 |
8 | import androidx.annotation.Nullable;
9 |
10 | import java.lang.reflect.Field;
11 |
12 | class AppStateUtil {
13 |
14 | private static final int PM_FLAGS_GET_APP_INFO = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ?
15 | PackageManager.MATCH_UNINSTALLED_PACKAGES
16 | : PackageManager.GET_UNINSTALLED_PACKAGES;
17 |
18 | private static final int PRIVATE_FLAG_HIDDEN = 1;
19 | private static final int FLAG_HIDDEN = 1 << 27;
20 |
21 | @Nullable
22 | private static Field AI_FIELD;
23 |
24 | static {
25 | try {
26 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
27 | throw new UnsupportedOperationException();
28 | AI_FIELD = ApplicationInfo.class.getDeclaredField("privateFlags");
29 | AI_FIELD.setAccessible(true);
30 | } catch (Throwable ignored) {
31 | AI_FIELD = null;
32 | }
33 | }
34 |
35 | private static boolean isAppHidden(ApplicationInfo ai) {
36 | if (AI_FIELD != null) {
37 | try {
38 | int flags = (int) AI_FIELD.get(ai);
39 | return (flags | PRIVATE_FLAG_HIDDEN) == flags;
40 | } catch (Throwable e) {
41 | return (ai.flags | FLAG_HIDDEN) == ai.flags;
42 | }
43 | } else {
44 | return (ai.flags | FLAG_HIDDEN) == ai.flags;
45 | }
46 | }
47 |
48 | @IceBox.AppState
49 | static int getAppEnabledSettings(Context context, String packageName) throws PackageManager.NameNotFoundException {
50 | ApplicationInfo applicationInfo = context.getPackageManager()
51 | .getApplicationInfo(packageName, PM_FLAGS_GET_APP_INFO);
52 | return getAppEnabledSettings(applicationInfo);
53 |
54 | }
55 |
56 | @IceBox.AppState
57 | static int getAppEnabledSettings(ApplicationInfo applicationInfo) {
58 | @IceBox.AppState int flag = 0;
59 | if (isAppHidden(applicationInfo)) flag += IceBox.FLAG_PM_HIDE;
60 | if (!applicationInfo.enabled) flag += IceBox.FLAG_PM_DISABLE_USER;
61 | return flag;
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/icebox/src/main/java/com/catchingnow/icebox/sdk_client/AuthorizeUtil.java:
--------------------------------------------------------------------------------
1 | package com.catchingnow.icebox.sdk_client;
2 |
3 | import android.app.PendingIntent;
4 | import android.content.Context;
5 | import android.content.Intent;
6 |
7 | class AuthorizeUtil {
8 |
9 | private static PendingIntent authorizePendingIntent = null;
10 |
11 | static PendingIntent getAuthorizedPI(Context context) {
12 | if (authorizePendingIntent == null) {
13 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
14 | authorizePendingIntent = PendingIntent.getActivity(context, 0x333, new Intent(context, StateReceiver.class), PendingIntent.FLAG_IMMUTABLE);
15 | } else {
16 | authorizePendingIntent = PendingIntent.getActivity(context, 0x333, new Intent(context, StateReceiver.class), PendingIntent.FLAG_ONE_SHOT);
17 | }
18 | }
19 | return authorizePendingIntent;
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/icebox/src/main/java/com/catchingnow/icebox/sdk_client/IceBox.java:
--------------------------------------------------------------------------------
1 | package com.catchingnow.icebox.sdk_client;
2 |
3 | import android.content.Context;
4 | import android.content.pm.ApplicationInfo;
5 | import android.content.pm.PackageManager;
6 | import android.net.Uri;
7 |
8 | import androidx.annotation.IntDef;
9 | import androidx.annotation.RequiresPermission;
10 | import androidx.annotation.WorkerThread;
11 |
12 | /**
13 | * IceBox SDK
14 | */
15 | public class IceBox {
16 |
17 | public static final String SDK_PERMISSION = "com.catchingnow.icebox.SDK";
18 |
19 | // 冰箱的包名
20 | public static final String PACKAGE_NAME = "com.catchingnow.icebox";
21 |
22 | // 最低支持 SDK 的冰箱 apk 版本号
23 | public static final int AVAILABLE_VERSION_CODE = 703;
24 |
25 | public enum WorkMode {
26 | MODE_PM_DISABLE_USER,
27 | MODE_PM_HIDE,
28 | MODE_NOT_AVAILABLE,
29 | }
30 |
31 | /**
32 | * 查询冰箱的工作模式
33 | *
34 | * 查询不需要权限
35 | *
36 | * @param context context
37 | * @return 如果是使用的 pm disable-user 模式,则返回 MODE_PM_DISABLE_USER,pm hide 则返回 MODE_PM_HIDE
38 | * 不可用则返回 MODE_NOT_AVAILABLE
39 | */
40 | public static WorkMode queryWorkMode(Context context) {
41 | return SdkImplement.queryWorkMode(context);
42 | }
43 |
44 | public static final int FLAG_PM_DISABLE_USER = 1;
45 | public static final int FLAG_PM_HIDE = 2;
46 |
47 | @IntDef(flag = true, value = {FLAG_PM_HIDE, FLAG_PM_DISABLE_USER})
48 | public @interface AppState {
49 | }
50 |
51 | /**
52 | * 查询一个 App 的冻结状态
53 | *
54 | * 查询不需要权限
55 | *
56 | * @param context context
57 | * @param packageName 包名
58 | * @return 一个 flag,状态可能为 0 (未冻结),1 (被 PM_DISABLE 冻结) 2(被 PM_HIDE冻结)或 3 (被冻了又冻)
59 | * @throws PackageManager.NameNotFoundException 未找到该 app
60 | */
61 | @AppState
62 | public static int getAppEnabledSetting(Context context, String packageName) throws PackageManager.NameNotFoundException {
63 | return SdkImplement.getAppEnabledSetting(context, packageName);
64 | }
65 |
66 | /**
67 | * 查询一个 App 的冻结状态
68 | *
69 | * 查询不需要权限
70 | *
71 | * @param applicationInfo applicationInfo
72 | * @return 一个 flag,状态可能为 0 (未冻结),1 (被 PM_DISABLE 冻结) 2(被 PM_HIDE冻结)或 3 (被冻了又冻)
73 | */
74 | @AppState
75 | public static int getAppEnabledSetting(ApplicationInfo applicationInfo) {
76 | return SdkImplement.getAppEnabledSetting(applicationInfo);
77 | }
78 |
79 | /**
80 | * 冻结解冻 App
81 | *
82 | * PS: 冰箱并不是所有的引擎都支持多用户,所以暂时禁用掉多用户功能。
83 | *
84 | * @param context context
85 | * @param packageNames 包名
86 | * @param enable true for 解冻,false for 冻结
87 | */
88 | @WorkerThread
89 | @RequiresPermission(SDK_PERMISSION)
90 | public static void setAppEnabledSettings(Context context, boolean enable, String... packageNames) {
91 | SdkImplement.setAppEnabledSettings(context, enable, packageNames);
92 | }
93 |
94 | public enum SilentInstallSupport {
95 | SUPPORTED,
96 | NOT_INSTALLED, //未安装冰箱 IceBox;
97 | UPDATE_REQUIRED, //冰箱 IceBox 版本过低;
98 | SYSTEM_NOT_SUPPORTED, //当前系统版本不支持静默安装;
99 | NOT_DEVICE_OWNER, //冰箱 IceBox 不是设备管理员;
100 | PERMISSION_REQUIRED, //当前 App 未取得权限;
101 |
102 | NOT_RUNNING //
103 | }
104 |
105 | /**
106 | * 查询当前冰箱是否支持静默安装
107 | * 仅设置为设备管理员的冰箱支持静默安装和卸载
108 | *
109 | * @param context context
110 | * @return 可能的枚举状态
111 | */
112 | public static SilentInstallSupport querySupportSilentInstall(Context context) {
113 | return SdkImplement.querySupportSilentInstall(context);
114 | }
115 |
116 | /**
117 | * 静默安装 APK
118 | *
119 | * @param context context
120 | * @param apkUri uri
121 | * @return 是否安装成功
122 | */
123 | @WorkerThread
124 | @RequiresPermission(SDK_PERMISSION)
125 | public static boolean installPackage(Context context, Uri apkUri) {
126 | return SdkImplement.installPackage(context, apkUri);
127 | }
128 |
129 | /**
130 | * 静默卸载 App
131 | *
132 | * @param context context
133 | * @param packageName 包名
134 | * @return 是否卸载成功
135 | */
136 | public static boolean uninstallPackage(Context context, String packageName) {
137 | return SdkImplement.uninstallPackage(context, packageName);
138 | }
139 |
140 | }
141 |
--------------------------------------------------------------------------------
/icebox/src/main/java/com/catchingnow/icebox/sdk_client/ResultReceiverUtil.java:
--------------------------------------------------------------------------------
1 | package com.catchingnow.icebox.sdk_client;
2 |
3 | import android.os.Parcel;
4 | import android.os.ResultReceiver;
5 |
6 | class ResultReceiverUtil {
7 |
8 | static ResultReceiver receiverForSending(ResultReceiver actualReceiver) {
9 | Parcel parcel = Parcel.obtain();
10 | actualReceiver.writeToParcel(parcel, 0);
11 | parcel.setDataPosition(0);
12 | ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel);
13 | parcel.recycle();
14 | return receiverForSending;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/icebox/src/main/java/com/catchingnow/icebox/sdk_client/StateReceiver.java:
--------------------------------------------------------------------------------
1 | package com.catchingnow.icebox.sdk_client;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 |
7 | public class StateReceiver extends BroadcastReceiver {
8 |
9 | @Override
10 | public void onReceive(Context context, Intent intent) {
11 | // 暂时不做操作,后续可能作为回调处理事件,请勿删除
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/icebox/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | sdk-client
3 |
4 |
--------------------------------------------------------------------------------
/screenshot/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/screenshot/1.jpg
--------------------------------------------------------------------------------
/screenshot/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/screenshot/2.jpg
--------------------------------------------------------------------------------
/screenshot/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/screenshot/3.jpg
--------------------------------------------------------------------------------
/screenshot/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/screenshot/4.jpg
--------------------------------------------------------------------------------
/screenshot/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/screenshot/5.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | maven { url 'https://maven.aliyun.com/repository/public/' }
4 | google()
5 | mavenCentral()
6 | gradlePluginPortal()
7 | }
8 | }
9 | dependencyResolutionManagement {
10 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
11 | repositories {
12 | google()
13 | mavenCentral()
14 | maven { url 'https://maven.aliyun.com/repository/jcenter' }
15 | maven { url 'https://jitpack.io' }
16 | maven { url 'https://dl.bintray.com/rikkaw/Shizuku' }
17 | }
18 | }
19 | rootProject.name = "ApkInstaller"
20 | include ':app', ':icebox'
21 |
--------------------------------------------------------------------------------
/sigenkey:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tokyonth/ApkInstaller/fb5b41ac57a1652a093d5dda1f02a514e3864690/sigenkey
--------------------------------------------------------------------------------