Compare commits

...

10 Commits

Author SHA1 Message Date
449fed287e feat: 适配Tab10CPro的5x5网格布局并优化对话框与上滑把手显示 2026-10-20 16:59:18 +08:00
7458216cbc feat(build): 添加G122J平台构建配置并适配平台逻辑 2026-10-15 14:34:27 +08:00
b3bf7c77f5 feat: 添加onyx设置重定向并禁用系统应用隐藏 2026-10-12 15:31:46 +08:00
d2c7fdd5a8 feat(ui): 添加壁纸设置与重置工具类 2026-09-24 10:49:25 +08:00
4eb0d65e8a feat: 集成Bugly崩溃上报并新增计算器禁用功能
- 在BaseApplication中初始化Bugly崩溃上报,设置设备型号和序列号
- 新增计算器应用禁用开关,默认禁止使用
- 调整相机和时钟禁用开关的默认值为禁止
- 升级版本号至1.6.0920(versionCode 211)
- build.gradle添加Bugly依赖

Conventional Commits格式的标题应简洁,现改为:

feat: 集成Bugly并新增计算器禁用功能
2026-09-23 15:26:03 +08:00
8e37bca0c3 fix(network): 修复重复请求拦截器去重失效问题
在请求发出前拦截重复请求,复用进行中请求的结果,
并在完成后保留 500ms 结果窗口;同时新增 DX11、G12NL
平台标识与构建变体,更新版本号至 1.6.0914。
2026-09-18 16:20:03 +08:00
151e488b6f feat(build): 添加DX11平台构建配置并更新版本号
- 新增DX11签名和Debug/Release构建类型
- 版本号升级至1.6.0731 (versionCode 206)
- 爱优读隐藏图标列表增加eswi系列包名
- 注释google()仓库改用maven.google.com
2026-09-04 09:18:10 +08:00
5d349abe65 fix: 使用多进程MMKV实例替代默认实例 2026-07-31 15:22:51 +08:00
8fee8d692c build: 修复第三方无法读取图标显示 2026-06-30 10:35:23 +08:00
da1efc3c32 build: add 6789u platform 2026-06-30 10:34:43 +08:00
38 changed files with 873 additions and 147 deletions

View File

@@ -84,7 +84,7 @@
android:fullBackupContent="@xml/backupscheme"
android:fullBackupOnly="true"
android:hardwareAccelerated="true"
android:icon="@drawable/ic_launcher_home"
android:icon="@mipmap/ic_launcher_home"
android:label="@string/derived_app_name"
android:largeHeap="@bool/config_largeHeap"
android:networkSecurityConfig="@xml/network"

View File

@@ -13,7 +13,7 @@
android:fullBackupContent="@xml/backupscheme"
android:fullBackupOnly="true"
android:hardwareAccelerated="true"
android:icon="@drawable/ic_launcher_home"
android:icon="@mipmap/ic_launcher_home"
android:label="@string/derived_app_name"
android:largeHeap="@bool/config_largeHeap"
android:restoreAnyVersion="true"

View File

