Compare commits

...

11 Commits

23 changed files with 423 additions and 264 deletions

View File

@@ -0,0 +1 @@

View File

@@ -18,34 +18,35 @@ def genVersionName(def versionName){
}
android {
compileSdkVersion 32
buildToolsVersion "32.0.0"
// 1. compileSdkVersion必须 ≥ targetSdkVersion建议直接等于 targetSdkVersion30
compileSdkVersion 30
// 2. buildToolsVersion需匹配 compileSdkVersion建议使用 30.x.x 最新稳定版(无需高于 compileSdkVersion
buildToolsVersion "30.0.3" // 这是 30 对应的最新稳定版,避免使用 beta 版
defaultConfig {
applicationId "cc.winboll.studio.winboll"
minSdkVersion 24
minSdkVersion 23
targetSdkVersion 30
versionCode 1
// versionName 更新后需要手动设置
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
versionName "15.0"
versionName "15.11"
if(true) {
versionName = genVersionName("${versionName}")
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
// 米盟 SDK
packagingOptions {
doNotStrip "*/*/libmimo_1011.so"
}
}
dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
api 'com.google.code.gson:gson:2.10.1'
// 下拉控件
@@ -60,19 +61,28 @@ dependencies {
api 'com.journeyapps:zxing-android-embedded:3.6.0'
// 应用介绍页类库
api 'io.github.medyo:android-about-page:2.0.0'
// 吐司类库
api 'com.github.getActivity:ToastUtils:10.5'
// 网络连接类库
// 网络连接类库
api 'com.squareup.okhttp3:okhttp:4.4.1'
// AndroidX 类库
// AndroidX 类库
api 'androidx.appcompat:appcompat:1.1.0'
api 'com.google.android.material:material:1.4.0'
//api 'com.google.android.material:material:1.4.0'
//api 'androidx.viewpager:viewpager:1.0.0'
//api 'androidx.vectordrawable:vectordrawable:1.1.0'
//api 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
//api 'androidx.fragment:fragment:1.1.0'
api 'cc.winboll.studio:libaes:15.10.2'
api 'cc.winboll.studio:libapputils:15.10.2'
api 'cc.winboll.studio:libappbase:15.10.9'
// 米盟
api 'com.miui.zeus:mimo-ad-sdk:5.3.+'//请使用最新版sdk
//注意以下5个库必须要引入
//implementation 'androidx.appcompat:appcompat:1.4.1'
api 'androidx.recyclerview:recyclerview:1.0.0'
api 'com.google.code.gson:gson:2.8.5'
api 'com.github.bumptech.glide:glide:4.9.0'
//annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
api 'cc.winboll.studio:libaes:15.11.6'
api 'cc.winboll.studio:libappbase:15.11.0'
api fileTree(dir: 'libs', include: ['*.jar'])
}

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Thu Nov 27 01:06:01 GMT 2025
stageCount=3
#Thu Nov 27 10:54:58 HKT 2025
stageCount=2
libraryProject=
baseVersion=15.0
publishVersion=15.0.2
buildCount=15
baseBetaVersion=15.0.3
baseVersion=15.11
publishVersion=15.11.1
buildCount=0
baseBetaVersion=15.11.2

View File

@@ -1,21 +1,137 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in C:\tools\adt-bundle-windows-x86_64-20131030\sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# ============================== 基础通用规则 ==============================
# 保留系统组件
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
# 保留 WinBoLL 核心包及子类(合并简化规则)
-keep class cc.winboll.studio.** { *; }
-keepclassmembers class cc.winboll.studio.** { *; }
# 保留所有类中的 public static final String TAG 字段(便于日志定位)
-keepclassmembers class * {
public static final java.lang.String TAG;
}
# 保留序列化类避免Parcelable/Gson解析异常
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
# 保留 R 文件避免资源ID混淆
-keepclassmembers class **.R$* {
public static <fields>;
}
# 保留 native 方法避免JNI调用失败
-keepclasseswithmembernames class * {
native <methods>;
}
# 保留注解和泛型(避免反射/序列化异常)
-keepattributes *Annotation*
-keepattributes Signature
# 屏蔽 Java 8+ 警告(适配 Java 7 语法)
-dontwarn java.lang.invoke.*
-dontwarn android.support.v8.renderscript.*
-dontwarn java.util.function.**
# ============================== 第三方框架专项规则 ==============================
# OkHttp 4.4.1米盟广告请求依赖完善Lambda兼容
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-keep class okhttp3.internal.** { *; }
-keep class okio.** { *; }
-dontwarn okhttp3.internal.platform.**
-dontwarn okio.**
# Glide 4.9.0(米盟广告图片加载依赖)
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.ImageHeaderParser$ImageType {
**[] $VALUES;
public *;
}
-keepclassmembers class * implements com.bumptech.glide.module.AppGlideModule {
<init>();
}
-dontwarn com.bumptech.glide.**
# Gson 2.8.5(米盟广告数据序列化依赖)
-keep class com.google.gson.** { *; }
-keep interface com.google.gson.** { *; }
-keepclassmembers class * {
@com.google.gson.annotations.SerializedName <fields>;
}
# 米盟 SDK(核心广告组件,完整保留避免加载失败)
-keep class com.miui.zeus.** { *; }
-keep interface com.miui.zeus.** { *; }
# 保留米盟日志字段(便于广告加载失败排查)
-keepclassmembers class com.miui.zeus.mimo.sdk.** {
public static final java.lang.String TAG;
}
# RecyclerView 1.0.0(米盟广告布局渲染依赖)
-keep class androidx.recyclerview.** { *; }
-keep interface androidx.recyclerview.** { *; }
-keepclassmembers class androidx.recyclerview.widget.RecyclerView$Adapter {
public *;
}
# 其他第三方框架(按引入依赖保留,无则可删除)
# XXPermissions 18.63
-keep class com.hjq.permissions.** { *; }
-keep interface com.hjq.permissions.** { *; }
# ZXing 二维码(核心解析组件)
-keep class com.google.zxing.** { *; }
-keep class com.journeyapps.zxing.** { *; }
# Jsoup HTML解析
-keep class org.jsoup.** { *; }
# Pinyin4j 拼音搜索
-keep class net.sourceforge.pinyin4j.** { *; }
# JSch SSH组件
-keep class com.jcraft.jsch.** { *; }
# AndroidX 基础组件
-keep class androidx.appcompat.** { *; }
-keep interface androidx.appcompat.** { *; }
# ============================== 优化与调试配置 ==============================
# 优化级别(平衡混淆效果与性能)
-optimizationpasses 5
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
# 调试辅助(保留行号便于崩溃定位)
-verbose
-dontpreverify
-dontusemixedcaseclassnames
-keepattributes SourceFile,LineNumberTable

View File

@@ -22,10 +22,8 @@ import android.widget.HorizontalScrollView;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import cc.winboll.studio.libaes.utils.WinBoLLActivityManager;
import cc.winboll.studio.libappbase.GlobalApplication;
import com.hjq.toast.ToastUtils;
import com.hjq.toast.style.WhiteToastStyle;
import cc.winboll.studio.libappbase.ToastUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
@@ -60,19 +58,27 @@ public class App extends GlobalApplication {
public void onCreate() {
super.onCreate();
WinBoLLActivityManager.init(this);
//WinBoLLActivityManager.init(this);
// 初始化 Toast 框架
ToastUtils.init(this);
// 设置 Toast 布局样式
//ToastUtils.setView(R.layout.view_toast);
ToastUtils.setStyle(new WhiteToastStyle());
ToastUtils.setGravity(Gravity.BOTTOM, 0, 200);
//ToastUtils.setStyle(new WhiteToastStyle());
//ToastUtils.setGravity(Gravity.BOTTOM, 0, 200);
//CrashHandler.getInstance().registerGlobal(this);
//CrashHandler.getInstance().registerPart(this);
}
@Override
public void onTerminate() {
super.onTerminate();
ToastUtils.release();
}
public static void write(InputStream input, OutputStream output) throws IOException {
byte[] buf = new byte[1024 * 8];
int len;

View File

@@ -12,7 +12,8 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import cc.winboll.studio.libaes.models.WinBoLLClientServiceBean;
import cc.winboll.studio.libapputils.utils.ServiceUtils;
import cc.winboll.studio.winboll.WinBoLLClientService;
import cc.winboll.studio.winboll.utils.ServiceUtils;
public class AssistantService extends Service {

View File

@@ -1,31 +1,22 @@
package cc.winboll.studio.winboll;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Toast;
import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity;
import cc.winboll.studio.libaes.dialogs.LocalFileSelectDialog;
import cc.winboll.studio.libaes.dialogs.StoragePathDialog;
import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity;
import cc.winboll.studio.libaes.models.DrawerMenuBean;
import cc.winboll.studio.libaes.unittests.SecondaryLibraryActivity;
import cc.winboll.studio.libaes.unittests.TestAButtonFragment;
import cc.winboll.studio.libaes.unittests.TestASupportToolbarActivity;
import cc.winboll.studio.libaes.unittests.TestAToolbarActivity;
import cc.winboll.studio.libaes.unittests.TestDrawerFragmentActivity;
import cc.winboll.studio.libaes.unittests.TestViewPageFragment;
import cc.winboll.studio.libaes.utils.WinBoLLActivityManager;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.winboll.R;
import cc.winboll.studio.winboll.fragments.MainFragment;
import com.a4455jkjh.colorpicker.ColorPickerDialog;
import java.util.ArrayList;
import cc.winboll.studio.winboll.activities.AboutActivity;
import cc.winboll.studio.winboll.fragments.MainFragment;
import java.util.ArrayList;
public class MainActivity extends DrawerFragmentActivity implements IWinBoLLActivity {
@@ -33,7 +24,7 @@ public class MainActivity extends DrawerFragmentActivity implements IWinBoLLActi
public static final String TAG = "MainActivity";
MainFragment mMainFragment;
@Override
public Activity getActivity() {
return null;
@@ -84,9 +75,9 @@ public class MainActivity extends DrawerFragmentActivity implements IWinBoLLActi
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar_main, menu);
if(App.isDebuging()) {
getMenuInflater().inflate(cc.winboll.studio.libapputils.R.menu.toolbar_studio_debug, menu);
}
// if (App.isDebugging()) {
// getMenuInflater().inflate(cc.winboll.studio.libapputils.R.menu.toolbar_studio_debug, menu);
// }
return super.onCreateOptionsMenu(menu);
}
@@ -117,6 +108,6 @@ public class MainActivity extends DrawerFragmentActivity implements IWinBoLLActi
return super.onOptionsItemSelected(item);
}
}

View File

@@ -5,6 +5,14 @@ package cc.winboll.studio.winboll.activities;
* @Date 2025/09/29 13:30
* @Describe 应用介绍窗口
*/
import android.content.Context;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.winboll.BuildConfig;
import cc.winboll.studio.winboll.R;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
@@ -16,8 +24,6 @@ import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity;
import cc.winboll.studio.libaes.models.APPInfo;
import cc.winboll.studio.libaes.utils.WinBoLLActivityManager;
import cc.winboll.studio.libaes.views.AboutView;
import cc.winboll.studio.winboll.R;
import cc.winboll.studio.libaes.BuildConfig;
public class AboutActivity extends WinBoLLActivity implements IWinBoLLActivity {
@@ -75,6 +81,8 @@ public class AboutActivity extends WinBoLLActivity implements IWinBoLLActivity {
WinBoLLActivityManager.getInstance().registeRemove(this);
}
public AboutView CreateAboutView() {
String szBranchName = "winboll";
APPInfo appInfo = new APPInfo();
@@ -89,7 +97,7 @@ public class AboutActivity extends WinBoLLActivity implements IWinBoLLActivity {
appInfo.setAppAPKName("WinBoLL");
appInfo.setAppAPKFolderName("WinBoLL");
//appInfo.setIsAddDebugTools(false);
appInfo.setIsAddDebugTools(BuildConfig.DEBUG);
//appInfo.setIsAddDebugTools(BuildConfig.DEBUG);
return new AboutView(mContext, appInfo);
}
}

View File

@@ -11,27 +11,15 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toolbar;
import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity;
import cc.winboll.studio.libaes.utils.WinBoLLActivityManager;
import cc.winboll.studio.winboll.R;
public class New2Activity extends WinBoLLActivity implements IWinBoLLActivity {
public class New2Activity extends WinBoLLActivity {
public static final String TAG = "New2Activity";
Toolbar mToolbar;
//LogView mLogView;
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -51,15 +39,15 @@ public class New2Activity extends WinBoLLActivity implements IWinBoLLActivity {
}
public void onCloseThisActivity(View view) {
WinBoLLActivityManager.getInstance().finish(this);
//WinBoLLActivityManager.getInstance().finish(this);
}
public void onCloseAllActivity(View view) {
WinBoLLActivityManager.getInstance().finishAll();
//WinBoLLActivityManager.getInstance().finishAll();
}
public void onNewActivity(View view) {
WinBoLLActivityManager.getInstance().startWinBoLLActivity(this, NewActivity.class);
//WinBoLLActivityManager.getInstance().startWinBoLLActivity(this, NewActivity.class);
}

View File

@@ -14,6 +14,7 @@ import android.widget.Toolbar;
import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity;
import cc.winboll.studio.libaes.utils.WinBoLLActivityManager;
import cc.winboll.studio.winboll.R;
import cc.winboll.studio.winboll.App;
public class NewActivity extends WinBoLLActivity implements IWinBoLLActivity {
@@ -58,7 +59,7 @@ public class NewActivity extends WinBoLLActivity implements IWinBoLLActivity {
}
public void onNew2Activity(View view) {
WinBoLLActivityManager.getInstance().startWinBoLLActivity(this, New2Activity.class);
// WinBoLLActivityManager.getInstance().startWinBoLLActivity(App.getInstance(), New2Activity.class);
}

View File

@@ -29,6 +29,7 @@ public class ShortcutActionActivity extends Activity {
* 处理应用图标快捷菜单的请求
*/
private void handleSwitchRequest() {
//ToastUtils.show("handleSwitchRequest");
Intent intent = getIntent();
if (intent != null && "switchto_en1".equals(intent.getDataString())) {
APPPlusUtils.switchAppLauncherToComponent(this, App.COMPONENT_EN1);

View File

@@ -9,28 +9,15 @@ import android.app.Activity;
import android.os.Bundle;
import android.view.MenuItem;
import androidx.appcompat.app.AppCompatActivity;
import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity;
import cc.winboll.studio.libaes.utils.WinBoLLActivityManager;
import cc.winboll.studio.libappbase.LogUtils;
public class WinBoLLActivity extends AppCompatActivity implements IWinBoLLActivity {
public class WinBoLLActivity extends AppCompatActivity {
public static final String TAG = "WinBoLLActivity";
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
@Override
protected void onResume() {
super.onResume();
LogUtils.d(TAG, String.format("onResume %s", getTag()));
}
@Override
@@ -49,12 +36,12 @@ public class WinBoLLActivity extends AppCompatActivity implements IWinBoLLActivi
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
WinBoLLActivityManager.getInstance().add(this);
//WinBoLLActivityManager.getInstance().add(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
WinBoLLActivityManager.getInstance().registeRemove(this);
//WinBoLLActivityManager.getInstance().registeRemove(this);
}
}

View File

@@ -40,7 +40,7 @@ public class WinBoLLUnitTestActivity extends AppCompatActivity {
setSupportActionBar(mToolbar);
CheckBox cbIsDebugMode = findViewById(R.id.activitymainCheckBox1);
cbIsDebugMode.setChecked(GlobalApplication.isDebuging());
cbIsDebugMode.setChecked(GlobalApplication.isDebugging());
}
@Override
@@ -70,8 +70,8 @@ public class WinBoLLUnitTestActivity extends AppCompatActivity {
public void onSwitchDebugMode(View view) {
boolean isDebuging = ((CheckBox)view).isChecked();
GlobalApplication.setIsDebuging(isDebuging);
GlobalApplication.saveDebugStatus(this);
GlobalApplication.setIsDebugging(isDebuging);
GlobalApplication.saveDebugStatus((App.getInstance()));
}
public void onPreviewGlobalCrashActivity(View view) {
@@ -110,7 +110,7 @@ public class WinBoLLUnitTestActivity extends AppCompatActivity {
public void onTestDemoServiceSOS(View view) {
Intent intent = new Intent(this, TestDemoService.class);
stopService(intent);
if (App.isDebuging()) {
if (App.isDebugging()) {
SOS.sosToAppBaseBeta(this, TestDemoService.class.getName());
} else {
SOS.sosToAppBase(this, TestDemoService.class.getName());

View File

@@ -9,12 +9,10 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import cc.winboll.studio.winboll.R;
import cc.winboll.studio.libaes.views.AButton;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.ToastUtils;
import android.widget.Switch;
import androidx.fragment.app.Fragment;
import cc.winboll.studio.libappbase.ToastUtils;
import cc.winboll.studio.winboll.R;
public class MainFragment extends Fragment {

View File

@@ -13,7 +13,6 @@ import android.content.IntentFilter;
import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.ToastUtils;
import cc.winboll.studio.libapputils.utils.AppUtils;
import cc.winboll.studio.winboll.WinBoLL;
import cc.winboll.studio.winboll.models.WinBoLLModel;
import cc.winboll.studio.winboll.models.WinBoLLNewsBean;
@@ -65,41 +64,41 @@ public class MainReceiver extends BroadcastReceiver {
}
} else if (intent.getAction().equals(SOS.ACTION_SOS)) {
LogUtils.d(TAG, "ACTION_SOS");
String sos = intent.getStringExtra(SOS.EXTRA_OBJECT);
LogUtils.d(TAG, String.format("SOS %s", sos));
if (sos != null && !sos.equals("")) {
SOSObject bean = SOS.parseSOSObject(sos);
if (bean != null) {
String szObjectPackageName = bean.getObjectPackageName();
LogUtils.d(TAG, String.format("szObjectPackageName %s", szObjectPackageName));
String szObjectServiveName = bean.getObjectServiveName();
LogUtils.d(TAG, String.format("szObjectServiveName %s", szObjectServiveName));
Intent intentService = new Intent();
intentService.setComponent(new ComponentName(szObjectPackageName, szObjectServiveName));
context.startService(intentService);
String appName = AppUtils.getAppNameByPackageName(context, szObjectPackageName);
LogUtils.d(TAG, String.format("appName %s", appName));
WinBoLLNewsBean appWinBoLLNewsBean = new WinBoLLNewsBean(appName);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String currentTime = sdf.format(new Date());
StringBuilder sbLine = new StringBuilder();
sbLine.append("[");
sbLine.append(currentTime);
sbLine.append("] Power to ");
sbLine.append(appName);
appWinBoLLNewsBean.setMessage(sbLine.toString());
APPNewsWidget.addWinBoLLNewsBean(context, appWinBoLLNewsBean);
Intent intentWidget = new Intent(context, APPNewsWidget.class);
intentWidget.setAction(APPNewsWidget.ACTION_RELOAD_REPORT);
context.sendBroadcast(intentWidget);
}
}
// String sos = intent.getStringExtra(SOS.EXTRA_OBJECT);
// LogUtils.d(TAG, String.format("SOS %s", sos));
// if (sos != null && !sos.equals("")) {
// SOSObject bean = SOS.parseSOSObject(sos);
// if (bean != null) {
// String szObjectPackageName = bean.getObjectPackageName();
// LogUtils.d(TAG, String.format("szObjectPackageName %s", szObjectPackageName));
// String szObjectServiveName = bean.getObjectServiveName();
// LogUtils.d(TAG, String.format("szObjectServiveName %s", szObjectServiveName));
//
// Intent intentService = new Intent();
// intentService.setComponent(new ComponentName(szObjectPackageName, szObjectServiveName));
// context.startService(intentService);
//
// String appName = AppUtils.getAppNameByPackageName(context, szObjectPackageName);
// LogUtils.d(TAG, String.format("appName %s", appName));
// WinBoLLNewsBean appWinBoLLNewsBean = new WinBoLLNewsBean(appName);
// SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
// String currentTime = sdf.format(new Date());
// StringBuilder sbLine = new StringBuilder();
// sbLine.append("[");
// sbLine.append(currentTime);
// sbLine.append("] Power to ");
// sbLine.append(appName);
// appWinBoLLNewsBean.setMessage(sbLine.toString());
//
// APPNewsWidget.addWinBoLLNewsBean(context, appWinBoLLNewsBean);
//
// Intent intentWidget = new Intent(context, APPNewsWidget.class);
// intentWidget.setAction(APPNewsWidget.ACTION_RELOAD_REPORT);
// context.sendBroadcast(intentWidget);
// }
//
//
// }
} else {
ToastUtils.show(szAction);
}

View File

@@ -17,13 +17,13 @@ public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (context.getString(R.string.action_sos).equals(intent.getAction())) {
String message = intent.getStringExtra("message");
String sosPackage = intent.getStringExtra("sosPackage");
// 处理接收到的广播消息
LogUtils.d(TAG, String.format("MyBroadcastReceiver action %s \n%s\n%s", intent.getAction(), sosPackage, message));
}
// if (context.getString(R.string.action_sos).equals(intent.getAction())) {
// String message = intent.getStringExtra("message");
// String sosPackage = intent.getStringExtra("sosPackage");
//
// // 处理接收到的广播消息
// LogUtils.d(TAG, String.format("MyBroadcastReceiver action %s \n%s\n%s", intent.getAction(), sosPackage, message));
// }
}
}

View File

@@ -111,7 +111,7 @@ public class TestDemoBindService extends Service {
// 所以退出时检查本服务是否配置启用,如果启用就发送一个 SOS 信号。
// 这样 APPBase 就会用组件方式启动本服务。
if (bean.isEnable()) {
if (App.isDebuging()) {
if (App.isDebugging()) {
SOS.sosToAppBaseBeta(this, TestDemoBindService.class.getName());
} else {
SOS.sosToAppBase(this, TestDemoBindService.class.getName());
@@ -156,7 +156,7 @@ public class TestDemoBindService extends Service {
isStarted = true;
super.run();
LogUtils.d(TAG, "run() start");
if (App.isDebuging()) {
if (App.isDebugging()) {
WinBoLL.bindToAPPBaseBeta(mContext, TestDemoBindService.class.getName());
} else {
WinBoLL.bindToAPPBase(mContext, TestDemoBindService.class.getName());

View File

@@ -0,0 +1,35 @@
package cc.winboll.studio.winboll.utils;
import android.app.ActivityManager;
import android.content.Context;
import java.util.List;
/**
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
* @Date 2025/11/27 10:25
* @Describe ServiceUtils
*/
public class ServiceUtils {
public static final String TAG = ServiceUtils.class.getSimpleName();
public static boolean isServiceAlive(Context context, String szServiceName) {
// 获取Activity管理者对象
ActivityManager manager = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
// 获取正在运行的服务此处设置最多取1000个
List<ActivityManager.RunningServiceInfo> runningServices = manager
.getRunningServices(1000);
if (runningServices.size() <= 0) {
return false;
}
// 遍历若存在名字和传入的serviceName的一致则说明存在
for (ActivityManager.RunningServiceInfo runningServiceInfo : runningServices) {
if (runningServiceInfo.service.getClassName().equals(szServiceName)) {
return true;
}
}
return false;
}
}

View File

@@ -9,6 +9,8 @@ import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.winboll.models.ResponseData;
import cc.winboll.studio.winboll.models.UserInfoModel;
import com.google.gson.Gson;
import java.io.File;
import java.io.IOException;
@@ -26,9 +28,6 @@ import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import cc.winboll.studio.winboll.models.UserInfoModel;
import cc.winboll.studio.winboll.models.ResponseData;
import cc.winboll.studio.libapputils.utils.FileUtils;
public class YunUtils {
public static final String TAG = "YunUtils";
@@ -138,62 +137,63 @@ public class YunUtils {
}
UserInfoModel loadUserInfoModel() {
LogUtils.d(TAG, "loadUserInfoModel");
if (new File(mUserInfoModelPath).exists()) {
try {
// 加载加密后的模型数据
byte[] encryptedData = FileUtils.readByteArrayFromFile(mUserInfoModelPath);
// 加载 RSA 工具
RSAUtils utils = RSAUtils.getInstance(mContext);
KeyPair keyPair = utils.getOrGenerateKeys();
//PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 私钥解密模型数据
String szInfo = utils.decryptWithPrivateKey(encryptedData, keyPair.getPrivate());
LogUtils.d(TAG, String.format("szInfo %s", szInfo));
mUserInfoModel = UserInfoModel.parseStringToBean(szInfo, UserInfoModel.class);
if (mUserInfoModel == null) {
LogUtils.d(TAG, "模型数据解析为空数据。");
}
LogUtils.d(TAG, "UserInfoModel 解密加载结束。");
} catch (Exception e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
} else {
LogUtils.d(TAG, "云服务登录信息不存在。");
mUserInfoModel = null;
}
return mUserInfoModel;
// LogUtils.d(TAG, "loadUserInfoModel");
// if (new File(mUserInfoModelPath).exists()) {
// try {
// // 加载加密后的模型数据
// byte[] encryptedData = FileUtils.readByteArrayFromFile(mUserInfoModelPath);
// // 加载 RSA 工具
// RSAUtils utils = RSAUtils.getInstance(mContext);
// KeyPair keyPair = utils.getOrGenerateKeys();
// //PublicKey publicKey = keyPair.getPublic();
// PrivateKey privateKey = keyPair.getPrivate();
// // 私钥解密模型数据
// String szInfo = utils.decryptWithPrivateKey(encryptedData, keyPair.getPrivate());
// LogUtils.d(TAG, String.format("szInfo %s", szInfo));
// mUserInfoModel = UserInfoModel.parseStringToBean(szInfo, UserInfoModel.class);
// if (mUserInfoModel == null) {
// LogUtils.d(TAG, "模型数据解析为空数据。");
// }
// LogUtils.d(TAG, "UserInfoModel 解密加载结束。");
// } catch (Exception e) {
// LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
// }
// } else {
// LogUtils.d(TAG, "云服务登录信息不存在。");
// mUserInfoModel = null;
// }
// return mUserInfoModel;
return null;
}
void saveUserInfoModel(UserInfoModel userInfoModel) {
LogUtils.d(TAG, "saveUserInfoModel");
try {
String szInfo = userInfoModel.toString();
LogUtils.d(TAG, "原始数据: " + szInfo);
RSAUtils utils = RSAUtils.getInstance(mContext);
KeyPair keyPair = utils.getOrGenerateKeys();
PublicKey publicKey = keyPair.getPublic();
// 公钥加密(传入字节数组,避免中间字符串转换)
byte[] encryptedData = utils.encryptWithPublicKey(szInfo, publicKey);
// 保存加密字节数组到文件(直接操作字节,无需转字符串)
FileUtils.writeByteArrayToFile(encryptedData, mUserInfoModelPath);
LogUtils.d(TAG, "加密数据已保存");
// 测试解密(仅调试用)
String szInfo2 = utils.decryptWithPrivateKey(encryptedData, keyPair.getPrivate());
LogUtils.d(TAG, "解密结果: " + szInfo2);
mUserInfoModel = UserInfoModel.parseStringToBean(szInfo2, UserInfoModel.class);
if (mUserInfoModel == null) {
LogUtils.d(TAG, "模型解析失败");
}
} catch (Exception e) {
LogUtils.d(TAG, "加密/解密失败: " + e.getMessage());
}
// LogUtils.d(TAG, "saveUserInfoModel");
// try {
// String szInfo = userInfoModel.toString();
// LogUtils.d(TAG, "原始数据: " + szInfo);
//
// RSAUtils utils = RSAUtils.getInstance(mContext);
// KeyPair keyPair = utils.getOrGenerateKeys();
// PublicKey publicKey = keyPair.getPublic();
//
// // 公钥加密(传入字节数组,避免中间字符串转换)
// byte[] encryptedData = utils.encryptWithPublicKey(szInfo, publicKey);
//
// // 保存加密字节数组到文件(直接操作字节,无需转字符串)
// FileUtils.writeByteArrayToFile(encryptedData, mUserInfoModelPath);
// LogUtils.d(TAG, "加密数据已保存");
//
// // 测试解密(仅调试用)
// String szInfo2 = utils.decryptWithPrivateKey(encryptedData, keyPair.getPrivate());
// LogUtils.d(TAG, "解密结果: " + szInfo2);
//
// mUserInfoModel = UserInfoModel.parseStringToBean(szInfo2, UserInfoModel.class);
// if (mUserInfoModel == null) {
// LogUtils.d(TAG, "模型解析失败");
// }
// } catch (Exception e) {
// LogUtils.d(TAG, "加密/解密失败: " + e.getMessage());
// }
}
// 发送 POST 请求JSON 数据)

View File

@@ -12,7 +12,6 @@ import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libapputils.utils.AppUtils;
import cc.winboll.studio.winboll.R;
import cc.winboll.studio.winboll.WinBoLL;
import cc.winboll.studio.winboll.models.WinBoLLModel;
@@ -56,43 +55,43 @@ public class APPNewsWidget extends AppWidgetProvider {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}else if (intent.getAction().equals(ACTION_WAKEUP_SERVICE)) {
LogUtils.d(TAG, "ACTION_WAKEUP_SERVICE");
String szWinBoLLModel = intent.getStringExtra(WinBoLL.EXTRA_WINBOLLMODEL);
LogUtils.d(TAG, String.format("szWinBoLLModel %s", szWinBoLLModel));
if (szWinBoLLModel != null && !szWinBoLLModel.equals("")) {
try {
WinBoLLModel bean = WinBoLLModel.parseStringToBean(szWinBoLLModel, WinBoLLModel.class);
if (bean != null) {
String szAppPackageName = bean.getAppPackageName();
LogUtils.d(TAG, String.format("szAppPackageName %s", szAppPackageName));
String szAppMainServiveName = bean.getAppMainServiveName();
LogUtils.d(TAG, String.format("szAppMainServiveName %s", szAppMainServiveName));
String appName = AppUtils.getAppNameByPackageName(context, szAppPackageName);
LogUtils.d(TAG, String.format("appName %s", appName));
WinBoLLNewsBean winBollNewsBean = new WinBoLLNewsBean(appName);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String currentTime = sdf.format(new Date());
StringBuilder sbLine = new StringBuilder();
sbLine.append("[");
sbLine.append(currentTime);
sbLine.append("] Wake up ");
sbLine.append(appName);
winBollNewsBean.setMessage(sbLine.toString());
addWinBoLLNewsBean(context, winBollNewsBean);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, APPNewsWidget.class));
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
} catch (IOException e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
}
// LogUtils.d(TAG, "ACTION_WAKEUP_SERVICE");
// String szWinBoLLModel = intent.getStringExtra(WinBoLL.EXTRA_WINBOLLMODEL);
// LogUtils.d(TAG, String.format("szWinBoLLModel %s", szWinBoLLModel));
// if (szWinBoLLModel != null && !szWinBoLLModel.equals("")) {
// try {
// WinBoLLModel bean = WinBoLLModel.parseStringToBean(szWinBoLLModel, WinBoLLModel.class);
// if (bean != null) {
// String szAppPackageName = bean.getAppPackageName();
// LogUtils.d(TAG, String.format("szAppPackageName %s", szAppPackageName));
// String szAppMainServiveName = bean.getAppMainServiveName();
// LogUtils.d(TAG, String.format("szAppMainServiveName %s", szAppMainServiveName));
//
//
// String appName = AppUtils.getAppNameByPackageName(context, szAppPackageName);
// LogUtils.d(TAG, String.format("appName %s", appName));
// WinBoLLNewsBean winBollNewsBean = new WinBoLLNewsBean(appName);
// SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
// String currentTime = sdf.format(new Date());
// StringBuilder sbLine = new StringBuilder();
// sbLine.append("[");
// sbLine.append(currentTime);
// sbLine.append("] Wake up ");
// sbLine.append(appName);
// winBollNewsBean.setMessage(sbLine.toString());
//
// addWinBoLLNewsBean(context, winBollNewsBean);
//
// AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
// int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, APPNewsWidget.class));
// for (int appWidgetId : appWidgetIds) {
// updateAppWidget(context, appWidgetManager, appWidgetId);
// }
// }
// } catch (IOException e) {
// LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
// }
// }
}
}

View File

@@ -9,9 +9,9 @@
android:shortcutLongLabel="@string/switchto_en1"
android:shortcutDisabledMessage="@string/en1_switch_disabled">
<intent
android:action="cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_EN1"
android:targetPackage="cc.winboll.studio.powerbell"
android:targetClass="cc.winboll.studio.powerbell.activities.ShortcutActionActivity"
android:action="cc.winboll.studio.winboll.App.ACTION_SWITCHTO_EN1"
android:targetPackage="cc.winboll.studio.winboll"
android:targetClass="cc.winboll.studio.winboll.activities.ShortcutActionActivity"
android:data="switchto_en1" />
<categories android:name="android.shortcut.conversation" />
</shortcut>-->
@@ -23,9 +23,9 @@
android:shortcutLongLabel="@string/switchto_cn1"
android:shortcutDisabledMessage="@string/cn1_switch_disabled">
<intent
android:action="cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN1"
android:targetPackage="cc.winboll.studio.powerbell"
android:targetClass="cc.winboll.studio.powerbell.activities.ShortcutActionActivity"
android:action="cc.winboll.studio.winboll.App.ACTION_SWITCHTO_CN1"
android:targetPackage="cc.winboll.studio.winboll"
android:targetClass="cc.winboll.studio.winboll.activities.ShortcutActionActivity"
android:data="switchto_cn1" />
<categories android:name="android.shortcut.conversation" />
</shortcut>
@@ -37,9 +37,9 @@
android:shortcutLongLabel="@string/switchto_cn2"
android:shortcutDisabledMessage="@string/cn2_switch_disabled">
<intent
android:action="cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN2"
android:targetPackage="cc.winboll.studio.powerbell"
android:targetClass="cc.winboll.studio.powerbell.activities.ShortcutActionActivity"
android:action="cc.winboll.studio.winboll.App.ACTION_SWITCHTO_CN2"
android:targetPackage="cc.winboll.studio.winboll"
android:targetClass="cc.winboll.studio.winboll.activities.ShortcutActionActivity"
android:data="switchto_cn2" />
<categories android:name="android.shortcut.conversation" />
</shortcut>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" >
<application>
<!-- Put flavor specific code here -->
</application>
</manifest>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Put flavor specific strings here -->
</resources>