@@ -75,8 +75,8 @@ android {
minSdkVersion 26
targetSdkVersion 28
versionCode 203
versionName "1.6.0526"
versionCode 216
versionName "1.6.1016"
ndk {
//选择要添加的对应 cpu 类型的 .so 库。
@@ -159,6 +159,15 @@ android {
v2SigningEnabled true
}
iPlay50miniPro {
storeFile file("keystore/iPlay50miniPro.jks")
storePassword "123456"
keyAlias "iplay50minipro"
keyPassword "123456"
v1SigningEnabled true
v2SigningEnabled true
}
G10P {
storeFile file("keystore/G10PMTK11.jks")
storePassword "123456"
@@ -239,27 +248,127 @@ android {
v2SigningEnabled true
}
G122 {
storeFile file("keystore/6789U.p12")
storePassword "123456"
keyAlias "6789u"
keyPassword "123456"
v1SigningEnabled true
v2SigningEnabled true
}
DX11 {
storeFile file("keystore/DX11.p12")
storePassword "123456"
keyAlias "dx11"
keyPassword "123456"
v1SigningEnabled true
v2SigningEnabled true
}
MT6789 {
storeFile file("keystore/MT6789.keystore")
storePassword "123456"
keyAlias "mt6789"
keyPassword "123456"
v1SigningEnabled true
v2SigningEnabled true
}
SM8150 {
storeFile file("keystore/sm8150.jks")
storePassword "logan-123456789"
keyAlias "platformkey"
keyPassword "logan-123456789"
v1SigningEnabled true
v2SigningEnabled true
}
G122J {
storeFile file("keystore/G122J.p12")
storePassword "123456"
keyAlias "g122j"
keyPassword "123456"
v1SigningEnabled true
v2SigningEnabled true
}
}
buildTypes {
G122JDebug.initWith(debug)
G122JDebug {
buildConfigField "String", "platform", '"G122J"'
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.G122J
}
G122JRelease.initWith(release)
G122JRelease {
buildConfigField "String", "platform", '"G122J"'
signingConfig signingConfigs.G122J
}
G12NLDebug.initWith(debug)
G12NLDebug {
buildConfigField "String", "platform", '"G12NL"'
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.MT6789
}
G12NLRelease.initWith(release)
G12NLRelease {
buildConfigField "String", "platform", '"G12NL"'
signingConfig signingConfigs.MT6789
}
DX11Debug.initWith(debug)
DX11Debug {
buildConfigField "String", "platform", '"DX11"'
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.DX11
}
DX11Release.initWith(release)
DX11Release {
buildConfigField "String", "platform", '"DX11"'
signingConfig signingConfigs.DX11
}
G122Debug.initWith(debug)
G122Debug {
buildConfigField "String", "platform", '"MT6765"'
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.G122
}
G122Release.initWith(release)
G122Release {
buildConfigField "String", "platform", '"MT6765"'
signingConfig signingConfigs.G122
}
QualcommDebug.initWith(debug)
QualcommDebug {
buildConfigField "String", "platform", '"QualcommA"'
versionNameSuffix "-debug"
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.zhanRui
signingConfig signingConfigs.SM8150
}
QualcommRelease.initWith(release)
QualcommRelease {
buildConfigField "String", "platform", '"QualcommA"'
signingConfig signingConfigs.zhanRui
signingConfig signingConfigs.SM8150
}
G128TDebug.initWith(debug)
G128TDebug {
buildConfigField "String", "platform", '"G128T"'
versionNameSuffix "-debug"
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.G128T
}
@@ -273,7 +382,7 @@ android {
QZ15Debug.initWith(debug)
QZ15Debug {
buildConfigField "String", "platform", '"QZA15"'
versionNameSuffix "-debug"
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.U1302
}
@@ -283,10 +392,10 @@ android {
buildConfigField "String", "platform", '"QZA15"'
signingConfig signingConfigs.U1302
}
seewoDebug.initWith(debug)
seewoDebug {
versionNameSuffix "-debug"
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.seewo
buildConfigField "String", "platform", '"seewo"'
@@ -300,7 +409,7 @@ android {
P50Debug.initWith(debug)
P50Debug {
versionNameSuffix "-debug"
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.P50
buildConfigField "String", "platform", '"P50TD"'
@@ -314,7 +423,7 @@ android {
T40AirDebug.initWith(debug)
T40AirDebug {
versionNameSuffix "-debug"
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.T40Air
buildConfigField "String", "platform", '"HL500"'
@@ -328,7 +437,7 @@ android {
// AiUduDebug.initWith(debug)
// AiUduDebug {
// versionNameSuffix "-debug"
// versionNameSuffix "_debug"
// debuggable true
// signingConfig signingConfigs.G10P
// buildConfigField "String", "platform", '"AUDG104"'
@@ -339,10 +448,10 @@ android {
// signingConfig signingConfigs.G10P
// buildConfigField "String", "platform", '"AUDG104"'
// }
Huaruian8768Debug.initWith(debug)
Huaruian8768Debug {
versionNameSuffix "-debug"
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.Huaruian8768
buildConfigField "String", "platform", '"MT8768"'
@@ -356,7 +465,7 @@ android {
G11Debug.initWith(debug)
G11Debug {
versionNameSuffix "-debug"
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.G11Userdebug
buildConfigField "String", "platform", '"MTKG11"'
@@ -370,7 +479,7 @@ android {
YXPD1Debug.initWith(debug)
YXPD1Debug {
versionNameSuffix "-debug"
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.G10P
buildConfigField "String", "platform", '"YXPD1"'
@@ -384,7 +493,7 @@ android {
c2Debug.initWith(debug)
c2Debug {
versionNameSuffix "-debug"
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.teclast8183
buildConfigField "String", "platform", '"MTK8183"'
@@ -398,7 +507,7 @@ android {
G10PDebug.initWith(debug)
G10PDebug {
versionNameSuffix "-debug"
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.G10P
buildConfigField "String", "platform", '"G10P"'
@@ -413,7 +522,7 @@ android {
G104Debug.initWith(debug)
G104Debug {
buildConfigField "String", "platform", '"MTK11"'
versionNameSuffix "-debug"
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.G10P
}
@@ -424,9 +533,23 @@ android {
signingConfig signingConfigs.G10P
}
iPlay50miniProDebug.initWith(debug)
iPlay50miniProDebug {
buildConfigField "String", "platform", '"miniG99"'
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.iPlay50miniPro
}
iPlay50miniProRelease.initWith(release)
iPlay50miniProRelease {
buildConfigField "String", "platform", '"miniG99"'
signingConfig signingConfigs.iPlay50miniPro
}
zhanRuiDebug.initWith(debug)
zhanRuiDebug {
versionNameSuffix "-debug"
versionNameSuffix "_debug"
buildConfigField "String", "platform", '"ZhanRui"'
debuggable true
signingConfig signingConfigs.zhanRui
@@ -441,7 +564,7 @@ android {
//userdebug rom使用这个版本
zhanRuiUserdebug.initWith(zhanRuiDebug)
zhanRuiUserdebug {
versionNameSuffix "-debug"
versionNameSuffix "_debug"
buildConfigField "String", "platform", '"ZhanRui"'
debuggable true
signingConfig signingConfigs.zhanRuiUserdebug
@@ -449,7 +572,7 @@ android {
zhanRui12Debug.initWith(debug)
zhanRui12Debug {
versionNameSuffix "-debug"
versionNameSuffix "_debug"
buildConfigField "String", "platform", '"AH6016"'
debuggable true
signingConfig signingConfigs.zhanRui12
@@ -464,7 +587,7 @@ android {
TeclastP20SDebug.initWith(debug)
TeclastP20SDebug {
debuggable true
versionNameSuffix "-debug"
versionNameSuffix "_debug"
buildConfigField "String", "platform", '"P20S"'
signingConfig signingConfigs.TeclastP20S
}
@@ -478,7 +601,7 @@ android {
zhanruiG10ZDebug.initWith(debug)
zhanruiG10ZDebug {
buildConfigField "String", "platform", '"ZR6016"'
versionNameSuffix "-debug"
versionNameSuffix "_debug"
debuggable true
signingConfig signingConfigs.zhanruiG10Z
}
@@ -492,7 +615,7 @@ android {
debug {
buildConfigField "String", "platform", '"MTK"'
debuggable true
versionNameSuffix "-debug"
versionNameSuffix "_debug"
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.mtk
@@ -631,7 +754,7 @@ repositories {
maven { url "../../../prebuilts/fullsdk-darwin/extras/android/m2repository" }
maven { url "../../../prebuilts/fullsdk-linux/extras/android/m2repository" }
google()
// google()
mavenCentral()
maven { url 'https://jitpack.io' }
maven { url 'https://maven.google.com' }
@@ -686,6 +809,8 @@ dependencies {
implementation 'com.jakewharton:disklrucache:2.0.2'
//mmkv
implementation 'com.tencent:mmkv-static:2.4.0'
//bugly
implementation 'com.tencent.bugly:crashreport:4.1.9.2'
// //腾讯移动推送 TPNS
// implementation 'com.tencent.tpns:tpns:1.3.2.0-release'
// //阿里云推送

View File

@@ -29,7 +29,7 @@
android:fullBackupOnly="true"
android:fullBackupContent="@xml/backupscheme"
android:hardwareAccelerated="true"
android:icon="@drawable/ic_launcher_home"
android:icon="@mipmap/ic_launcher_home"
android:label="@string/derived_app_name"
android:theme="@style/AppTheme"
android:largeHeap="@bool/config_largeHeap"

View File

@@ -15,6 +15,16 @@ android {
}
buildTypes {
G122JDebug {}
G122JRelease {}
MX11Debug {}
MX11Release {}
G12NLDebug {}
G12NLRelease {}
DX11Debug {}
DX11Release {}
G122Debug {}
G122Release {}
QualcommDebug {}
QualcommRelease {}
G128TDebug {}
@@ -39,6 +49,8 @@ android {
c2Release {}
G104Debug {}
G104Release {}
iPlay50miniProDebug {}
iPlay50miniProRelease {}
G10PDebug {}
G10PRelease {}
zhanRuiDebug {}

BIN
keystore/6789U.p12 Normal file

Binary file not shown.

BIN
keystore/DX11.p12 Normal file

Binary file not shown.

BIN
keystore/G122J.p12 Normal file

Binary file not shown.

BIN
keystore/MT6789.keystore Normal file

Binary file not shown.

BIN
keystore/iPlay50miniPro.jks Normal file

Binary file not shown.

BIN
keystore/sm8150.jks Normal file

Binary file not shown.

View File

@@ -29,7 +29,7 @@
android:fullBackupOnly="true"
android:fullBackupContent="@xml/backupscheme"
android:hardwareAccelerated="true"
android:icon="@drawable/ic_launcher_home"
android:icon="@mipmap/ic_launcher_home"
android:label="@string/derived_app_name"
android:theme="@style/AppTheme"
android:largeHeap="@bool/config_largeHeap"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -2,8 +2,8 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ffffff" />
<stroke
android:width="0.8dp"
android:color="#ffffff" />
android:width="1dp"
android:color="#000000" />
<!-- 圆角 -->
<corners android:radius="6dp" />
</shape>

View File

@@ -53,6 +53,17 @@
tools:text="请输入密码" />
</LinearLayout>
<ImageView
android:id="@+id/iv_close"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_alignParentEnd="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="4dp"
android:layout_marginEnd="12dp"
android:src="@drawable/icon_close" />
<EditText
android:id="@+id/message"
android:layout_width="match_parent"

View File

@@ -20,7 +20,7 @@
<widget
android:label="My custom widget"
android:initialLayout="@layout/sample_widget_layout"
android:icon="@drawable/ic_launcher_home"
android:icon="@mipmap/ic_launcher_home"
android:resizeMode="horizontal|vertical"
launcher:numRows="2"
launcher:numColumns="3"

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2009 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Tab10CPro_GK exclusive 5x5 layout (5 columns / 5 rows, 5 hotseat icons) -->
<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.uiuios">
<!-- Hotseat (screen 0..4 for 5x5, without com.aoleyun.info) -->
<favorite
launcher:className="com.aoleyun.sn.activity.SplashActivity"
launcher:container="-101"
launcher:packageName="com.aoleyun.sn"
launcher:screen="0"
launcher:x="0"
launcher:y="0" />
<favorite
launcher:className="com.aoleyun.appstore.activity.SplashActivity"
launcher:container="-101"
launcher:packageName="com.aoleyun.appstore"
launcher:screen="1"
launcher:x="1"
launcher:y="0" />
<favorite
launcher:className="com.android.settings.Settings"
launcher:container="-101"
launcher:packageName="com.android.settings"
launcher:screen="2"
launcher:x="2"
launcher:y="0" />
<favorite
launcher:className="com.aoleyun.browser.activity.main.MainActivity"
launcher:container="-101"
launcher:packageName="com.aoleyun.browser"
launcher:screen="3"
launcher:x="3"
launcher:y="0" />
<favorite
launcher:className="com.aoleyun.sn.activity.EyeProtectionActivity"
launcher:container="-101"
launcher:packageName="com.aoleyun.sn"
launcher:screen="4"
launcher:x="4"
launcher:y="0" />
</favorites>

View File

@@ -176,4 +176,24 @@
</grid-option>
<!-- Tab10CPro_GK (1860x2480, density 300) exclusive 5x5 profile with larger icons -->
<grid-option
launcher:name="tab10cpro_5x5"
launcher:numRows="5"
launcher:numColumns="5"
launcher:numFolderRows="4"
launcher:numFolderColumns="4"
launcher:numHotseatIcons="5"
launcher:defaultLayoutId="@xml/default_workspace_tab10cpro_5x5" >
<display-option
launcher:name="Tab10CPro 5x5"
launcher:minWidthDps="992"
launcher:minHeightDps="1323"
launcher:iconImageSize="100"
launcher:iconTextSize="15.0"
launcher:canBeDefault="true" />
</grid-option>
</profiles>

View File

@@ -224,19 +224,6 @@ public class DeviceProfile {
updateAvailableDimensions(dm, res);
// Now that we have all of the variables calculated, we can tune certain sizes.
if (!isVerticalBarLayout() && isPhone && isTallDevice) {
// We increase the hotseat size when there is extra space.
// ie. For a display with a large aspect ratio, we can keep the icons on the workspace
// in portrait mode closer together by adding more height to the hotseat.
// Note: This calculation was created after noticing a pattern in the design spec.
int extraSpace = getCellSize().y - iconSizePx - iconDrawablePaddingPx * 2
- verticalDragHandleSizePx;
hotseatBarSizePx += extraSpace;
hotseatBarBottomPaddingPx += extraSpace;
// Recalculate the available dimensions using the new hotseat size.
updateAvailableDimensions(dm, res);
}
updateWorkspacePadding();
// This is done last, after iconSizePx is calculated above.
@@ -473,11 +460,8 @@ public class DeviceProfile {
((inv.numColumns - 1) * cellWidthPx)));
availablePaddingX = (int) Math.min(availablePaddingX,
widthPx * MAX_HORIZONTAL_PADDING_PERCENT);
int availablePaddingY = Math.max(0, heightPx - edgeMarginPx - paddingBottom
- (2 * inv.numRows * cellHeightPx) - hotseatBarTopPaddingPx
- hotseatBarBottomPaddingPx);
padding.set(availablePaddingX / 2, edgeMarginPx + availablePaddingY / 2,
availablePaddingX / 2, paddingBottom + availablePaddingY / 2);
padding.set(availablePaddingX / 2, edgeMarginPx,
availablePaddingX / 2, paddingBottom);
} else {
// Pad the top and bottom of the workspace with search/hotseat bar sizes
padding.set(desiredWorkspaceLeftRightMarginPx,

View File

@@ -24,6 +24,9 @@ import android.annotation.TargetApi;
import android.appwidget.AppWidgetHostView;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
@@ -56,7 +59,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
@@ -69,6 +71,7 @@ public class InvariantDeviceProfile {
new MainThreadInitializedObject<>(InvariantDeviceProfile::new);
private static final String KEY_IDP_GRID_NAME = "idp_grid_name";
private static final String KEY_LAST_VERSION = "idp_last_version";
private static final float ICON_SIZE_DEFINED_IN_APP_DP = 48;
@@ -127,7 +130,8 @@ public class InvariantDeviceProfile {
private OverlayMonitor mOverlayMonitor;
@VisibleForTesting
public InvariantDeviceProfile() {}
public InvariantDeviceProfile() {
}
private InvariantDeviceProfile(InvariantDeviceProfile p) {
numRows = p.numRows;
@@ -147,6 +151,9 @@ public class InvariantDeviceProfile {
@TargetApi(23)
private InvariantDeviceProfile(Context context) {
// On app upgrade, drop the previously saved grid for Tab10CPro_GK so the dedicated
// 5x5 profile (icon size / grid / default layout) is re-selected.
maybeResetGridOnUpgrade(context);
initGrid(context, Utilities.getPrefs(context).getString(KEY_IDP_GRID_NAME, null));
mConfigMonitor = new ConfigMonitor(context,
APPLY_CONFIG_AT_RUNTIME.get() ? this::onConfigChanged : this::killProcess);
@@ -163,6 +170,41 @@ public class InvariantDeviceProfile {
}
}
/**
* When the app's versionCode is raised, clear the previously saved grid name for
* Tab10CPro_GK so that {@link #initGrid} re-selects the dedicated 5x5 profile
* (icon size / grid / default layout) instead of keeping a stale saved configuration.
* A same-version reinstall does NOT trigger a reset. Other models are unaffected.
*/
private static void maybeResetGridOnUpgrade(Context context) {
if (!"Tab10CPro_GK".equals(Build.MODEL)) {
return;
}
SharedPreferences prefs = Utilities.getPrefs(context);
long currentVersion = getCurrentVersionCode(context);
long lastVersion = prefs.getLong(KEY_LAST_VERSION, -1);
if (lastVersion != -1 && lastVersion < currentVersion) {
Log.e(TAG, "maybeResetGridOnUpgrade: version raised " + lastVersion
+ " -> " + currentVersion + ", reset saved grid: "
+ prefs.getString(KEY_IDP_GRID_NAME, null));
prefs.edit().remove(KEY_IDP_GRID_NAME).apply();
}
prefs.edit().putLong(KEY_LAST_VERSION, currentVersion).apply();
}
private static long getCurrentVersionCode(Context context) {
try {
PackageInfo info = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
return info.getLongVersionCode();
}
return info.versionCode;
} catch (PackageManager.NameNotFoundException e) {
return -1;
}
}
/**
* Retrieve system defined or RRO overriden icon shape.
*/
@@ -185,8 +227,8 @@ public class InvariantDeviceProfile {
display.getCurrentSizeRange(smallestSize, largestSize);
ArrayList<DisplayOption> allOptions = getPredefinedDeviceProfiles(context, gridName);
for (DisplayOption displayOption:allOptions){
Log.e(TAG, "initGrid: "+displayOption.grid.name);
for (DisplayOption displayOption : allOptions) {
Log.e(TAG, "initGrid: " + displayOption.grid.name);
}
// This guarantees that width < height
float minWidthDps = Utilities.dpiFromPx(Math.min(smallestSize.x, smallestSize.y), dm);
@@ -196,18 +238,35 @@ public class InvariantDeviceProfile {
Float.compare(dist(minWidthDps, minHeightDps, a.minWidthDps, a.minHeightDps),
dist(minWidthDps, minHeightDps, b.minWidthDps, b.minHeightDps)));
DisplayOption interpolatedDisplayOption =
invDistWeightedInterpolate(minWidthDps, minHeightDps, allOptions);
GridOption closestProfile;
if ("Aiud_A8_ag_1095".equals(Build.MODEL)) {
closestProfile = allOptions.stream().filter(new Predicate<DisplayOption>() {
@Override
public boolean test(DisplayOption displayOption) {
return "aiudu".equals(displayOption.grid.name);
}
}).collect(Collectors.toList()).get(0).grid;
}else {
closestProfile = allOptions.get(0).grid;
}
invDistWeightedInterpolate(minWidthDps, minHeightDps, allOptions);
GridOption closestProfile = allOptions.stream()
.filter(new Predicate<DisplayOption>() {
@Override
public boolean test(DisplayOption displayOption) {
if ("Aiud_A8_ag_1095".equals(Build.MODEL)) {
return "aiudu".equals(displayOption.grid.name);
} else if ("Tab10CPro_GK".equals(Build.MODEL)) {
// Tab10CPro_GK (1860x2480, density 300) exclusive 5x5 profile
return "tab10cpro_5x5".equals(displayOption.grid.name);
}
return false;
}
})
.map(new java.util.function.Function<DisplayOption, GridOption>() {
@Override
public GridOption apply(DisplayOption displayOption) {
return displayOption.grid;
}
})
.findFirst()
.orElse(allOptions.get(0).grid);
Log.e(TAG, "initGrid: deviceModel=" + Build.MODEL
+ ", minWidthDps=" + minWidthDps + ", minHeightDps=" + minHeightDps
+ ", selectedGrid=" + closestProfile.name
+ ", numRows=" + closestProfile.numRows
+ ", numColumns=" + closestProfile.numColumns
+ ", numHotseatIcons=" + closestProfile.numHotseatIcons
+ ", defaultLayoutId=" + closestProfile.defaultLayoutId);
numRows = closestProfile.numRows;
numColumns = closestProfile.numColumns;
numHotseatIcons = closestProfile.numHotseatIcons;
@@ -360,7 +419,7 @@ public class InvariantDeviceProfile {
}
}
}
} catch (IOException|XmlPullParserException e) {
} catch (IOException | XmlPullParserException e) {
throw new RuntimeException(e);
}
@@ -388,7 +447,7 @@ public class InvariantDeviceProfile {
private int getLauncherIconDensity(int requiredSize) {
// Densities typically defined by an app.
int[] densityBuckets = new int[] {
int[] densityBuckets = new int[]{
DisplayMetrics.DENSITY_LOW,
DisplayMetrics.DENSITY_MEDIUM,
DisplayMetrics.DENSITY_TV,
@@ -412,7 +471,7 @@ public class InvariantDeviceProfile {
/**
* Apply any Partner customization grid overrides.
*
* <p>
* Currently we support: all apps row / column count.
*/
private void applyPartnerDeviceProfileOverrides(Context context, DisplayMetrics dm) {
@@ -428,7 +487,7 @@ public class InvariantDeviceProfile {
@VisibleForTesting
static DisplayOption invDistWeightedInterpolate(float width, float height,
ArrayList<DisplayOption> points) {
ArrayList<DisplayOption> points) {
float weights = 0;
DisplayOption p = points.get(0);
@@ -471,8 +530,8 @@ public class InvariantDeviceProfile {
// We will use these two data points to extrapolate how much the wallpaper parallax effect
// to span (ie travel) at any aspect ratio:
final float ASPECT_RATIO_LANDSCAPE = 16/10f;
final float ASPECT_RATIO_PORTRAIT = 10/16f;
final float ASPECT_RATIO_LANDSCAPE = 16 / 10f;
final float ASPECT_RATIO_PORTRAIT = 10 / 16f;
final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE = 1.5f;
final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT = 1.2f;

View File

@@ -47,6 +47,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Parcelable;
import android.os.Process;
import android.os.StrictMode;
@@ -78,6 +79,7 @@ import com.aoleyun.os.allapps.AllAppsStore;
import com.aoleyun.os.allapps.AllAppsTransitionController;
import com.aoleyun.os.allapps.DiscoveryBounce;
import com.aoleyun.os.anim.PropertyListBuilder;
import com.aoleyun.os.comm.CommonConfig;
import com.aoleyun.os.compat.AppWidgetManagerCompat;
import com.aoleyun.os.compat.LauncherAppsCompatVO;
import com.aoleyun.os.config.FeatureFlags;
@@ -153,6 +155,7 @@ import com.aoleyun.os.widget.custom.CustomWidgetParser;
import com.arialyy.aria.core.Aria;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.tencent.bugly.crashreport.CrashReport;
import com.tencent.mmkv.MMKV;
import java.io.File;
@@ -203,6 +206,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
public static final String TAG = "Launcher";
static final boolean LOGD = false;
private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
static final boolean DEBUG_STRICT_MODE = false;
private static final int REQUEST_CREATE_SHORTCUT = 1;
@@ -480,10 +485,12 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
try {
if ("Aiud_A8_ag_1095".equals(Build.MODEL)
||JgyUtils.getInstance().checkAppPlatform() == JgyUtils.seewoPlatform
|| JgyUtils.getInstance().checkAppPlatform() == JgyUtils.seewoPlatform
) {
wallpaperManager.setBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.wallpapers_aiudu));
}else {
} else if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.QualcommPlatform) {
// wallpaperManager.clear();
} else {
wallpaperManager.setBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.wallpapers));
}
} catch (IOException e) {
@@ -1243,10 +1250,10 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
}
private void removeRecentTask() {
Handler.getMain().postDelayed(new Runnable() {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
String ApplicationLock = MMKV.defaultMMKV().decodeString("ApplicationLock");
String ApplicationLock = mMMKV.decodeString("ApplicationLock");
Type type = new TypeToken<List<AppPasswdBean>>() {
}.getType();
Gson gson = new Gson();

View File

@@ -1,14 +1,17 @@
package com.aoleyun.os.base;
import android.app.Application;
import android.os.Build;
import android.util.Log;
import com.aoleyun.os.manager.ConnectManager;
import com.aoleyun.os.network.NetInterfaceManager;
import com.aoleyun.os.uiuiutils.JgyUtils;
import com.aoleyun.os.uiuiutils.TimeUtils;
import com.aoleyun.os.uiuiutils.Utils;
import com.arialyy.aria.core.Aria;
import com.hjq.toast.Toaster;
import com.tencent.bugly.crashreport.CrashReport;
import com.tencent.mmkv.MMKV;
public class BaseApplication extends Application {
@@ -20,6 +23,10 @@ public class BaseApplication extends Application {
String rootDir = MMKV.initialize(this);
Log.e(TAG, "onCreate: " + rootDir);
CrashReport.initCrashReport(getApplicationContext(), "6c94f946fe", false);
CrashReport.setDeviceModel(this, Build.MODEL);
CrashReport.setDeviceId(this, Utils.getSerial(this));
JgyUtils.init(this);
TimeUtils.init(this);
Aria.init(this);

View File

@@ -6,6 +6,7 @@ import android.graphics.drawable.Drawable;
import android.os.Environment;
import android.util.Log;
import com.aoleyun.os.comm.CommonConfig;
import com.jakewharton.disklrucache.DiskLruCache;
import com.tencent.mmkv.MMKV;
@@ -30,7 +31,7 @@ import java.io.Serializable;
public class CacheHelper {
private static final String TAG = "DiskLruCacheHelper";
private MMKV mMMKV = MMKV.defaultMMKV();
private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
private static final String DIR_NAME = "diskCache";
private static final int MAX_COUNT = 5 * 1024 * 1024;

View File

@@ -114,7 +114,7 @@ public class IconCache extends BaseIconCache {
false /*replace existing*/);
}
} catch (NameNotFoundException e) {
Log.d(TAG, "Package not found", e);
Log.d(TAG, "Package not found: " + packageName);
}
}
@@ -233,16 +233,20 @@ public class IconCache extends BaseIconCache {
private List<String> appClassNameList = new ArrayList<String>() {{
this.add("com.android.calculator2.Calculator");//计算器
this.add("com.onyx.calculator.Calculator");//计算器
this.add("com.android.calendar.AllInOneActivity");//日历
this.add("com.onyx.mail.calendar.ui.CalendarActivity");//日历
this.add("com.android.camera.CameraLauncher");//相机
this.add("com.mediatek.camera.CameraLauncher");//相机
this.add("com.android.contacts.activities.PeopleActivity");//通讯录
this.add("com.android.deskclock.DeskClock");//时钟
this.add("com.simplemobiletools.clock.activities.SplashActivity");//时钟
this.add("com.android.dialer.DialtactsActivity");//电话
this.add("com.android.dialer.app.DialtactsActivity");//电话
this.add("com.android.dialer.main.impl.MainActivity");//电话
this.add("com.android.gallery3d.v2.app.GalleryActivity2");//图库
this.add("com.android.gallery3d.app.GalleryActivity");//图库
this.add("com.onyx.gallery.activities.NewMainActivity");//图库
this.add("com.android.messaging.ui.conversationlist.ConversationListActivity");//信息
this.add("com.android.mms.ui.BootActivity");//信息
this.add("com.android.music.MusicBrowserActivity");//音乐
@@ -262,20 +266,28 @@ public class IconCache extends BaseIconCache {
this.add("com.aoleyun.sn.activity.EyeProtectionActivity");//护眼模式
this.add("com.aoleyun.sn.activity.CleanupActivity");//一键加速
this.add("com.aoleyun.sn.activity.update.UpdateActivity");//检查更新
this.add("com.onyx.easytransfer.main.MainActivity");//互传
this.add("com.onyx.easytransfer.wechat.ui.WeChatDropActivity");//微信互传
this.add("com.onyx.floatingbutton.FloatButtonSettingActivity");//互传
}};
private List<String> appIconList = new ArrayList<String>() {{
this.add("com_android_calculator2");
this.add("com_android_calculator2");
this.add("com_android_calendar");
this.add("com_android_calendar");
this.add("com_android_camera");
this.add("com_android_camera");
this.add("com_android_contacts");
this.add("com_android_deskclock");
this.add("com_android_deskclock");
this.add("com_android_dialer");
this.add("com_android_dialer");
this.add("com_android_dialer");
this.add("com_android_gallery3d_app");
this.add("com_android_gallery3d_app");
this.add("com_android_gallery3d_app");
this.add("com_android_mms_ui");
this.add("com_android_mms_ui");
this.add("com_android_music");
@@ -295,6 +307,9 @@ public class IconCache extends BaseIconCache {
this.add("com_system_huyan");
this.add("com_system_clean");
this.add("com_aoleyun_update");
this.add("com_onyx_easytransfer");
this.add("com_onyx_easytransfer_wechat");
this.add("com_onyx_floatingbutton");
}};
public Drawable getFullResIcon(LauncherActivityInfo info) {

View File

@@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.util.Log;
import com.aoleyun.os.comm.CommonConfig;
import com.aoleyun.os.uiuiutils.TimeUtils;
import com.tencent.mmkv.MMKV;
@@ -33,7 +34,7 @@ public class ConnectManager {
@SuppressLint("StaticFieldLeak")
private static ConnectManager sInstance;
private Context mContext;
private MMKV mMMKV = MMKV.defaultMMKV();
private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
private ConnectManager(Context context) {
if (context == null) {

View File

@@ -267,6 +267,11 @@ public class LoaderTask implements Runnable {
this.add("com.elink.autotest");
this.add("com.emdoor.pressure.tester");
this.add("emdoor.digit.tester");
this.add("com.eswi.android.expand");
this.add("com.eswi.errorscollection");
this.add("com.eswi.homework");
this.add("com.eswi.learnpackage");
}};
/*爱优读需要隐藏的图标*/
@@ -356,6 +361,7 @@ public class LoaderTask implements Runnable {
this.add("com.ss.android.ugc.aweme");
this.add("com.tencent.mm");
this.add("com.google.android.inputmethod.pinyin");
this.add("com.onyx");
}};
@@ -556,6 +562,11 @@ public class LoaderTask implements Runnable {
ComponentName cn = intent.getComponent();
targetPkg = cn == null ? intent.getPackage() : cn.getPackageName();
if (!TextUtils.isEmpty(targetPkg) && SYSTEM_HIDE_APP.contains(targetPkg)) {
c.markDeleted("System hide app removed: " + targetPkg);
continue;
}
if (allUsers.indexOfValue(c.user) < 0) {
if (c.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
c.markDeleted("Legacy shortcuts are only allowed for current users");

View File

@@ -5,6 +5,7 @@ import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import com.aoleyun.os.comm.CommonConfig;
import com.aoleyun.os.disklrucache.CacheHelper;
import com.aoleyun.os.manager.ConnectManager;
import com.aoleyun.os.manager.ConnectMode;
@@ -54,7 +55,7 @@ public class NetInterfaceManager {
private Context mContext;
private Retrofit mRetrofit;
private OkHttpClient okHttpClient;
private MMKV mMMKV = MMKV.defaultMMKV();
private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
private CacheHelper cacheHelper;
//超时时间
@@ -207,6 +208,14 @@ public class NetInterfaceManager {
set.add(JgyUtils.AUDG104Tag);
} else if (platform == JgyUtils.seewoPlatform) {
set.add(JgyUtils.seewoTag);
} else if (platform == JgyUtils.QualcommPlatform) {
set.add(JgyUtils.Qualcomm_TAG);
} else if (platform == JgyUtils.DX11Platform) {
set.add(JgyUtils.DX11_TAG);
} else if (platform == JgyUtils.G12NLPlatform) {
set.add(JgyUtils.G12NL_TAG);
} else if (platform == JgyUtils.G122JPlatform) {
set.add(JgyUtils.G122J_TAG);
}
}
});
@@ -267,10 +276,10 @@ public class NetInterfaceManager {
if (listBaseResponse.code == 200) {
List<AppPasswdBean> beanList = listBaseResponse.data;
String jsonString = JsonParser.parseString(new Gson().toJson(beanList)).getAsJsonArray().toString();
MMKV.defaultMMKV().encode("ApplicationLock", jsonString);
mMMKV.encode("ApplicationLock", jsonString);
Log.e("getAppPasswd", "onNext: " + jsonString);
} else {
MMKV.defaultMMKV().encode("ApplicationLock", "");
mMMKV.remove("ApplicationLock");
}
}

View File

@@ -8,9 +8,13 @@ import com.aoleyun.os.uiuiutils.MD5Util;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.RequestBody;
@@ -19,89 +23,292 @@ import okhttp3.ResponseBody;
import okio.Buffer;
/**
* v1.0 2022-07-15 16:16:52
* 重复请求拦截器。
*
* <p>原实现是在 {@code chain.proceed()} 之后才判断是否为重复请求,此时请求早已发到服务器,
* 只能丢弃返回结果,所以服务端依然会收到两次(甚至多次)请求;并且记录在 finally 中立即删除,
* 去重窗口几乎为零,重复请求根本拦不住。</p>
*
* <p>优化后的策略:</p>
* <ul>
* <li>发请求之前先判断是否已经有相同请求:有则等待它的结果并复用,不再访问服务器;</li>
* <li>请求完成后在 {@link #REUSE_WINDOW_MS} 内保留结果,短时间内相同的请求直接复用结果;</li>
* <li>复用时使用真实的状态码、响应头和响应体,调用方无感知(原来的空 {@link Response} 会让
* 解析层直接抛异常);</li>
* <li>无响应体或响应体过大(超过 {@link #MAX_DEDUP_BODY_BYTES})的请求不参与去重,直接透传,
* 避免占用大量内存。</li>
* </ul>
*
* <p>v1.0 2022-07-15 16:16:52</p>
*/
public class RepeatRequestInterceptor implements Interceptor {
private static final String TAG = RepeatRequestInterceptor.class.getSimpleName();
private static final String TAG = "RepeatRequestInterceptor";
private final ConcurrentHashMap<String, Long> requestIdsMap = new ConcurrentHashMap<>();
public static final String REPEAT_REQUEST_PROTOCOL = "OKHTTP_REPEAT_REQUEST_PROTOCOL";
/**
* 等待进行中请求返回结果的最长时间,超时后本次请求自己访问服务器。
* 需要大于 OkHttpClient 的超时时间(当前为 5 秒)。
*/
private static final long WAIT_IN_FLIGHT_TIMEOUT_MS = 10_000L;
/**
* 请求完成后结果保留的时间。在该时间内收到相同请求,直接复用结果,不再访问服务器。
* 需要小于业务侧的刷新间隔(ConnectMode 最小为 1 分钟)。
*/
private static final long REUSE_WINDOW_MS = 500L;
/** 超过该大小的响应体不参与去重(直接透传),避免内存占用 */
private static final long MAX_DEDUP_BODY_BYTES = 1024 * 1024L;
/** 参与去重 key 计算的请求体最大字节数 */
private static final int MAX_BODY_BYTES_FOR_KEY = 8 * 1024;
/** 日志中请求体、响应体的最大长度 */
private static final int MAX_LOG_BODY_LENGTH = 10240;
private final ConcurrentHashMap<String, RepeatRecord> recordMap = new ConcurrentHashMap<>();
@NotNull
@Override
public Response intercept(@NotNull Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
ResponseBody responseBody = response.body();
String bodyText = requestBodyToString(request.body());
String requestKey = buildRequestKey(request, bodyText);
//会消费请求,导致请求多次
String content = responseBody.string();
// Response copy = response.newBuilder().body(responseBody).build();
ResponseBody copy = ResponseBody.create(responseBody.contentType(), content);
if (BuildConfig.DEBUG) {
Log.e(TAG, "请求体返回:| Response: " + request.url().encodedPath() + "\t body: " + content);
clearExpiredRecords();
RepeatRecord record = acquireRecord(requestKey);
if (record == null) {
// 已有相同请求,但没有拿到可用结果(上一次失败、超时或结果过大),本次请求直接访问服务器
return chain.proceed(request);
}
//相同的请求
String requestKey = MD5Util.getUpperMD5Str(request.method() + request.url().toString() + requestBodyToString(request.body()));
long time = System.currentTimeMillis();//请求时间
if (!record.isOwner()) {
// 复用相同请求的结果:服务端只会收到一次请求
log("复用请求:", requestKey, request, bodyText);
return record.newResponse(request);
}
log("注册请求:", requestKey, request, bodyText);
try {
if (requestIdsMap.size() > 0 && requestIdsMap.containsKey(requestKey)) {
log("重复请求:", requestKey, request);
//下面这行写了不会抛出onerror
// chain.call().cancel();
return new Response.Builder()
.protocol(Protocol.get(REPEAT_REQUEST_PROTOCOL))
.request(request) //multi thread
.build();
Response response = chain.proceed(request);
ResponseBody responseBody = response.body();
if (responseBody == null || responseBody.contentLength() > MAX_DEDUP_BODY_BYTES) {
// 无响应体或响应体过大:不消费 body,也不参与去重,直接透传
logResponse(request, null);
return response;
}
requestIdsMap.put(requestKey, time);
log("注册请求:", requestKey, request);
// RepeatRequestInterceptor.Builder builder = request.newBuilder();
// builder.addHeader("header", jsonObject.toString());
return response.newBuilder().body(copy).build();
// body 只能被消费一次,读出来之后重建一个新的 body 返回给调用方
MediaType contentType = responseBody.contentType();
byte[] bytes = responseBody.bytes();
logResponse(request, bytes);
if (bytes.length <= MAX_DEDUP_BODY_BYTES) {
// 缓存结果,供等待中的、以及短时间内后续的相同请求复用
record.complete(response, bytes, contentType);
}
return response.newBuilder().body(ResponseBody.create(contentType, bytes)).build();
} catch (IOException e) {
Log.e(TAG, "intercept: " + e.getMessage());
throw e;
} finally {
if (requestIdsMap.containsKey(requestKey) && requestIdsMap.containsValue(time)) {//请求任务完成删除map中的数据
requestIdsMap.remove(requestKey);
log("移除请求:", requestKey, request);
// 兜底:无论成功、失败还是异常,都结束记录,避免等待中的相同请求被一直阻塞
record.finish();
}
}
/**
* 获取请求对应的去重记录。
*
* @return 返回记录表示本次请求要么成为 owner 去访问服务器、要么直接复用已有结果;
* 返回 null 表示已有相同请求但结果不可用,本次请求自己访问服务器(不参与去重)
*/
private RepeatRecord acquireRecord(String requestKey) {
while (true) {
long now = System.currentTimeMillis();
RepeatRecord record = recordMap.get(requestKey);
if (record == null) {
RepeatRecord created = new RepeatRecord();
if (recordMap.putIfAbsent(requestKey, created) == null) {
created.markOwner();
return created;
}
continue;// 其他线程抢先注册,重新判断
}
if (record.isExpired(now)) {
// 结果已过期,替换为本次请求的记录并成为 owner
RepeatRecord created = new RepeatRecord();
if (recordMap.replace(requestKey, record, created)) {
created.markOwner();
return created;
}
continue;
}
// 已有相同请求:等待它的结果,拿到结果直接复用
if (record.await(WAIT_IN_FLIGHT_TIMEOUT_MS)) {
return record;
}
return null;
}
}
/** 清理过期记录,释放其缓存的响应体 */
private void clearExpiredRecords() {
if (recordMap.isEmpty()) {
return;
}
long now = System.currentTimeMillis();
for (Map.Entry<String, RepeatRecord> entry : recordMap.entrySet()) {
RepeatRecord record = entry.getValue();
if (record.isExpired(now)) {
recordMap.remove(entry.getKey(), record);
}
}
}
private void log(String action, String requestKey, Request request) {
private static String buildRequestKey(Request request, String bodyText) {
return MD5Util.getUpperMD5Str(request.method() + "|" + request.url() + "|" + bodyText);
}
/**
* 请求体转字符串,用于计算去重 key 和输出日志。
* 只读取可重复读写的请求体,避免把一次性(one-shot)请求体读空。
*/
private static String requestBodyToString(RequestBody body) {
if (body == null || body.isOneShot()) {
return "";
}
try {
Buffer buffer = new Buffer();
body.writeTo(buffer);
long size = buffer.size();
if (size > MAX_BODY_BYTES_FOR_KEY) {
// 请求体过大时只取前一部分参与去重,避免不必要的内存开销
return size + ":" + buffer.readByteString(MAX_BODY_BYTES_FOR_KEY).hex();
}
return buffer.readUtf8();
} catch (Exception e) {
return "";
}
}
private static void log(String action, String requestKey, Request request, String bodyText) {
if (BuildConfig.DEBUG) {
Log.e("REPEAT-REQUEST", action + requestKey + " Method @" + request.method() + " --- " + " URL = " + request.url().encodedPath() + "\t" + bodyToString(request));
String body = bodyText.length() > MAX_LOG_BODY_LENGTH ? "-too long" : bodyText;
Log.e("REPEAT-REQUEST", action + requestKey + " Method @" + request.method()
+ " --- " + " URL = " + request.url().encodedPath() + "\t" + body);
} else {
Log.e("REPEAT-REQUEST", action + requestKey + " Method @" + request.method());
}
}
private static String bodyToString(final Request request) {
try {
final Request copy = request.newBuilder().build();
final Buffer buffer = new Buffer();
copy.body().writeTo(buffer);
if (buffer.size() > 4096) {
return "-too long";
}
return buffer.readUtf8();
} catch (Exception e) {
return "-";
private static void logResponse(Request request, byte[] bytes) {
if (!BuildConfig.DEBUG) {
return;
}
if (bytes == null || bytes.length > MAX_LOG_BODY_LENGTH) {
Log.e(TAG, "请求体返回:| Response: " + request.url() + "\t body: too long");
} else {
Log.e(TAG, "请求体返回:| Response: " + request.url()
+ "\t body: " + new String(bytes, StandardCharsets.UTF_8));
}
}
private static String requestBodyToString(RequestBody body) {
try {
final Buffer buffer = new Buffer();
body.writeTo(buffer);
if (buffer.size() > 4096) {
return "-too long";
/**
* 一次请求的去重记录:owner 线程负责访问服务器,其他相同请求等待并复用它的结果
*/
private static final class RepeatRecord {
private final Object lock = new Object();
private final long createdTime = System.currentTimeMillis();
private boolean owner;
private boolean finished;
private boolean succeed;
private long finishedTime;
private byte[] body;
private MediaType contentType;
private Headers headers;
private Protocol protocol;
private int code;
private String message;
void markOwner() {
owner = true;
}
boolean isOwner() {
return owner;
}
/**
* 等待 owner 请求结束
*
* @return true 表示已拿到可复用的结果
*/
boolean await(long timeoutMs) {
synchronized (lock) {
if (!finished) {
try {
lock.wait(timeoutMs);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
return finished && succeed;
}
}
/** 请求成功,缓存结果并唤醒等待的请求 */
void complete(Response response, byte[] body, MediaType contentType) {
synchronized (lock) {
if (finished) {
return;
}
this.body = body;
this.contentType = contentType;
this.headers = response.headers();
this.protocol = response.protocol();
this.code = response.code();
this.message = response.message();
this.succeed = true;
finished = true;
finishedTime = System.currentTimeMillis();
lock.notifyAll();
}
}
/** 请求结束(失败或异常时没有可复用的结果);重复调用忽略 */
void finish() {
synchronized (lock) {
if (finished) {
return;
}
finished = true;
finishedTime = System.currentTimeMillis();
lock.notifyAll();
}
}
/** 进行中的记录超过等待超时时间、已完成的记录超过结果保留时间即视为过期 */
boolean isExpired(long now) {
synchronized (lock) {
if (!finished) {
return now - createdTime > WAIT_IN_FLIGHT_TIMEOUT_MS;
}
return now - finishedTime > REUSE_WINDOW_MS;
}
}
/** 用缓存的结果构建响应,状态码、响应头、响应体都是真实数据 */
Response newResponse(Request request) {
synchronized (lock) {
return new Response.Builder()
.request(request)
.protocol(protocol)
.code(code)
.message(message)
.headers(headers)
.body(ResponseBody.create(contentType, body))
.build();
}
return buffer.readUtf8();
} catch (Exception e) {
return "-";
}
}
}

View File

@@ -23,6 +23,7 @@ import static com.aoleyun.os.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED;
import static com.aoleyun.os.model.AppLaunchTracker.CONTAINER_ALL_APPS;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Process;
@@ -44,6 +45,7 @@ import com.aoleyun.os.ItemInfo;
import com.aoleyun.os.Launcher;
import com.aoleyun.os.LauncherAppWidgetInfo;
import com.aoleyun.os.LauncherAppWidgetProviderInfo;
import com.aoleyun.os.comm.CommonConfig;
import com.aoleyun.os.uiuiutils.CustomDialog;
import com.aoleyun.os.uiuiutils.JgyUtils;
import com.hjq.toast.Toaster;
@@ -72,6 +74,7 @@ import java.util.List;
* Class for handling clicks on workspace and all-apps items
*/
public class ItemClickHandler {
private static MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
/**
* Instance used for click handling on items
@@ -107,14 +110,29 @@ public class ItemClickHandler {
}
Object tag = v.getTag();
if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.QualcommPlatform) {
// 点击系统设置时,重定向到 onyx 设置页面
String pkgName = getTagPackageName(tag);
if ("com.android.settings".equals(pkgName)) {
Intent onyxSettingsIntent = new Intent();
onyxSettingsIntent.setComponent(
new ComponentName("com.onyx", "com.onyx.tablet.settings.SettingsActivity"));
onyxSettingsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
launcher.startActivitySafely(v, onyxSettingsIntent,
tag instanceof ItemInfo ? (ItemInfo) tag : null, sourceContainer);
return;
}
}
if (tag instanceof WorkspaceItemInfo) {
String packageName = ((WorkspaceItemInfo) tag).getTargetComponent().getPackageName();
if (is_forbid(v.getContext(), packageName)) {
return;
}
//获取本地密码
String ApplicationLock = MMKV.defaultMMKV().decodeString("ApplicationLock");
Log.e("onClick", "onClick: " + ApplicationLock);
String ApplicationLock = mMMKV.decodeString("ApplicationLock");
Log.e("ItemClickHandler", "onClick: " + ApplicationLock);
Type type = new TypeToken<List<AppPasswdBean>>() {
}.getType();
List<AppPasswdBean> appPasswdBeans = new Gson().fromJson(ApplicationLock, type);
@@ -189,7 +207,7 @@ public class ItemClickHandler {
switch (pkg) {
case "com.mediatek.camera":
case "com.android.camera2":
if (Settings.System.getInt(context.getContentResolver(), "qch_app_camera", 0) == 1) {
if (Settings.System.getInt(context.getContentResolver(), "qch_app_camera", 1) == 1) {
Toaster.show("摄像头已禁止使用");
return true;
}
@@ -207,7 +225,7 @@ public class ItemClickHandler {
}
break;
case "com.android.deskclock":
if (Settings.System.getInt(context.getContentResolver(), "qch_app_deskclock", 0) == 1) {
if (Settings.System.getInt(context.getContentResolver(), "qch_app_deskclock", 1) == 1) {
Toaster.show("时钟已禁止使用");
return true;
}
@@ -237,6 +255,13 @@ public class ItemClickHandler {
return true;
}
break;
case "com.android.calculator":
case "com.android.calculator2":
if (Settings.System.getInt(context.getContentResolver(), "aole_app_calculator", 1) == 1) {
Toaster.show("计算器已禁止使用");
return true;
}
break;
default:
}
return false;
@@ -396,4 +421,18 @@ public class ItemClickHandler {
}
launcher.startActivitySafely(v, intent, item, sourceContainer);
}
/**
* 从点击的 tag 中提取包名,用于判断是否重定向到 onyx 设置页。
*/
private static String getTagPackageName(Object tag) {
if (tag instanceof WorkspaceItemInfo) {
ComponentName cn = ((WorkspaceItemInfo) tag).getTargetComponent();
return cn != null ? cn.getPackageName() : null;
} else if (tag instanceof AppInfo) {
ComponentName cn = ((AppInfo) tag).getTargetComponent();
return cn != null ? cn.getPackageName() : null;
}
return null;
}
}

View File

@@ -24,7 +24,7 @@ public class CustomDialog extends AlertDialog {
/**
* 显示的图片
*/
private ImageView imageIv;
private ImageView imageIv, ivClose;
/**
* 显示的标题
@@ -103,6 +103,12 @@ public class CustomDialog extends AlertDialog {
}
}
});
ivClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
}
/**
@@ -176,6 +182,7 @@ public class CustomDialog extends AlertDialog {
}
});
imageIv = findViewById(R.id.image);
ivClose= findViewById(R.id.iv_close);
columnLineView = findViewById(R.id.column_line);
}

View File

@@ -45,6 +45,11 @@ public class JgyUtils {
public static final int MT8768Platform = 17;
public static final int AUDG104Platform = 18;
public static final int seewoPlatform = 25;
public static final int QualcommPlatform = 30;
public static final int DX11Platform = 31;
public static final int G12NLPlatform = 32;
public static final int G122JPlatform = 34;
public static final String Other = "其他";
public static final String MTKTag = "MTK";
@@ -62,7 +67,10 @@ public class JgyUtils {
public static final String MT8768Tag = "MT8768";
public static final String AUDG104Tag = "AUDG104";
public static final String seewoTag = "seewo";
public static final String Qualcomm_TAG = "QualcommA";
public static final String DX11_TAG = "DX11";
public static final String G12NL_TAG = "G12NL";
public static final String G122J_TAG = "G122J";
private JgyUtils(Context context) {
if (context == null) {
@@ -120,6 +128,18 @@ public class JgyUtils {
} else if (seewoTag.equalsIgnoreCase(platform)) {
Log.i(TAG, "checkAppPlatform: " + "seewo");
return seewoPlatform;
} else if (Qualcomm_TAG.equalsIgnoreCase(platform)) {
Log.i(TAG, "checkAppPlatform: " + "QualcommA");
return QualcommPlatform;
} else if (DX11_TAG.equalsIgnoreCase(platform)) {
Log.i(TAG, "checkAppPlatform: " + "DX11");
return DX11Platform;
} else if (G12NL_TAG.equalsIgnoreCase(platform)) {
Log.i(TAG, "checkAppPlatform: " + "G12NL");
return G12NLPlatform;
} else if (G122J_TAG.equalsIgnoreCase(platform)) {
Log.i(TAG, "checkAppPlatform: " + "G122J");
return G122JPlatform;
} else {
Log.i(TAG, "checkAppPlatform: " + "没有数据");
return UnknowPlatform;
@@ -154,6 +174,14 @@ public class JgyUtils {
getAppPlatformCallback.AppPlatform(AUDG104Platform);
} else if (seewoTag.equalsIgnoreCase(platform)) {
getAppPlatformCallback.AppPlatform(seewoPlatform);
} else if (Qualcomm_TAG.equalsIgnoreCase(platform)) {
getAppPlatformCallback.AppPlatform(QualcommPlatform);
} else if (DX11_TAG.equalsIgnoreCase(platform)) {
getAppPlatformCallback.AppPlatform(DX11Platform);
} else if (G12NL_TAG.equalsIgnoreCase(platform)) {
getAppPlatformCallback.AppPlatform(G12NLPlatform);
} else if (G122J_TAG.equalsIgnoreCase(platform)) {
getAppPlatformCallback.AppPlatform(G122JPlatform);
} else {
getAppPlatformCallback.AppPlatform(UnknowPlatform);
}
@@ -291,6 +319,13 @@ public class JgyUtils {
}
public static boolean isDisable(Context context, String pkg) {
if (
"org.chromium.chrome".equals(pkg)
|| "com.onyx.appmarket".equals(pkg)
// || "com.onyx.easytransfer".equals(pkg)
) {
return true;
}
String aole_disable_app_list = Settings.Global.getString(context.getContentResolver(), "aole_disable_app_list");
if (TextUtils.isEmpty(aole_disable_app_list)) {
return false;

View File

@@ -0,0 +1,120 @@
package com.aoleyun.os.uiuiutils;
import android.app.WallpaperManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.content.Context;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import java.io.IOException;
public class WallpaperUtils {
/**
* @param lockOnly true=仅锁屏;false=按 flags 控制
* @param flags 0 使用传统 setBitmap(主屏);
* WallpaperManager.FLAG_SYSTEM 主屏;
* WallpaperManager.FLAG_LOCK 锁屏;
* 可组合 FLAG_SYSTEM|FLAG_LOCK
*/
public static void setBitmapAsWallpaper(final Context context,
final Bitmap bmp,
final boolean lockOnly,
final int flags) {
new AsyncTask<Void, Void, Boolean>() {
@Override
protected Boolean doInBackground(Void... v) {
try {
WallpaperManager wm = WallpaperManager.getInstance(context);
if (lockOnly && android.os.Build.VERSION.SDK_INT >= 24) {
wm.setBitmap(bmp, null, true, WallpaperManager.FLAG_LOCK);
} else if (flags != 0 && android.os.Build.VERSION.SDK_INT >= 24) {
wm.setBitmap(bmp, null, true, flags);
} else {
wm.setBitmap(bmp); // 传统:设置主屏壁纸
}
return true;
} catch (IOException e) {
Log.e("Wallpaper", "set failed", e);
return false;
}
}
}.execute();
}
// 获取当前主屏壁纸并重新设置(相当于“重设当前壁纸”)
public static void reapplyCurrentWallpaper(Context context) {
new AsyncTask<Void, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(Void... voids) {
try {
WallpaperManager wm = WallpaperManager.getInstance(context);
Drawable d = wm.getDrawable(); // 当前系统壁纸,无则返回默认 [11](@ref)
if (d instanceof BitmapDrawable) {
return ((BitmapDrawable) d).getBitmap();
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
protected void onPostExecute(Bitmap bmp) {
if (bmp == null) return;
setBitmapAsWallpaper(context, bmp, false, 0);
}
}.execute();
}
public static void reapplyLockWallpaper(Context context) {
if (android.os.Build.VERSION.SDK_INT < 24) return;
new AsyncTask<Void, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(Void... v) {
try {
WallpaperManager wm = WallpaperManager.getInstance(context);
ParcelFileDescriptor pfd = wm.getWallpaperFile(WallpaperManager.FLAG_LOCK);
if (pfd == null) {
pfd = wm.getWallpaperFile(WallpaperManager.FLAG_SYSTEM);
}
if (pfd == null) return null;
Bitmap bmp = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
pfd.close();
return bmp;
} catch (Exception e) {
return null;
}
}
@Override
protected void onPostExecute(Bitmap bmp) {
if (bmp != null) setBitmapAsWallpaper(context, bmp, true, 0);
}
}.execute();
}
public static void applyBuiltInDefault(Context context) {
new AsyncTask<Void, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(Void... v) {
WallpaperManager wm = WallpaperManager.getInstance(context);
Drawable d = wm.getBuiltInDrawable(); // 框架内置默认壁纸
if (d instanceof BitmapDrawable) {
return ((BitmapDrawable) d).getBitmap();
}
return null;
}
@Override
protected void onPostExecute(Bitmap bmp) {
if (bmp != null) setBitmapAsWallpaper(context, bmp, false, 0);
}
}.execute();
}
}

View File

@@ -174,6 +174,7 @@ public class ScrimView extends View implements Insettable, WallpaperColorInfo.On
onExtractedColorsChanged(mWallpaperColorInfo);
mAM.addAccessibilityStateChangeListener(this);
mLauncher.getStateManager().addStateListener(this);
onAccessibilityStateChanged(mAM.isEnabled());
}
@@ -182,6 +183,7 @@ public class ScrimView extends View implements Insettable, WallpaperColorInfo.On
super.onDetachedFromWindow();
mWallpaperColorInfo.removeOnChangeListener(this);
mAM.removeAccessibilityStateChangeListener(this);
mLauncher.getStateManager().removeStateListener(this);
}
@Override
@@ -320,11 +322,7 @@ public class ScrimView extends View implements Insettable, WallpaperColorInfo.On
@Override
public void onAccessibilityStateChanged(boolean enabled) {
LauncherStateManager stateManager = mLauncher.getStateManager();
stateManager.removeStateListener(this);
if (enabled) {
stateManager.addStateListener(this);
handleStateChangedComplete(mLauncher.getStateManager().getState());
} else {
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
@@ -333,7 +331,9 @@ public class ScrimView extends View implements Insettable, WallpaperColorInfo.On
}
private void updateDragHandleVisibility(Drawable recycle) {
boolean visible = mLauncher.getDeviceProfile().isVerticalBarLayout() || mAM.isEnabled();
// 桌面主屏(NORMAL)状态下隐藏上滑把手(drag handle),由分页指示器(PageIndicatorDots)展示页面信息
boolean visible = (mLauncher.getDeviceProfile().isVerticalBarLayout() || mAM.isEnabled())
&& !mLauncher.isInState(NORMAL);
boolean wasVisible = mDragHandle != null;
if (visible != wasVisible) {
if (visible) {
@@ -378,6 +378,7 @@ public class ScrimView extends View implements Insettable, WallpaperColorInfo.On
setImportantForAccessibility(finalState == ALL_APPS
? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
: IMPORTANT_FOR_ACCESSIBILITY_AUTO);
updateDragHandleVisibility(null);
}
protected class AccessibilityHelper extends ExploreByTouchHelper {