diff --git a/.gitignore b/.gitignore index 88afb93..5dea002 100644 --- a/.gitignore +++ b/.gitignore @@ -96,6 +96,7 @@ local.properties ## 忽略模块应用编译配置 /settings.gradle +/gradle.properties ## 忽略 srv 纠结问题 /srv/ diff --git a/androiddemo/.gitignore b/androiddemo/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/androiddemo/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/androiddemo/app_update_description.txt b/androiddemo/app_update_description.txt new file mode 100644 index 0000000..e69de29 diff --git a/androiddemo/build.gradle b/androiddemo/build.gradle new file mode 100644 index 0000000..8357611 --- /dev/null +++ b/androiddemo/build.gradle @@ -0,0 +1,74 @@ +apply plugin: 'com.android.application' +apply from: '../.winboll/winboll_app_build.gradle' +apply from: '../.winboll/winboll_lint_build.gradle' + +def genVersionName(def versionName){ + // 检查编译标志位配置 + assert (winbollBuildProps['stageCount'] != null) + assert (winbollBuildProps['baseVersion'] != null) + // 保存基础版本号 + winbollBuildProps.setProperty("baseVersion", "${versionName}"); + //保存编译标志配置 + FileOutputStream fos = new FileOutputStream(winbollBuildPropsFile) + winbollBuildProps.store(fos, "${winbollBuildPropsDesc}"); + fos.close(); + + // 返回编译版本号 + return "${versionName}." + winbollBuildProps['stageCount'] +} + +android { + productFlavors { + beta { + } + stage { + } + } + + compileSdkVersion 30 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "cc.winboll.studio.androiddemo" + minSdkVersion 26 + targetSdkVersion 29 + versionCode 1 + // versionName 更新后需要手动设置 + // .winboll/winbollBuildProps.properties 文件的 stageCount=0 + // Gradle编译环境下合起来的 versionName 就是 "${versionName}.0" + versionName "1.0" + if(true) { + versionName = genVersionName("${versionName}") + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + api fileTree(dir: 'libs', include: ['*.jar']) + + // 吐司类库 + implementation 'com.github.getActivity:ToastUtils:10.5' + + // Android 类库 + // https://mvnrepository.com/artifact/com.android.support/support-v4 + implementation 'com.android.support:support-v4:28.0.0' + // https://mvnrepository.com/artifact/com.android.support/support-compat + implementation 'com.android.support:support-compat:28.0.0' + // https://mvnrepository.com/artifact/com.android.support/support-media-compat + implementation 'com.android.support:support-media-compat:28.0.0' + // https://mvnrepository.com/artifact/com.android.support/support-core-utils + implementation 'com.android.support:support-core-utils:28.0.0' + // https://mvnrepository.com/artifact/com.android.support/support-core-ui + implementation 'com.android.support:support-core-ui:28.0.0' + // https://mvnrepository.com/artifact/com.android.support/support-fragment + implementation 'com.android.support:support-fragment:28.0.0' + // https://mvnrepository.com/artifact/com.android.support/recyclerview-v7 + implementation 'com.android.support:recyclerview-v7:28.0.0' +} diff --git a/androiddemo/build.properties b/androiddemo/build.properties new file mode 100644 index 0000000..4d98e2f --- /dev/null +++ b/androiddemo/build.properties @@ -0,0 +1,8 @@ +#Created by .winboll/winboll_app_build.gradle +#Tue Mar 11 18:02:14 GMT 2025 +stageCount=0 +libraryProject= +baseVersion=1.0 +publishVersion=1.0.0 +buildCount=1 +baseBetaVersion=1.0.1 diff --git a/androiddemo/proguard-rules.pro b/androiddemo/proguard-rules.pro new file mode 100644 index 0000000..64b4a05 --- /dev/null +++ b/androiddemo/proguard-rules.pro @@ -0,0 +1,21 @@ +# 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 \ No newline at end of file diff --git a/androiddemo/src/beta/AndroidManifest.xml b/androiddemo/src/beta/AndroidManifest.xml new file mode 100644 index 0000000..ee78d9f --- /dev/null +++ b/androiddemo/src/beta/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/androiddemo/src/beta/res/values/strings.xml b/androiddemo/src/beta/res/values/strings.xml new file mode 100644 index 0000000..e0c92e9 --- /dev/null +++ b/androiddemo/src/beta/res/values/strings.xml @@ -0,0 +1,7 @@ + + + + + Android Demo + + + diff --git a/androiddemo/src/main/AndroidManifest.xml b/androiddemo/src/main/AndroidManifest.xml new file mode 100644 index 0000000..43eac9a --- /dev/null +++ b/androiddemo/src/main/AndroidManifest.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/androiddemo/src/main/java/cc/winboll/studio/androiddemo/GlobalApplication.java b/androiddemo/src/main/java/cc/winboll/studio/androiddemo/GlobalApplication.java new file mode 100644 index 0000000..e13af9a --- /dev/null +++ b/androiddemo/src/main/java/cc/winboll/studio/androiddemo/GlobalApplication.java @@ -0,0 +1,334 @@ +package cc.winboll.studio.androiddemo; + +import android.app.Activity; +import android.app.Application; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.res.Resources; +import android.graphics.Typeface; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.text.TextUtils; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.ViewGroup; +import android.widget.HorizontalScrollView; +import android.widget.ScrollView; +import android.widget.TextView; +import android.widget.Toast; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.Thread.UncaughtExceptionHandler; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.concurrent.atomic.AtomicBoolean; + +public class GlobalApplication extends Application { + + private static Handler MAIN_HANDLER = new Handler(Looper.getMainLooper()); + + @Override + public void onCreate() { + super.onCreate(); + CrashHandler.getInstance().registerGlobal(this); + CrashHandler.getInstance().registerPart(this); + } + + public static void write(InputStream input, OutputStream output) throws IOException { + byte[] buf = new byte[1024 * 8]; + int len; + while ((len = input.read(buf)) != -1) { + output.write(buf, 0, len); + } + } + + public static void write(File file, byte[] data) throws IOException { + File parent = file.getParentFile(); + if (parent != null && !parent.exists()) parent.mkdirs(); + + ByteArrayInputStream input = new ByteArrayInputStream(data); + FileOutputStream output = new FileOutputStream(file); + try { + write(input, output); + } finally { + closeIO(input, output); + } + } + + public static String toString(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + write(input, output); + try { + return output.toString("UTF-8"); + } finally { + closeIO(input, output); + } + } + + public static void closeIO(Closeable... closeables) { + for (Closeable closeable : closeables) { + try { + if (closeable != null) closeable.close(); + } catch (IOException ignored) {} + } + } + + public static class CrashHandler { + + public static final UncaughtExceptionHandler DEFAULT_UNCAUGHT_EXCEPTION_HANDLER = Thread.getDefaultUncaughtExceptionHandler(); + + private static CrashHandler sInstance; + + private PartCrashHandler mPartCrashHandler; + + public static CrashHandler getInstance() { + if (sInstance == null) { + sInstance = new CrashHandler(); + } + return sInstance; + } + + public void registerGlobal(Context context) { + registerGlobal(context, null); + } + + public void registerGlobal(Context context, String crashDir) { + Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandlerImpl(context.getApplicationContext(), crashDir)); + } + + public void unregister() { + Thread.setDefaultUncaughtExceptionHandler(DEFAULT_UNCAUGHT_EXCEPTION_HANDLER); + } + + public void registerPart(Context context) { + unregisterPart(context); + mPartCrashHandler = new PartCrashHandler(context.getApplicationContext()); + MAIN_HANDLER.postAtFrontOfQueue(mPartCrashHandler); + } + + public void unregisterPart(Context context) { + if (mPartCrashHandler != null) { + mPartCrashHandler.isRunning.set(false); + mPartCrashHandler = null; + } + } + + private static class PartCrashHandler implements Runnable { + + private final Context mContext; + + public AtomicBoolean isRunning = new AtomicBoolean(true); + + public PartCrashHandler(Context context) { + this.mContext = context; + } + + @Override + public void run() { + while (isRunning.get()) { + try { + Looper.loop(); + } catch (final Throwable e) { + e.printStackTrace(); + if (isRunning.get()) { + MAIN_HANDLER.post(new Runnable(){ + + @Override + public void run() { + Toast.makeText(mContext, e.toString(), Toast.LENGTH_LONG).show(); + } + }); + } else { + if (e instanceof RuntimeException) { + throw (RuntimeException)e; + } else { + throw new RuntimeException(e); + } + } + } + } + } + } + + private static class UncaughtExceptionHandlerImpl implements UncaughtExceptionHandler { + + private static DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss"); + + private final Context mContext; + + private final File mCrashDir; + + public UncaughtExceptionHandlerImpl(Context context, String crashDir) { + this.mContext = context; + this.mCrashDir = TextUtils.isEmpty(crashDir) ? new File(mContext.getExternalCacheDir(), "crash") : new File(crashDir); + } + + @Override + public void uncaughtException(Thread thread, Throwable throwable) { + try { + + String log = buildLog(throwable); + writeLog(log); + + try { + Intent intent = new Intent(mContext, CrashActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(Intent.EXTRA_TEXT, log); + mContext.startActivity(intent); + } catch (Throwable e) { + e.printStackTrace(); + writeLog(e.toString()); + } + + throwable.printStackTrace(); + android.os.Process.killProcess(android.os.Process.myPid()); + System.exit(0); + + } catch (Throwable e) { + if (DEFAULT_UNCAUGHT_EXCEPTION_HANDLER != null) DEFAULT_UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(thread, throwable); + } + } + + private String buildLog(Throwable throwable) { + String time = DATE_FORMAT.format(new Date()); + + String versionName = "unknown"; + long versionCode = 0; + try { + PackageInfo packageInfo = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0); + versionName = packageInfo.versionName; + versionCode = Build.VERSION.SDK_INT >= 28 ? packageInfo.getLongVersionCode() : packageInfo.versionCode; + } catch (Throwable ignored) {} + + LinkedHashMap head = new LinkedHashMap(); + head.put("Time Of Crash", time); + head.put("Device", String.format("%s, %s", Build.MANUFACTURER, Build.MODEL)); + head.put("Android Version", String.format("%s (%d)", Build.VERSION.RELEASE, Build.VERSION.SDK_INT)); + head.put("App Version", String.format("%s (%d)", versionName, versionCode)); + head.put("Kernel", getKernel()); + head.put("Support Abis", Build.VERSION.SDK_INT >= 21 && Build.SUPPORTED_ABIS != null ? Arrays.toString(Build.SUPPORTED_ABIS): "unknown"); + head.put("Fingerprint", Build.FINGERPRINT); + + StringBuilder builder = new StringBuilder(); + + for (String key : head.keySet()) { + if (builder.length() != 0) builder.append("\n"); + builder.append(key); + builder.append(" : "); + builder.append(head.get(key)); + } + + builder.append("\n\n"); + builder.append(Log.getStackTraceString(throwable)); + + return builder.toString(); + } + + private void writeLog(String log) { + String time = DATE_FORMAT.format(new Date()); + File file = new File(mCrashDir, "crash_" + time + ".txt"); + try { + write(file, log.getBytes("UTF-8")); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + private static String getKernel() { + try { + return GlobalApplication.toString(new FileInputStream("/proc/version")).trim(); + } catch (Throwable e) { + return e.getMessage(); + } + } + } + } + + public static final class CrashActivity extends Activity { + + private String mLog; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setTheme(android.R.style.Theme_DeviceDefault); + setTitle("App Crash"); + + mLog = getIntent().getStringExtra(Intent.EXTRA_TEXT); + + ScrollView contentView = new ScrollView(this); + contentView.setFillViewport(true); + + HorizontalScrollView horizontalScrollView = new HorizontalScrollView(this); + + TextView textView = new TextView(this); + int padding = dp2px(16); + textView.setPadding(padding, padding, padding, padding); + textView.setText(mLog); + textView.setTextIsSelectable(true); + textView.setTypeface(Typeface.DEFAULT); + textView.setLinksClickable(true); + + horizontalScrollView.addView(textView); + contentView.addView(horizontalScrollView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + + setContentView(contentView); + } + + private void restart() { + Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName()); + if (intent != null) { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } + finish(); + android.os.Process.killProcess(android.os.Process.myPid()); + System.exit(0); + } + + private static int dp2px(float dpValue) { + final float scale = Resources.getSystem().getDisplayMetrics().density; + return (int) (dpValue * scale + 0.5f); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + menu.add(0, android.R.id.copy, 0, android.R.string.copy) + .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.copy: + ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + cm.setPrimaryClip(ClipData.newPlainText(getPackageName(), mLog)); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void onBackPressed() { + restart(); + } + } +} \ No newline at end of file diff --git a/androiddemo/src/main/java/cc/winboll/studio/androiddemo/MainActivity.java b/androiddemo/src/main/java/cc/winboll/studio/androiddemo/MainActivity.java new file mode 100644 index 0000000..dcef375 --- /dev/null +++ b/androiddemo/src/main/java/cc/winboll/studio/androiddemo/MainActivity.java @@ -0,0 +1,15 @@ +package cc.winboll.studio.androiddemo; + +import android.app.Activity; +import android.os.Bundle; + +public class MainActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + } + +} \ No newline at end of file diff --git a/androiddemo/src/main/res/drawable/ic_launcher.png b/androiddemo/src/main/res/drawable/ic_launcher.png new file mode 100644 index 0000000..b824ebd Binary files /dev/null and b/androiddemo/src/main/res/drawable/ic_launcher.png differ diff --git a/androiddemo/src/main/res/layout/activity_main.xml b/androiddemo/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..f8b9a89 --- /dev/null +++ b/androiddemo/src/main/res/layout/activity_main.xml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/androiddemo/src/main/res/values-v21/styles.xml b/androiddemo/src/main/res/values-v21/styles.xml new file mode 100644 index 0000000..0aed032 --- /dev/null +++ b/androiddemo/src/main/res/values-v21/styles.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/androiddemo/src/main/res/values/colors.xml b/androiddemo/src/main/res/values/colors.xml new file mode 100644 index 0000000..294809a --- /dev/null +++ b/androiddemo/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #009688 + #00796B + #FF9800 + \ No newline at end of file diff --git a/androiddemo/src/main/res/values/strings.xml b/androiddemo/src/main/res/values/strings.xml new file mode 100644 index 0000000..21acbbd --- /dev/null +++ b/androiddemo/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Android Demo + diff --git a/androiddemo/src/main/res/values/styles.xml b/androiddemo/src/main/res/values/styles.xml new file mode 100644 index 0000000..6799c28 --- /dev/null +++ b/androiddemo/src/main/res/values/styles.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/androiddemo/src/stage/AndroidManifest.xml b/androiddemo/src/stage/AndroidManifest.xml new file mode 100644 index 0000000..ee78d9f --- /dev/null +++ b/androiddemo/src/stage/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/androiddemo/src/stage/res/values/strings.xml b/androiddemo/src/stage/res/values/strings.xml new file mode 100644 index 0000000..ace0c41 --- /dev/null +++ b/androiddemo/src/stage/res/values/strings.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/androidxdemo/.gitignore b/androidxdemo/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/androidxdemo/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/androidxdemo/app_update_description.txt b/androidxdemo/app_update_description.txt new file mode 100644 index 0000000..e69de29 diff --git a/androidxdemo/build.gradle b/androidxdemo/build.gradle new file mode 100644 index 0000000..fcf214f --- /dev/null +++ b/androidxdemo/build.gradle @@ -0,0 +1,76 @@ +apply plugin: 'com.android.application' +apply from: '../.winboll/winboll_app_build.gradle' +apply from: '../.winboll/winboll_lint_build.gradle' + +def genVersionName(def versionName){ + // 检查编译标志位配置 + assert (winbollBuildProps['stageCount'] != null) + assert (winbollBuildProps['baseVersion'] != null) + // 保存基础版本号 + winbollBuildProps.setProperty("baseVersion", "${versionName}"); + //保存编译标志配置 + FileOutputStream fos = new FileOutputStream(winbollBuildPropsFile) + winbollBuildProps.store(fos, "${winbollBuildPropsDesc}"); + fos.close(); + + // 返回编译版本号 + return "${versionName}." + winbollBuildProps['stageCount'] +} + +android { + productFlavors { + beta { + } + stage { + } + } + + compileSdkVersion 30 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "cc.winboll.studio.androidxdemo" + minSdkVersion 26 + targetSdkVersion 29 + versionCode 1 + // versionName 更新后需要手动设置 + // .winboll/winbollBuildProps.properties 文件的 stageCount=0 + // Gradle编译环境下合起来的 versionName 就是 "${versionName}.0" + versionName "1.0" + if(true) { + versionName = genVersionName("${versionName}") + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + api fileTree(dir: 'libs', include: ['*.jar']) + + // SSH + implementation 'com.jcraft:jsch:0.1.55' + // Html 解析 + implementation 'org.jsoup:jsoup:1.13.1' + // 二维码类库 + implementation 'com.google.zxing:core:3.4.1' + implementation 'com.journeyapps:zxing-android-embedded:3.6.0' + // 应用介绍页类库 + implementation 'io.github.medyo:android-about-page:2.0.0' + // 吐司类库 + implementation 'com.github.getActivity:ToastUtils:10.5' + // 网络连接类库 + implementation 'com.squareup.okhttp3:okhttp:4.4.1' + // Android 类库 + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.viewpager:viewpager:1.0.0' + implementation 'androidx.vectordrawable:vectordrawable:1.1.0' + implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0' + implementation 'androidx.fragment:fragment:1.1.0' + implementation 'com.google.android.material:material:1.4.0' +} diff --git a/androidxdemo/build.properties b/androidxdemo/build.properties new file mode 100644 index 0000000..8d115d9 --- /dev/null +++ b/androidxdemo/build.properties @@ -0,0 +1,8 @@ +#Created by .winboll/winboll_app_build.gradle +#Tue Mar 11 18:25:43 GMT 2025 +stageCount=0 +libraryProject= +baseVersion=1.0 +publishVersion=1.0.0 +buildCount=4 +baseBetaVersion=1.0.1 diff --git a/androidxdemo/proguard-rules.pro b/androidxdemo/proguard-rules.pro new file mode 100644 index 0000000..64b4a05 --- /dev/null +++ b/androidxdemo/proguard-rules.pro @@ -0,0 +1,21 @@ +# 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 \ No newline at end of file diff --git a/androidxdemo/src/beta/AndroidManifest.xml b/androidxdemo/src/beta/AndroidManifest.xml new file mode 100644 index 0000000..ee78d9f --- /dev/null +++ b/androidxdemo/src/beta/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/androidxdemo/src/beta/res/values/strings.xml b/androidxdemo/src/beta/res/values/strings.xml new file mode 100644 index 0000000..bf50bcf --- /dev/null +++ b/androidxdemo/src/beta/res/values/strings.xml @@ -0,0 +1,6 @@ + + + + AndroidX Demo + + + diff --git a/androidxdemo/src/main/AndroidManifest.xml b/androidxdemo/src/main/AndroidManifest.xml new file mode 100644 index 0000000..6d0c707 --- /dev/null +++ b/androidxdemo/src/main/AndroidManifest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/androidxdemo/src/main/java/cc/winboll/studio/androidxdemo/GlobalApplication.java b/androidxdemo/src/main/java/cc/winboll/studio/androidxdemo/GlobalApplication.java new file mode 100644 index 0000000..7abaf88 --- /dev/null +++ b/androidxdemo/src/main/java/cc/winboll/studio/androidxdemo/GlobalApplication.java @@ -0,0 +1,334 @@ +package cc.winboll.studio.androidxdemo; + +import android.app.Activity; +import android.app.Application; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.res.Resources; +import android.graphics.Typeface; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.text.TextUtils; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.ViewGroup; +import android.widget.HorizontalScrollView; +import android.widget.ScrollView; +import android.widget.TextView; +import android.widget.Toast; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.Thread.UncaughtExceptionHandler; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.concurrent.atomic.AtomicBoolean; + +public class GlobalApplication extends Application { + + private static Handler MAIN_HANDLER = new Handler(Looper.getMainLooper()); + + @Override + public void onCreate() { + super.onCreate(); + CrashHandler.getInstance().registerGlobal(this); + CrashHandler.getInstance().registerPart(this); + } + + public static void write(InputStream input, OutputStream output) throws IOException { + byte[] buf = new byte[1024 * 8]; + int len; + while ((len = input.read(buf)) != -1) { + output.write(buf, 0, len); + } + } + + public static void write(File file, byte[] data) throws IOException { + File parent = file.getParentFile(); + if (parent != null && !parent.exists()) parent.mkdirs(); + + ByteArrayInputStream input = new ByteArrayInputStream(data); + FileOutputStream output = new FileOutputStream(file); + try { + write(input, output); + } finally { + closeIO(input, output); + } + } + + public static String toString(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + write(input, output); + try { + return output.toString("UTF-8"); + } finally { + closeIO(input, output); + } + } + + public static void closeIO(Closeable... closeables) { + for (Closeable closeable : closeables) { + try { + if (closeable != null) closeable.close(); + } catch (IOException ignored) {} + } + } + + public static class CrashHandler { + + public static final UncaughtExceptionHandler DEFAULT_UNCAUGHT_EXCEPTION_HANDLER = Thread.getDefaultUncaughtExceptionHandler(); + + private static CrashHandler sInstance; + + private PartCrashHandler mPartCrashHandler; + + public static CrashHandler getInstance() { + if (sInstance == null) { + sInstance = new CrashHandler(); + } + return sInstance; + } + + public void registerGlobal(Context context) { + registerGlobal(context, null); + } + + public void registerGlobal(Context context, String crashDir) { + Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandlerImpl(context.getApplicationContext(), crashDir)); + } + + public void unregister() { + Thread.setDefaultUncaughtExceptionHandler(DEFAULT_UNCAUGHT_EXCEPTION_HANDLER); + } + + public void registerPart(Context context) { + unregisterPart(context); + mPartCrashHandler = new PartCrashHandler(context.getApplicationContext()); + MAIN_HANDLER.postAtFrontOfQueue(mPartCrashHandler); + } + + public void unregisterPart(Context context) { + if (mPartCrashHandler != null) { + mPartCrashHandler.isRunning.set(false); + mPartCrashHandler = null; + } + } + + private static class PartCrashHandler implements Runnable { + + private final Context mContext; + + public AtomicBoolean isRunning = new AtomicBoolean(true); + + public PartCrashHandler(Context context) { + this.mContext = context; + } + + @Override + public void run() { + while (isRunning.get()) { + try { + Looper.loop(); + } catch (final Throwable e) { + e.printStackTrace(); + if (isRunning.get()) { + MAIN_HANDLER.post(new Runnable(){ + + @Override + public void run() { + Toast.makeText(mContext, e.toString(), Toast.LENGTH_LONG).show(); + } + }); + } else { + if (e instanceof RuntimeException) { + throw (RuntimeException)e; + } else { + throw new RuntimeException(e); + } + } + } + } + } + } + + private static class UncaughtExceptionHandlerImpl implements UncaughtExceptionHandler { + + private static DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss"); + + private final Context mContext; + + private final File mCrashDir; + + public UncaughtExceptionHandlerImpl(Context context, String crashDir) { + this.mContext = context; + this.mCrashDir = TextUtils.isEmpty(crashDir) ? new File(mContext.getExternalCacheDir(), "crash") : new File(crashDir); + } + + @Override + public void uncaughtException(Thread thread, Throwable throwable) { + try { + + String log = buildLog(throwable); + writeLog(log); + + try { + Intent intent = new Intent(mContext, CrashActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(Intent.EXTRA_TEXT, log); + mContext.startActivity(intent); + } catch (Throwable e) { + e.printStackTrace(); + writeLog(e.toString()); + } + + throwable.printStackTrace(); + android.os.Process.killProcess(android.os.Process.myPid()); + System.exit(0); + + } catch (Throwable e) { + if (DEFAULT_UNCAUGHT_EXCEPTION_HANDLER != null) DEFAULT_UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(thread, throwable); + } + } + + private String buildLog(Throwable throwable) { + String time = DATE_FORMAT.format(new Date()); + + String versionName = "unknown"; + long versionCode = 0; + try { + PackageInfo packageInfo = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0); + versionName = packageInfo.versionName; + versionCode = Build.VERSION.SDK_INT >= 28 ? packageInfo.getLongVersionCode() : packageInfo.versionCode; + } catch (Throwable ignored) {} + + LinkedHashMap head = new LinkedHashMap(); + head.put("Time Of Crash", time); + head.put("Device", String.format("%s, %s", Build.MANUFACTURER, Build.MODEL)); + head.put("Android Version", String.format("%s (%d)", Build.VERSION.RELEASE, Build.VERSION.SDK_INT)); + head.put("App Version", String.format("%s (%d)", versionName, versionCode)); + head.put("Kernel", getKernel()); + head.put("Support Abis", Build.VERSION.SDK_INT >= 21 && Build.SUPPORTED_ABIS != null ? Arrays.toString(Build.SUPPORTED_ABIS): "unknown"); + head.put("Fingerprint", Build.FINGERPRINT); + + StringBuilder builder = new StringBuilder(); + + for (String key : head.keySet()) { + if (builder.length() != 0) builder.append("\n"); + builder.append(key); + builder.append(" : "); + builder.append(head.get(key)); + } + + builder.append("\n\n"); + builder.append(Log.getStackTraceString(throwable)); + + return builder.toString(); + } + + private void writeLog(String log) { + String time = DATE_FORMAT.format(new Date()); + File file = new File(mCrashDir, "crash_" + time + ".txt"); + try { + write(file, log.getBytes("UTF-8")); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + private static String getKernel() { + try { + return GlobalApplication.toString(new FileInputStream("/proc/version")).trim(); + } catch (Throwable e) { + return e.getMessage(); + } + } + } + } + + public static final class CrashActivity extends Activity { + + private String mLog; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setTheme(android.R.style.Theme_DeviceDefault); + setTitle("App Crash"); + + mLog = getIntent().getStringExtra(Intent.EXTRA_TEXT); + + ScrollView contentView = new ScrollView(this); + contentView.setFillViewport(true); + + HorizontalScrollView horizontalScrollView = new HorizontalScrollView(this); + + TextView textView = new TextView(this); + int padding = dp2px(16); + textView.setPadding(padding, padding, padding, padding); + textView.setText(mLog); + textView.setTextIsSelectable(true); + textView.setTypeface(Typeface.DEFAULT); + textView.setLinksClickable(true); + + horizontalScrollView.addView(textView); + contentView.addView(horizontalScrollView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + + setContentView(contentView); + } + + private void restart() { + Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName()); + if (intent != null) { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } + finish(); + android.os.Process.killProcess(android.os.Process.myPid()); + System.exit(0); + } + + private static int dp2px(float dpValue) { + final float scale = Resources.getSystem().getDisplayMetrics().density; + return (int) (dpValue * scale + 0.5f); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + menu.add(0, android.R.id.copy, 0, android.R.string.copy) + .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.copy: + ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + cm.setPrimaryClip(ClipData.newPlainText(getPackageName(), mLog)); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void onBackPressed() { + restart(); + } + } +} \ No newline at end of file diff --git a/androidxdemo/src/main/java/cc/winboll/studio/androidxdemo/MainActivity.java b/androidxdemo/src/main/java/cc/winboll/studio/androidxdemo/MainActivity.java new file mode 100644 index 0000000..de5c892 --- /dev/null +++ b/androidxdemo/src/main/java/cc/winboll/studio/androidxdemo/MainActivity.java @@ -0,0 +1,19 @@ +package cc.winboll.studio.androidxdemo; + +import android.os.Bundle; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; + +public class MainActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + Toolbar toolbar=(Toolbar)findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + } + +} \ No newline at end of file diff --git a/androidxdemo/src/main/res/drawable-v24/ic_launcher_foreground.xml b/androidxdemo/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/androidxdemo/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/androidxdemo/src/main/res/drawable/ic_launcher_background.xml b/androidxdemo/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/androidxdemo/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/androidxdemo/src/main/res/layout/activity_main.xml b/androidxdemo/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..034ba40 --- /dev/null +++ b/androidxdemo/src/main/res/layout/activity_main.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + diff --git a/androidxdemo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/androidxdemo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/androidxdemo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/androidxdemo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/androidxdemo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/androidxdemo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/androidxdemo/src/main/res/mipmap-hdpi/ic_launcher.png b/androidxdemo/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a2f5908 Binary files /dev/null and b/androidxdemo/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/androidxdemo/src/main/res/mipmap-hdpi/ic_launcher_round.png b/androidxdemo/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..1b52399 Binary files /dev/null and b/androidxdemo/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/androidxdemo/src/main/res/mipmap-mdpi/ic_launcher.png b/androidxdemo/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..ff10afd Binary files /dev/null and b/androidxdemo/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/androidxdemo/src/main/res/mipmap-mdpi/ic_launcher_round.png b/androidxdemo/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..115a4c7 Binary files /dev/null and b/androidxdemo/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/androidxdemo/src/main/res/mipmap-xhdpi/ic_launcher.png b/androidxdemo/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..dcd3cd8 Binary files /dev/null and b/androidxdemo/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/androidxdemo/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/androidxdemo/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..459ca60 Binary files /dev/null and b/androidxdemo/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/androidxdemo/src/main/res/mipmap-xxhdpi/ic_launcher.png b/androidxdemo/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..8ca12fe Binary files /dev/null and b/androidxdemo/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/androidxdemo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/androidxdemo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..8e19b41 Binary files /dev/null and b/androidxdemo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/androidxdemo/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/androidxdemo/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..b824ebd Binary files /dev/null and b/androidxdemo/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/androidxdemo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/androidxdemo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..4c19a13 Binary files /dev/null and b/androidxdemo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/androidxdemo/src/main/res/values/colors.xml b/androidxdemo/src/main/res/values/colors.xml new file mode 100644 index 0000000..479769a --- /dev/null +++ b/androidxdemo/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #009688 + #00796B + #FF9800 + \ No newline at end of file diff --git a/androidxdemo/src/main/res/values/strings.xml b/androidxdemo/src/main/res/values/strings.xml new file mode 100644 index 0000000..6aea12c --- /dev/null +++ b/androidxdemo/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + AndroidX Demo + + diff --git a/androidxdemo/src/main/res/values/styles.xml b/androidxdemo/src/main/res/values/styles.xml new file mode 100644 index 0000000..0eb88fe --- /dev/null +++ b/androidxdemo/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/androidxdemo/src/stage/AndroidManifest.xml b/androidxdemo/src/stage/AndroidManifest.xml new file mode 100644 index 0000000..ee78d9f --- /dev/null +++ b/androidxdemo/src/stage/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/androidxdemo/src/stage/res/values/strings.xml b/androidxdemo/src/stage/res/values/strings.xml new file mode 100644 index 0000000..ace0c41 --- /dev/null +++ b/androidxdemo/src/stage/res/values/strings.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/appbase/build.gradle b/appbase/build.gradle index 6193aa5..4632155 100644 --- a/appbase/build.gradle +++ b/appbase/build.gradle @@ -18,8 +18,8 @@ def genVersionName(def versionName){ } android { - compileSdkVersion 30 - buildToolsVersion "30.0.3" + compileSdkVersion 32 + buildToolsVersion "32.0.0" defaultConfig { applicationId "cc.winboll.studio.appbase" @@ -29,7 +29,7 @@ android { // versionName 更新后需要手动设置 // .winboll/winbollBuildProps.properties 文件的 stageCount=0 // Gradle编译环境下合起来的 versionName 就是 "${versionName}.0" - versionName "2.0" + versionName "15.0" if(true) { versionName = genVersionName("${versionName}") } @@ -45,5 +45,5 @@ android { dependencies { api project(':libappbase') - api fileTree(dir: 'libs', include: ['*.jar']) + api fileTree(dir: 'libs', include: ['*.jar']) } diff --git a/appbase/build.properties b/appbase/build.properties index 9e59591..b0c800f 100644 --- a/appbase/build.properties +++ b/appbase/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Tue Feb 25 16:51:17 HKT 2025 -stageCount=3 +#Mon Mar 24 21:28:41 GMT 2025 +stageCount=11 libraryProject=libappbase -baseVersion=2.0 -publishVersion=2.0.2 -buildCount=0 -baseBetaVersion=2.0.3 +baseVersion=15.0 +publishVersion=15.0.10 +buildCount=12 +baseBetaVersion=15.0.11 diff --git a/appbase/src/main/AndroidManifest.xml b/appbase/src/main/AndroidManifest.xml index ed6e233..19f89ca 100644 --- a/appbase/src/main/AndroidManifest.xml +++ b/appbase/src/main/AndroidManifest.xml @@ -7,12 +7,13 @@ android:name=".App" android:icon="@drawable/ic_launcher" android:label="@string/app_name" - android:theme="@style/AppTheme" + android:theme="@style/MyAPPBaseTheme" android:resizeableActivity="true"> @@ -49,24 +50,38 @@ android:name=".services.MainService" android:exported="true"/> + + + + + + - - + + + + + + - + - + - + @@ -91,6 +106,10 @@ android:name="android.max_aspect" android:value="4.0"/> + diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/App.java b/appbase/src/main/java/cc/winboll/studio/appbase/App.java index 84d0424..74f9bbc 100644 --- a/appbase/src/main/java/cc/winboll/studio/appbase/App.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/App.java @@ -6,22 +6,22 @@ package cc.winboll.studio.appbase; * @Describe APPbase 应用类 */ import cc.winboll.studio.libappbase.GlobalApplication; -import cc.winboll.studio.libappbase.SOSCSBroadcastReceiver; import android.content.IntentFilter; +import cc.winboll.studio.libappbase.sos.SOSCenterServiceReceiver; +import cc.winboll.studio.libappbase.sos.SOS; public class App extends GlobalApplication { public static final String TAG = "App"; - SOSCSBroadcastReceiver mSOSCSBroadcastReceiver; + SOSCenterServiceReceiver mSOSCenterServiceReceiver; @Override public void onCreate() { super.onCreate(); - GlobalApplication.setIsDebuging(this, BuildConfig.DEBUG); - mSOSCSBroadcastReceiver = new SOSCSBroadcastReceiver(); + mSOSCenterServiceReceiver = new SOSCenterServiceReceiver(); IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(SOSCSBroadcastReceiver.ACTION_SOS); - registerReceiver(mSOSCSBroadcastReceiver, intentFilter); + intentFilter.addAction(SOS.ACTION_SOS); + registerReceiver(mSOSCenterServiceReceiver, intentFilter); } } diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/MainActivity.java b/appbase/src/main/java/cc/winboll/studio/appbase/MainActivity.java index 3e4cac0..b2b5842 100644 --- a/appbase/src/main/java/cc/winboll/studio/appbase/MainActivity.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/MainActivity.java @@ -1,28 +1,41 @@ package cc.winboll.studio.appbase; +import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.CheckBox; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.Toolbar; +import android.widget.Toolbar; import cc.winboll.studio.appbase.R; +import cc.winboll.studio.appbase.activities.NewActivity; import cc.winboll.studio.appbase.services.MainService; +import cc.winboll.studio.appbase.services.TestDemoBindService; +import cc.winboll.studio.appbase.services.TestDemoService; import cc.winboll.studio.libappbase.GlobalApplication; import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.LogView; -import cc.winboll.studio.libappbase.SOS; -import cc.winboll.studio.libappbase.SimpleOperateSignalCenterService; -import cc.winboll.studio.libappbase.bean.APPSOSBean; -import cc.winboll.studio.libappbase.services.TestService; +import cc.winboll.studio.libappbase.sos.SOS; +import cc.winboll.studio.libappbase.utils.ToastUtils; import cc.winboll.studio.libappbase.widgets.StatusWidget; -import com.hjq.toast.ToastUtils; +import cc.winboll.studio.libappbase.winboll.IWinBollActivity; +import cc.winboll.studio.libappbase.winboll.WinBollActivityManager; -public class MainActivity extends AppCompatActivity { +public class MainActivity extends Activity implements IWinBollActivity { public static final String TAG = "MainActivity"; + + @Override + public Activity getActivity() { + return this; + } + @Override + public String getTag() { + return TAG; + } + + Toolbar mToolbar; LogView mLogView; @Override @@ -31,14 +44,17 @@ public class MainActivity extends AppCompatActivity { ToastUtils.show("onCreate"); setContentView(R.layout.activity_main); - Toolbar toolbar = findViewById(R.id.activitymainToolbar1); - setSupportActionBar(toolbar); + mToolbar = findViewById(R.id.toolbar); + setActionBar(mToolbar); CheckBox cbIsDebugMode = findViewById(R.id.activitymainCheckBox1); cbIsDebugMode.setChecked(GlobalApplication.isDebuging()); mLogView = findViewById(R.id.activitymainLogView1); - if (GlobalApplication.isDebuging()) { mLogView.start(); } + if (GlobalApplication.isDebuging()) { + mLogView.start(); + ToastUtils.show("LogView start."); + } } @Override @@ -57,7 +73,8 @@ public class MainActivity extends AppCompatActivity { } public void onSwitchDebugMode(View view) { - GlobalApplication.setIsDebuging(this, ((CheckBox)view).isChecked()); + boolean isDebuging = ((CheckBox)view).isChecked(); + GlobalApplication.setIsDebuging(isDebuging); } public void onStartCenter(View view) { @@ -68,17 +85,17 @@ public class MainActivity extends AppCompatActivity { MainService.stopMainService(this); } - public void onTestStopWithoutSettingEnable(View view) { - LogUtils.d(TAG, "onTestStopWithoutSettingEnable"); - stopService(new Intent(this, SimpleOperateSignalCenterService.class)); + public void onTestStopMainServiceWithoutSettingEnable(View view) { + LogUtils.d(TAG, "onTestStopMainServiceWithoutSettingEnable"); + stopService(new Intent(this, MainService.class)); } - public void onTestStartWithString(View view) { - LogUtils.d(TAG, "onTestStartWithString"); + public void onTestUseComponentStartService(View view) { + LogUtils.d(TAG, "onTestUseComponentStartService"); // 目标服务的包名和类名 String packageName = this.getPackageName(); - String serviceClassName = SimpleOperateSignalCenterService.class.getName(); + String serviceClassName = TestDemoService.class.getName(); // 构建Intent Intent intentService = new Intent(); @@ -87,30 +104,59 @@ public class MainActivity extends AppCompatActivity { startService(intentService); } - public void onSOS(View view) { - Intent intent = new Intent(this, TestService.class); + public void onTestDemoServiceSOS(View view) { + Intent intent = new Intent(this, TestDemoService.class); stopService(intent); - SOS.sosWinBollService(this, new APPSOSBean(getPackageName(), TestService.class.getName())); + if (App.isDebuging()) { + SOS.sosToAppBaseBeta(this, TestDemoService.class.getName()); + } else { + SOS.sosToAppBase(this, TestDemoService.class.getName()); + } } - public void onStartTestService(View view) { - Intent intent = new Intent(this, TestService.class); - intent.setAction(SOS.ACTION_SERVICE_ENABLE); + public void onSartTestDemoService(View view) { + Intent intent = new Intent(this, TestDemoService.class); + intent.setAction(TestDemoService.ACTION_ENABLE); startService(intent); } - public void onStopTestService(View view) { - Intent intent = new Intent(this, TestService.class); - intent.setAction(SOS.ACTION_SERVICE_DISABLE); + public void onStopTestDemoService(View view) { + Intent intent = new Intent(this, TestDemoService.class); + intent.setAction(TestDemoService.ACTION_DISABLE); startService(intent); - - Intent intentStop = new Intent(this, TestService.class); + + Intent intentStop = new Intent(this, TestDemoService.class); stopService(intentStop); } - public void onStopTestServiceNoSettings(View view) { - Intent intent = new Intent(this, TestService.class); + public void onStopTestDemoServiceNoSettings(View view) { + Intent intent = new Intent(this, TestDemoService.class); stopService(intent); } + + public void onSartTestDemoBindService(View view) { + Intent intent = new Intent(this, TestDemoBindService.class); + intent.setAction(TestDemoBindService.ACTION_ENABLE); + startService(intent); + + } + + public void onStopTestDemoBindService(View view) { + Intent intent = new Intent(this, TestDemoBindService.class); + intent.setAction(TestDemoBindService.ACTION_DISABLE); + startService(intent); + + Intent intentStop = new Intent(this, TestDemoBindService.class); + stopService(intentStop); + } + + public void onStopTestDemoBindServiceNoSettings(View view) { + Intent intent = new Intent(this, TestDemoBindService.class); + stopService(intent); + } + + public void onTestOpenNewActivity(View view) { + WinBollActivityManager.getInstance(this).startWinBollActivity(this, NewActivity.class); + } } diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/MyTileService.java b/appbase/src/main/java/cc/winboll/studio/appbase/MyTileService.java index ab3b255..3f3fcca 100644 --- a/appbase/src/main/java/cc/winboll/studio/appbase/MyTileService.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/MyTileService.java @@ -7,7 +7,7 @@ package cc.winboll.studio.appbase; import android.content.Context; import android.service.quicksettings.Tile; import android.service.quicksettings.TileService; -import cc.winboll.studio.appbase.beans.MainServiceBean; +import cc.winboll.studio.appbase.models.MainServiceBean; import cc.winboll.studio.appbase.services.MainService; public class MyTileService extends TileService { diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/activities/NewActivity.java b/appbase/src/main/java/cc/winboll/studio/appbase/activities/NewActivity.java new file mode 100644 index 0000000..289be86 --- /dev/null +++ b/appbase/src/main/java/cc/winboll/studio/appbase/activities/NewActivity.java @@ -0,0 +1,41 @@ +package cc.winboll.studio.appbase.activities; + +import android.app.Activity; +import android.os.Bundle; +import android.view.View; +import cc.winboll.studio.appbase.R; +import cc.winboll.studio.libappbase.winboll.IWinBollActivity; +import cc.winboll.studio.libappbase.winboll.WinBollActivityManager; + +/** + * @Author ZhanGSKen@AliYun.Com + * @Date 2025/03/25 05:04:22 + */ +public class NewActivity extends Activity implements IWinBollActivity { + + public static final String TAG = "NewActivity"; + + @Override + public Activity getActivity() { + return this; + } + + @Override + public String getTag() { + return TAG; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_new); + } + + public void onCloseThisActivity(View view) { + WinBollActivityManager.getInstance(this).finish(this); + } + + public void onCloseAllActivity(View view) { + WinBollActivityManager.getInstance(this).finishAll(); + } +} diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/bean/SimpleOperateSignalCenterServiceBean.java b/appbase/src/main/java/cc/winboll/studio/appbase/models/MainServiceBean.java similarity index 81% rename from libappbase/src/main/java/cc/winboll/studio/libappbase/bean/SimpleOperateSignalCenterServiceBean.java rename to appbase/src/main/java/cc/winboll/studio/appbase/models/MainServiceBean.java index d6d3f00..5df134e 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/bean/SimpleOperateSignalCenterServiceBean.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/models/MainServiceBean.java @@ -1,20 +1,21 @@ -package cc.winboll.studio.libappbase.bean; +package cc.winboll.studio.appbase.models; + +/** + * @Author ZhanGSKen@AliYun.Com + * @Date 2025/02/13 07:06:13 + */ import android.util.JsonReader; import android.util.JsonWriter; import cc.winboll.studio.libappbase.BaseBean; import java.io.IOException; -/** - * @Author ZhanGSKen@AliYun.Com - * @Date 2025/02/13 04:27:42 - */ -public class SimpleOperateSignalCenterServiceBean extends BaseBean { +public class MainServiceBean extends BaseBean { - public static final String TAG = "SimpleOperateSignalCenterServiceBean"; + public static final String TAG = "MainServiceBean"; boolean isEnable; - - public SimpleOperateSignalCenterServiceBean() { + + public MainServiceBean() { this.isEnable = false; } @@ -28,7 +29,7 @@ public class SimpleOperateSignalCenterServiceBean extends BaseBean { @Override public String getName() { - return SimpleOperateSignalCenterServiceBean.class.getName(); + return MainServiceBean.class.getName(); } @Override diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/bean/TestServiceBean.java b/appbase/src/main/java/cc/winboll/studio/appbase/models/TestDemoBindServiceBean.java similarity index 87% rename from libappbase/src/main/java/cc/winboll/studio/libappbase/bean/TestServiceBean.java rename to appbase/src/main/java/cc/winboll/studio/appbase/models/TestDemoBindServiceBean.java index 30d8cfe..f702494 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/bean/TestServiceBean.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/models/TestDemoBindServiceBean.java @@ -1,8 +1,8 @@ -package cc.winboll.studio.libappbase.bean; +package cc.winboll.studio.appbase.models; /** * @Author ZhanGSKen@AliYun.Com - * @Date 2025/02/19 13:34:52 + * @Date 2025/03/07 12:47:22 * @Describe TestServiceBean */ import android.util.JsonReader; @@ -10,13 +10,13 @@ import android.util.JsonWriter; import cc.winboll.studio.libappbase.BaseBean; import java.io.IOException; -public class TestServiceBean extends BaseBean { +public class TestDemoBindServiceBean extends BaseBean { public static final String TAG = "TestServiceBean"; boolean isEnable; - public TestServiceBean() { + public TestDemoBindServiceBean() { this.isEnable = false; } @@ -30,7 +30,7 @@ public class TestServiceBean extends BaseBean { @Override public String getName() { - return TestServiceBean.class.getName(); + return TestDemoBindServiceBean.class.getName(); } @Override diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/models/TestDemoServiceBean.java b/appbase/src/main/java/cc/winboll/studio/appbase/models/TestDemoServiceBean.java new file mode 100644 index 0000000..90f7518 --- /dev/null +++ b/appbase/src/main/java/cc/winboll/studio/appbase/models/TestDemoServiceBean.java @@ -0,0 +1,68 @@ +package cc.winboll.studio.appbase.models; + +/** + * @Author ZhanGSKen@AliYun.Com + * @Date 2025/03/07 12:49:21 + * @Describe TestDemoServiceBean + */ +import android.util.JsonReader; +import android.util.JsonWriter; +import cc.winboll.studio.libappbase.BaseBean; +import java.io.IOException; + +public class TestDemoServiceBean extends BaseBean { + + public static final String TAG = "TestDemoServiceBean"; + + boolean isEnable; + + public TestDemoServiceBean() { + this.isEnable = false; + } + + public void setIsEnable(boolean isEnable) { + this.isEnable = isEnable; + } + + public boolean isEnable() { + return isEnable; + } + + @Override + public String getName() { + return TestDemoServiceBean.class.getName(); + } + + @Override + public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException { + super.writeThisToJsonWriter(jsonWriter); + jsonWriter.name("isEnable").value(isEnable()); + + } + + @Override + public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException { + if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else { + if (name.equals("isEnable")) { + setIsEnable(jsonReader.nextBoolean()); + } else { + return false; + } + } + return true; + } + + @Override + public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException { + jsonReader.beginObject(); + while (jsonReader.hasNext()) { + String name = jsonReader.nextName(); + if (!initObjectsFromJsonReader(jsonReader, name)) { + jsonReader.skipValue(); + } + } + // 结束 JSON 对象 + jsonReader.endObject(); + return this; + } +} diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/beans/SOSReportBean.java b/appbase/src/main/java/cc/winboll/studio/appbase/models/WinBollNewsBean.java similarity index 64% rename from appbase/src/main/java/cc/winboll/studio/appbase/beans/SOSReportBean.java rename to appbase/src/main/java/cc/winboll/studio/appbase/models/WinBollNewsBean.java index d579482..66ee6b6 100644 --- a/appbase/src/main/java/cc/winboll/studio/appbase/beans/SOSReportBean.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/models/WinBollNewsBean.java @@ -1,4 +1,4 @@ -package cc.winboll.studio.appbase.beans; +package cc.winboll.studio.appbase.models; /** * @Author ZhanGSKen@AliYun.Com @@ -10,45 +10,45 @@ import android.util.JsonWriter; import cc.winboll.studio.libappbase.BaseBean; import java.io.IOException; -public class SOSReportBean extends BaseBean { +public class WinBollNewsBean extends BaseBean { - public static final String TAG = "APPSOSReportBean"; + public static final String TAG = "WinBollNewsBean"; - protected String sosReport; + protected String message; - public SOSReportBean() { - this.sosReport = ""; + public WinBollNewsBean() { + this.message = ""; } - public SOSReportBean(String sosReport) { - this.sosReport = sosReport; + public WinBollNewsBean(String message) { + this.message = message; } - public void setSosReport(String sosReport) { - this.sosReport = sosReport; + public void setMessage(String message) { + this.message = message; } - public String getSosReport() { - return sosReport; + public String getMessage() { + return message; } @Override public String getName() { - return SOSReportBean.class.getName(); + return WinBollNewsBean.class.getName(); } @Override public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException { super.writeThisToJsonWriter(jsonWriter); - jsonWriter.name("sosReport").value(getSosReport()); + jsonWriter.name("message").value(getMessage()); } @Override public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException { if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else { - if (name.equals("sosReport")) { - setSosReport(jsonReader.nextString()); + if (name.equals("message")) { + setMessage(jsonReader.nextString()); } else { return false; } diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/widgets/SOSWidgetClickListener.java b/appbase/src/main/java/cc/winboll/studio/appbase/receivers/APPNewsWidgetClickListener.java similarity index 55% rename from appbase/src/main/java/cc/winboll/studio/appbase/widgets/SOSWidgetClickListener.java rename to appbase/src/main/java/cc/winboll/studio/appbase/receivers/APPNewsWidgetClickListener.java index 42dc31f..70561c9 100644 --- a/appbase/src/main/java/cc/winboll/studio/appbase/widgets/SOSWidgetClickListener.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/receivers/APPNewsWidgetClickListener.java @@ -1,20 +1,20 @@ -package cc.winboll.studio.appbase.widgets; +package cc.winboll.studio.appbase.receivers; /** * @Author ZhanGSKen@AliYun.Com - * @Date 2025/02/15 17:20:46 - * @Describe WidgetButtonClickListener + * @Date 2025/03/24 07:11:44 */ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import cc.winboll.studio.appbase.widgets.APPNewsWidget; import cc.winboll.studio.libappbase.LogUtils; -public class SOSWidgetClickListener extends BroadcastReceiver { +public class APPNewsWidgetClickListener extends BroadcastReceiver { - public static final String TAG = "SOSWidgetClickListener"; - public static final String ACTION_PRE = "cc.winboll.studio.appbase.widgets.SOSWidgetClickListener.ACTION_PRE"; - public static final String ACTION_NEXT = "cc.winboll.studio.appbase.widgets.SOSWidgetClickListener.ACTION_NEXT"; + public static final String TAG = "APPNewsWidgetClickListener"; + public static final String ACTION_PRE = APPNewsWidgetClickListener.class.getName() + ".ACTION_PRE"; + public static final String ACTION_NEXT = APPNewsWidgetClickListener.class.getName() + ".ACTION_NEXT"; @Override public void onReceive(Context context, Intent intent) { @@ -25,10 +25,10 @@ public class SOSWidgetClickListener extends BroadcastReceiver { } if (action.equals(ACTION_PRE)) { LogUtils.d(TAG, "ACTION_PRE"); - SOSWidget.prePage(context); + APPNewsWidget.prePage(context); } else if (action.equals(ACTION_NEXT)) { LogUtils.d(TAG, "ACTION_NEXT"); - SOSWidget.nextPage(context); + APPNewsWidget.nextPage(context); } else { LogUtils.d(TAG, String.format("action %s", action)); } diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/receivers/MainReceiver.java b/appbase/src/main/java/cc/winboll/studio/appbase/receivers/MainReceiver.java index 36b12ed..498f877 100644 --- a/appbase/src/main/java/cc/winboll/studio/appbase/receivers/MainReceiver.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/receivers/MainReceiver.java @@ -5,20 +5,21 @@ package cc.winboll.studio.appbase.receivers; * @Date 2025/02/13 06:58:04 * @Describe 主要广播接收器 */ -import android.appwidget.AppWidgetManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import cc.winboll.studio.appbase.beans.SOSReportBean; +import cc.winboll.studio.appbase.models.WinBollNewsBean; import cc.winboll.studio.appbase.services.MainService; -import cc.winboll.studio.appbase.widgets.SOSWidget; +import cc.winboll.studio.appbase.widgets.APPNewsWidget; import cc.winboll.studio.libappbase.AppUtils; import cc.winboll.studio.libappbase.LogUtils; -import cc.winboll.studio.libappbase.SOS; -import cc.winboll.studio.libappbase.bean.APPSOSBean; -import com.hjq.toast.ToastUtils; +import cc.winboll.studio.libappbase.sos.APPModel; +import cc.winboll.studio.libappbase.sos.SOS; +import cc.winboll.studio.libappbase.sos.SOSObject; +import cc.winboll.studio.libappbase.sos.WinBoll; +import cc.winboll.studio.libappbase.utils.ToastUtils; import java.io.IOException; import java.lang.ref.WeakReference; import java.text.SimpleDateFormat; @@ -27,12 +28,10 @@ import java.util.Date; public class MainReceiver extends BroadcastReceiver { public static final String TAG = "MainReceiver"; + public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED"; + WeakReference mwrService; - // 存储电量指示值, - // 用于校验电量消息时的电量变化 - static volatile int _mnTheQuantityOfElectricityOld = -1; - static volatile boolean _mIsCharging = false; public MainReceiver(MainService service) { mwrService = new WeakReference(service); @@ -43,74 +42,62 @@ public class MainReceiver extends BroadcastReceiver { String szAction = intent.getAction(); if (szAction.equals(ACTION_BOOT_COMPLETED)) { ToastUtils.show("ACTION_BOOT_COMPLETED"); - } else if (szAction.equals(SOS.ACTION_BIND)) { + } else if (szAction.equals(WinBoll.ACTION_BIND)) { LogUtils.d(TAG, "ACTION_BIND"); LogUtils.d(TAG, String.format("context.getPackageName() %s", context.getPackageName())); LogUtils.d(TAG, String.format("intent.getAction() %s", intent.getAction())); - String SOS = intent.getStringExtra("SOS"); - LogUtils.d(TAG, String.format("SOS %s", SOS)); - if (SOS != null && SOS.equals("Service")) { - String szAPPSOSBean = intent.getStringExtra("APPSOSBean"); - LogUtils.d(TAG, String.format("szAPPSOSBean %s", szAPPSOSBean)); - if (szAPPSOSBean != null && !szAPPSOSBean.equals("")) { - try { - APPSOSBean bean = APPSOSBean.parseStringToBean(szAPPSOSBean, APPSOSBean.class); - if (bean != null) { - String sosPackage = bean.getSosPackage(); - LogUtils.d(TAG, String.format("sosPackage %s", sosPackage)); - String sosClassName = bean.getSosClassName(); - LogUtils.d(TAG, String.format("sosClassName %s", sosClassName)); - mwrService.get().bindSOSConnection(bean); - } - } catch (IOException e) { - LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); + String szAPPModel = intent.getStringExtra(WinBoll.EXTRA_APPMODEL); + LogUtils.d(TAG, String.format("szAPPModel %s", szAPPModel)); + if (szAPPModel != null && !szAPPModel.equals("")) { + try { + APPModel bean = APPModel.parseStringToBean(szAPPModel, APPModel.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)); + mwrService.get().bindAPPModelConnection(bean); } + } catch (IOException e) { + LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); } } } else if (intent.getAction().equals(SOS.ACTION_SOS)) { LogUtils.d(TAG, "ACTION_SOS"); - LogUtils.d(TAG, String.format("context.getPackageName() %s", context.getPackageName())); - LogUtils.d(TAG, String.format("intent.getAction() %s", intent.getAction())); - String SOS = intent.getStringExtra("SOS"); - LogUtils.d(TAG, String.format("SOS %s", SOS)); - if (SOS != null && SOS.equals("Service")) { - String szAPPSOSBean = intent.getStringExtra("APPSOSBean"); - LogUtils.d(TAG, String.format("szAPPSOSBean %s", szAPPSOSBean)); - if (szAPPSOSBean != null && !szAPPSOSBean.equals("")) { - try { - APPSOSBean bean = APPSOSBean.parseStringToBean(szAPPSOSBean, APPSOSBean.class); - if (bean != null) { - String sosPackage = bean.getSosPackage(); - LogUtils.d(TAG, String.format("sosPackage %s", sosPackage)); - String sosClassName = bean.getSosClassName(); - LogUtils.d(TAG, String.format("sosClassName %s", sosClassName)); + 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(sosPackage, sosClassName)); - context.startService(intentService); + Intent intentService = new Intent(); + intentService.setComponent(new ComponentName(szObjectPackageName, szObjectServiveName)); + context.startService(intentService); - String appName = AppUtils.getAppNameByPackageName(context, sosPackage); - LogUtils.d(TAG, String.format("appName %s", appName)); - SOSReportBean appSOSReportBean = new SOSReportBean(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); - appSOSReportBean.setSosReport(sbLine.toString()); + 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()); - SOSWidget.addAPPSOSReportBean(context, appSOSReportBean); - - Intent intentWidget = new Intent(context, SOSWidget.class); - intentWidget.setAction(SOSWidget.ACTION_RELOAD_REPORT); - context.sendBroadcast(intentWidget); - } - } catch (IOException e) { - LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); - } + APPNewsWidget.addWinBollNewsBean(context, appWinBollNewsBean); + + Intent intentWidget = new Intent(context, APPNewsWidget.class); + intentWidget.setAction(APPNewsWidget.ACTION_RELOAD_REPORT); + context.sendBroadcast(intentWidget); } + + } } else { ToastUtils.show(szAction); @@ -123,9 +110,7 @@ public class MainReceiver extends BroadcastReceiver { IntentFilter filter=new IntentFilter(); filter.addAction(ACTION_BOOT_COMPLETED); filter.addAction(SOS.ACTION_SOS); - filter.addAction(SOS.ACTION_BIND); - filter.addAction(SOS.ACTION_SERVICE_ENABLE); - filter.addAction(SOS.ACTION_SERVICE_DISABLE); + filter.addAction(WinBoll.ACTION_BIND); //filter.addAction(Intent.ACTION_BATTERY_CHANGED); service.registerReceiver(this, filter); } diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/services/AssistantService.java b/appbase/src/main/java/cc/winboll/studio/appbase/services/AssistantService.java index b2e2f9b..8db3f50 100644 --- a/appbase/src/main/java/cc/winboll/studio/appbase/services/AssistantService.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/services/AssistantService.java @@ -11,7 +11,7 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; -import cc.winboll.studio.appbase.beans.MainServiceBean; +import cc.winboll.studio.appbase.models.MainServiceBean; import cc.winboll.studio.appbase.services.AssistantService; import cc.winboll.studio.appbase.services.MainService; import cc.winboll.studio.libappbase.LogUtils; diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/services/MainService.java b/appbase/src/main/java/cc/winboll/studio/appbase/services/MainService.java index 93e41b7..fdbbd62 100644 --- a/appbase/src/main/java/cc/winboll/studio/appbase/services/MainService.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/services/MainService.java @@ -18,15 +18,15 @@ import android.content.ServiceConnection; import android.os.Binder; import android.os.IBinder; import cc.winboll.studio.appbase.MyTileService; -import cc.winboll.studio.appbase.beans.MainServiceBean; +import cc.winboll.studio.appbase.models.MainServiceBean; import cc.winboll.studio.appbase.handlers.MainServiceHandler; import cc.winboll.studio.appbase.receivers.MainReceiver; import cc.winboll.studio.appbase.services.AssistantService; import cc.winboll.studio.appbase.threads.MainServiceThread; -import cc.winboll.studio.appbase.widgets.SOSWidget; +import cc.winboll.studio.appbase.widgets.APPNewsWidget; import cc.winboll.studio.libappbase.LogUtils; -import cc.winboll.studio.libappbase.bean.APPSOSBean; import java.util.ArrayList; +import cc.winboll.studio.libappbase.sos.APPModel; public class MainService extends Service { @@ -45,7 +45,7 @@ public class MainService extends Service { AssistantService mAssistantService; boolean isBound = false; MainReceiver mMainReceiver; - ArrayList mSOSConnectionList; + ArrayList mAPPModelConnectionList; @Override public IBinder onBind(Intent intent) { @@ -60,7 +60,7 @@ public class MainService extends Service { public void onCreate() { super.onCreate(); LogUtils.d(TAG, "onCreate()"); - mSOSConnectionList = new ArrayList(); + mAPPModelConnectionList = new ArrayList(); _mControlCenterService = MainService.this; isServiceRunning = false; @@ -101,8 +101,8 @@ public class MainService extends Service { } // 启动小部件 - Intent intentTimeWidget = new Intent(this, SOSWidget.class); - intentTimeWidget.setAction(SOSWidget.ACTION_RELOAD_REPORT); + Intent intentTimeWidget = new Intent(this, APPNewsWidget.class); + intentTimeWidget.setAction(APPNewsWidget.ACTION_RELOAD_REPORT); this.sendBroadcast(intentTimeWidget); startMainServiceThread(); @@ -117,21 +117,11 @@ public class MainService extends Service { // void wakeupAndBindAssistant() { LogUtils.d(TAG, "wakeupAndBindAssistant()"); -// if (ServiceUtils.isServiceAlive(getApplicationContext(), AssistantService.class.getName()) == false) { -// startService(new Intent(MainService.this, AssistantService.class)); -// //LogUtils.d(TAG, "call wakeupAndBindAssistant() : Binding... AssistantService"); -// bindService(new Intent(MainService.this, AssistantService.class), mMyServiceConnection, Context.BIND_IMPORTANT); -// } + Intent intent = new Intent(this, AssistantService.class); startService(intent); // 绑定服务的Intent - //Intent intent = new Intent(this, AssistantService.class); bindService(intent, mMyServiceConnection, Context.BIND_IMPORTANT); - -// Intent intent = new Intent(this, AssistantService.class); -// startService(intent); -// LogUtils.d(TAG, "startService(intent)"); -// bindService(new Intent(this, AssistantService.class), mMyServiceConnection, Context.BIND_IMPORTANT); } // 开启提醒铃声线程 @@ -192,40 +182,40 @@ public class MainService extends Service { } } - public void bindSOSConnection(APPSOSBean bean) { - LogUtils.d(TAG, "bindSOSConnection(...)"); + public void bindAPPModelConnection(APPModel bean) { + LogUtils.d(TAG, "bindAPPModelConnection(...)"); // 清理旧的绑定链接 - for (int i = mSOSConnectionList.size() - 1; i > -1; i--) { - SOSConnection item = mSOSConnectionList.get(i); - if (item.isBindToAPPSOSBean(bean)) { + for (int i = mAPPModelConnectionList.size() - 1; i > -1; i--) { + APPConnection item = mAPPModelConnectionList.get(i); + if (item.isBindToAPP(bean)) { LogUtils.d(TAG, "Bind Servive exist."); unbindService(item); - mSOSConnectionList.remove(i); + mAPPModelConnectionList.remove(i); } } // 绑定服务 - SOSConnection sosConnection = new SOSConnection(); + APPConnection appConnection = new APPConnection(); Intent intentService = new Intent(); - intentService.setComponent(new ComponentName(bean.getSosPackage(), bean.getSosClassName())); - bindService(intentService, sosConnection, Context.BIND_IMPORTANT); - mSOSConnectionList.add(sosConnection); + intentService.setComponent(new ComponentName(bean.getAppPackageName(), bean.getAppMainServiveName())); + bindService(intentService, appConnection, Context.BIND_IMPORTANT); + mAPPModelConnectionList.add(appConnection); - Intent intentWidget = new Intent(this, SOSWidget.class); - intentWidget.setAction(SOSWidget.ACTION_WAKEUP_SERVICE); - APPSOSBean appSOSBean = new APPSOSBean(bean.getSosPackage(), bean.getSosClassName()); + Intent intentWidget = new Intent(this, APPNewsWidget.class); + intentWidget.setAction(APPNewsWidget.ACTION_WAKEUP_SERVICE); + APPModel appSOSBean = new APPModel(bean.getAppPackageName(), bean.getAppMainServiveName()); intentWidget.putExtra("APPSOSBean", appSOSBean.toString()); sendBroadcast(intentWidget); } - public class SOSConnection implements ServiceConnection { + public class APPConnection implements ServiceConnection { ComponentName mComponentName; - boolean isBindToAPPSOSBean(APPSOSBean bean) { + boolean isBindToAPP(APPModel bean) { return mComponentName != null - && mComponentName.getClassName().equals(bean.getSosClassName()) - && mComponentName.getPackageName().equals(bean.getSosPackage()); + && mComponentName.getClassName().equals(bean.getAppMainServiveName()) + && mComponentName.getPackageName().equals(bean.getAppPackageName()); } @Override @@ -241,13 +231,13 @@ public class MainService extends Service { LogUtils.d(TAG, String.format("onServiceDisconnected : \ngetClassName %s\ngetPackageName %s", name.getClassName(), name.getPackageName())); // 尝试无参数启动一下服务 - String sosPackage = mComponentName.getPackageName(); - LogUtils.d(TAG, String.format("sosPackage %s", sosPackage)); - String sosClassName = mComponentName.getClassName(); - LogUtils.d(TAG, String.format("sosClassName %s", sosClassName)); + String appPackage = mComponentName.getPackageName(); + LogUtils.d(TAG, String.format("appPackage %s", appPackage)); + String appMainServiceClassName = mComponentName.getClassName(); + LogUtils.d(TAG, String.format("appMainServiceClassName %s", appMainServiceClassName)); Intent intentService = new Intent(); - intentService.setComponent(new ComponentName(sosPackage, sosClassName)); + intentService.setComponent(new ComponentName(appPackage, appMainServiceClassName)); startService(intentService); } diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/services/TestDemoBindService.java b/appbase/src/main/java/cc/winboll/studio/appbase/services/TestDemoBindService.java new file mode 100644 index 0000000..14209de --- /dev/null +++ b/appbase/src/main/java/cc/winboll/studio/appbase/services/TestDemoBindService.java @@ -0,0 +1,178 @@ +package cc.winboll.studio.appbase.services; + +/** + * @Author ZhanGSKen@AliYun.Com + * @Date 2025/03/07 12:45:49 + * @Describe 启动时申请绑定到APPBase主服务的服务示例 + */ +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; +import cc.winboll.studio.appbase.models.TestDemoBindServiceBean; +import cc.winboll.studio.libappbase.LogUtils; +import cc.winboll.studio.libappbase.sos.WinBoll; +import cc.winboll.studio.appbase.App; +import cc.winboll.studio.libappbase.sos.SOS; + +public class TestDemoBindService extends Service { + + public static final String TAG = "TestDemoBindService"; + + public static final String ACTION_ENABLE = TestDemoBindService.class.getName() + ".ACTION_ENABLE"; + public static final String ACTION_DISABLE = TestDemoBindService.class.getName() + ".ACTION_DISABLE"; + + volatile static TestThread _TestThread; + + volatile static boolean _IsRunning; + + public synchronized static void setIsRunning(boolean isRunning) { + _IsRunning = isRunning; + } + + public static boolean isRunning() { + return _IsRunning; + } + + @Override + public IBinder onBind(Intent intent) { + return new MyBinder(); + } + + public class MyBinder extends Binder { + public TestDemoBindService getService() { + return TestDemoBindService.this; + } + } + + @Override + public void onCreate() { + super.onCreate(); + LogUtils.d(TAG, "onCreate()"); + + run(); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + LogUtils.d(TAG, "onStartCommand(...)"); + TestDemoBindServiceBean bean = TestDemoBindServiceBean.loadBean(this, TestDemoBindServiceBean.class); + if (bean == null) { + bean = new TestDemoBindServiceBean(); + } + + if (intent.getAction() != null) { + if (intent.getAction().equals(ACTION_ENABLE)) { + bean.setIsEnable(true); + LogUtils.d(TAG, "setIsEnable(true);"); + TestDemoBindServiceBean.saveBean(this, bean); + } else if (intent.getAction().equals(ACTION_DISABLE)) { + bean.setIsEnable(false); + LogUtils.d(TAG, "setIsEnable(false);"); + TestDemoBindServiceBean.saveBean(this, bean); + } + } + + run(); + + return (bean.isEnable()) ? START_STICKY : super.onStartCommand(intent, flags, startId); + //return super.onStartCommand(intent, flags, startId); + } + + void run() { + LogUtils.d(TAG, "run()"); + TestDemoBindServiceBean bean = TestDemoBindServiceBean.loadBean(this, TestDemoBindServiceBean.class); + if (bean == null) { + bean = new TestDemoBindServiceBean(); + TestDemoBindServiceBean.saveBean(this, bean); + } + if (bean.isEnable()) { + LogUtils.d(TAG, "run() bean.isEnable()"); + TestThread.getInstance(this).start(); + LogUtils.d(TAG, "_TestThread.start()"); + } + } + + + @Override + public void onDestroy() { + super.onDestroy(); + LogUtils.d(TAG, "onDestroy()"); + TestDemoBindServiceBean bean = TestDemoBindServiceBean.loadBean(this, TestDemoBindServiceBean.class); + if (bean == null) { + bean = new TestDemoBindServiceBean(); + } + + TestThread.getInstance(this).setIsExit(true); + + // 预防 APPBase 应用重启绑定失效。 + // 所以退出时检查本服务是否配置启用,如果启用就发送一个 SOS 信号。 + // 这样 APPBase 就会用组件方式启动本服务。 + if (bean.isEnable()) { + if (App.isDebuging()) { + SOS.sosToAppBaseBeta(this, TestDemoBindService.class.getName()); + } else { + SOS.sosToAppBase(this, TestDemoBindService.class.getName()); + } + } + + _IsRunning = false; + } + + static class TestThread extends Thread { + + volatile static TestThread _TestThread; + Context mContext; + volatile boolean isStarted = false; + volatile boolean isExit = false; + + TestThread(Context context) { + super(); + mContext = context; + } + + public static synchronized TestThread getInstance(Context context) { + if (_TestThread != null) { + _TestThread.setIsExit(true); + } + _TestThread = new TestThread(context); + + return _TestThread; + } + + public synchronized void setIsExit(boolean isExit) { + this.isExit = isExit; + } + + public boolean isExit() { + return isExit; + } + + @Override + public void run() { + if (isStarted == false) { + isStarted = true; + super.run(); + LogUtils.d(TAG, "run() start"); + if (App.isDebuging()) { + WinBoll.bindToAPPBaseBeta(mContext, TestDemoBindService.class.getName()); + } else { + WinBoll.bindToAPPBase(mContext, TestDemoBindService.class.getName()); + } + + while (!isExit()) { + LogUtils.d(TAG, "run()"); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); + } + } + + LogUtils.d(TAG, "run() exit"); + } + } + } +} diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/services/TestService.java b/appbase/src/main/java/cc/winboll/studio/appbase/services/TestDemoService.java similarity index 67% rename from libappbase/src/main/java/cc/winboll/studio/libappbase/services/TestService.java rename to appbase/src/main/java/cc/winboll/studio/appbase/services/TestDemoService.java index fc86253..6098dce 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/services/TestService.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/services/TestDemoService.java @@ -1,23 +1,25 @@ -package cc.winboll.studio.libappbase.services; +package cc.winboll.studio.appbase.services; /** * @Author ZhanGSKen@AliYun.Com - * @Date 2025/02/15 20:48:36 - * @Describe TestService + * @Date 2025/03/07 12:39:24 + * @Describe 普通服务示例 */ import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.IBinder; +import cc.winboll.studio.appbase.models.TestDemoServiceBean; import cc.winboll.studio.libappbase.LogUtils; -import cc.winboll.studio.libappbase.SOS; -import cc.winboll.studio.libappbase.bean.APPSOSBean; -import cc.winboll.studio.libappbase.bean.TestServiceBean; +import cc.winboll.studio.libappbase.sos.WinBoll; -public class TestService extends Service { +public class TestDemoService extends Service { - public static final String TAG = "TestService"; + public static final String TAG = "TestDemoService"; + + public static final String ACTION_ENABLE = TestDemoService.class.getName() + ".ACTION_ENABLE"; + public static final String ACTION_DISABLE = TestDemoService.class.getName() + ".ACTION_DISABLE"; volatile static TestThread _TestThread; @@ -37,8 +39,8 @@ public class TestService extends Service { } public class MyBinder extends Binder { - public TestService getService() { - return TestService.this; + public TestDemoService getService() { + return TestDemoService.this; } } @@ -54,29 +56,35 @@ public class TestService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { LogUtils.d(TAG, "onStartCommand(...)"); - TestServiceBean bean = TestServiceBean.loadBean(this, TestServiceBean.class); + TestDemoServiceBean bean = TestDemoServiceBean.loadBean(this, TestDemoServiceBean.class); if (bean == null) { - bean = new TestServiceBean(); + bean = new TestDemoServiceBean(); } - if (intent.getAction() != null && intent.getAction().equals(SOS.ACTION_SERVICE_ENABLE)) { - bean.setIsEnable(true); - TestServiceBean.saveBean(this, bean); - run(); - } else if (intent.getAction() != null && intent.getAction().equals(SOS.ACTION_SERVICE_DISABLE)) { - bean.setIsEnable(false); - TestServiceBean.saveBean(this, bean); + + if (intent.getAction() != null) { + if (intent.getAction().equals(ACTION_ENABLE)) { + bean.setIsEnable(true); + LogUtils.d(TAG, "setIsEnable(true);"); + TestDemoServiceBean.saveBean(this, bean); + } else if (intent.getAction().equals(ACTION_DISABLE)) { + bean.setIsEnable(false); + LogUtils.d(TAG, "setIsEnable(false);"); + TestDemoServiceBean.saveBean(this, bean); + } } - LogUtils.d(TAG, String.format("TestServiceBean.saveBean setIsEnable %s", bean.isEnable())); + + run(); + return (bean.isEnable()) ? START_STICKY : super.onStartCommand(intent, flags, startId); //return super.onStartCommand(intent, flags, startId); } void run() { LogUtils.d(TAG, "run()"); - TestServiceBean bean = TestServiceBean.loadBean(this, TestServiceBean.class); + TestDemoServiceBean bean = TestDemoServiceBean.loadBean(this, TestDemoServiceBean.class); if (bean == null) { - bean = new TestServiceBean(); - TestServiceBean.saveBean(this, bean); + bean = new TestDemoServiceBean(); + TestDemoServiceBean.saveBean(this, bean); } if (bean.isEnable()) { LogUtils.d(TAG, "run() bean.isEnable()"); @@ -91,7 +99,7 @@ public class TestService extends Service { super.onDestroy(); LogUtils.d(TAG, "onDestroy()"); TestThread.getInstance(this).setIsExit(true); - + _IsRunning = false; } @@ -130,7 +138,6 @@ public class TestService extends Service { isStarted = true; super.run(); LogUtils.d(TAG, "run() start"); - SOS.bindToAPPService(mContext, new APPSOSBean(mContext.getPackageName(), TestService.class.getName())); while (!isExit()) { LogUtils.d(TAG, "run()"); diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/widgets/SOSWidget.java b/appbase/src/main/java/cc/winboll/studio/appbase/widgets/APPNewsWidget.java similarity index 53% rename from appbase/src/main/java/cc/winboll/studio/appbase/widgets/SOSWidget.java rename to appbase/src/main/java/cc/winboll/studio/appbase/widgets/APPNewsWidget.java index b614da9..c844983 100644 --- a/appbase/src/main/java/cc/winboll/studio/appbase/widgets/SOSWidget.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/widgets/APPNewsWidget.java @@ -12,31 +12,33 @@ import android.content.Context; import android.content.Intent; import android.widget.RemoteViews; import cc.winboll.studio.appbase.R; -import cc.winboll.studio.appbase.beans.SOSReportBean; +import cc.winboll.studio.appbase.models.WinBollNewsBean; +import cc.winboll.studio.appbase.receivers.APPNewsWidgetClickListener; import cc.winboll.studio.libappbase.AppUtils; import cc.winboll.studio.libappbase.LogUtils; -import cc.winboll.studio.libappbase.bean.APPSOSBean; +import cc.winboll.studio.libappbase.sos.APPModel; +import cc.winboll.studio.libappbase.sos.WinBoll; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; -public class SOSWidget extends AppWidgetProvider { +public class APPNewsWidget extends AppWidgetProvider { - public static final String TAG = "SOSWidget"; + public static final String TAG = "APPNewsWidget"; - public static final String ACTION_WAKEUP_SERVICE = "cc.winboll.studio.appbase.widgets.SOSWidget.ACTION_WAKEUP_SERVICE"; - public static final String ACTION_RELOAD_REPORT = "cc.winboll.studio.appbase.widgets.SOSWidget.ACTION_RELOAD_REPORT"; + public static final String ACTION_WAKEUP_SERVICE = APPNewsWidget.class.getName() + ".ACTION_WAKEUP_SERVICE"; + public static final String ACTION_RELOAD_REPORT = APPNewsWidget.class.getName() + ".ACTION_RELOAD_REPORT"; - volatile static ArrayList _SOSReportBeanList; + volatile static ArrayList _WinBollNewsBeanList; final static int _MAX_PAGES = 10; final static int _OnePageLinesCount = 5; volatile static int _CurrentPageIndex = 0; @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { - initAPPSOSReportBeanList(context); + initWinBollNewsBeanList(context); for (int appWidgetId : appWidgetIds) { updateAppWidget(context, appWidgetManager, appWidgetId); } @@ -45,31 +47,31 @@ public class SOSWidget extends AppWidgetProvider { @Override public void onReceive(Context context, Intent intent) { super.onReceive(context, intent); - initAPPSOSReportBeanList(context); + initWinBollNewsBeanList(context); if (intent.getAction().equals(ACTION_RELOAD_REPORT)) { LogUtils.d(TAG, "ACTION_RELOAD_REPORT"); AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); - int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, SOSWidget.class)); + int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, APPNewsWidget.class)); for (int appWidgetId : appWidgetIds) { updateAppWidget(context, appWidgetManager, appWidgetId); } }else if (intent.getAction().equals(ACTION_WAKEUP_SERVICE)) { LogUtils.d(TAG, "ACTION_WAKEUP_SERVICE"); - String szAPPSOSBean = intent.getStringExtra("APPSOSBean"); - LogUtils.d(TAG, String.format("szAPPSOSBean %s", szAPPSOSBean)); - if (szAPPSOSBean != null && !szAPPSOSBean.equals("")) { + String szAPPModel = intent.getStringExtra(WinBoll.EXTRA_APPMODEL); + LogUtils.d(TAG, String.format("szAPPModel %s", szAPPModel)); + if (szAPPModel != null && !szAPPModel.equals("")) { try { - APPSOSBean bean = APPSOSBean.parseStringToBean(szAPPSOSBean, APPSOSBean.class); + APPModel bean = APPModel.parseStringToBean(szAPPModel, APPModel.class); if (bean != null) { - String sosPackage = bean.getSosPackage(); - LogUtils.d(TAG, String.format("sosPackage %s", sosPackage)); - String sosClassName = bean.getSosClassName(); - LogUtils.d(TAG, String.format("sosClassName %s", sosClassName)); + 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, sosPackage); + String appName = AppUtils.getAppNameByPackageName(context, szAppPackageName); LogUtils.d(TAG, String.format("appName %s", appName)); - SOSReportBean appSOSReportBean = new SOSReportBean(appName); + WinBollNewsBean winBollNewsBean = new WinBollNewsBean(appName); SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); String currentTime = sdf.format(new Date()); StringBuilder sbLine = new StringBuilder(); @@ -77,12 +79,12 @@ public class SOSWidget extends AppWidgetProvider { sbLine.append(currentTime); sbLine.append("] Wake up "); sbLine.append(appName); - appSOSReportBean.setSosReport(sbLine.toString()); + winBollNewsBean.setMessage(sbLine.toString()); - addAPPSOSReportBean(context, appSOSReportBean); + addWinBollNewsBean(context, winBollNewsBean); AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); - int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, SOSWidget.class)); + int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, APPNewsWidget.class)); for (int appWidgetId : appWidgetIds) { updateAppWidget(context, appWidgetManager, appWidgetId); } @@ -97,53 +99,53 @@ public class SOSWidget extends AppWidgetProvider { // // 加入新报告信息 // - public synchronized static void addAPPSOSReportBean(Context context, SOSReportBean bean) { - initAPPSOSReportBeanList(context); - _SOSReportBeanList.add(0, bean); + public synchronized static void addWinBollNewsBean(Context context, WinBollNewsBean bean) { + initWinBollNewsBeanList(context); + _WinBollNewsBeanList.add(0, bean); // 控制记录总数 - while (_SOSReportBeanList.size() > _MAX_PAGES * _OnePageLinesCount) { - _SOSReportBeanList.remove(_SOSReportBeanList.size() - 1); + while (_WinBollNewsBeanList.size() > _MAX_PAGES * _OnePageLinesCount) { + _WinBollNewsBeanList.remove(_WinBollNewsBeanList.size() - 1); } - SOSReportBean.saveBeanList(context, _SOSReportBeanList, SOSReportBean.class); + WinBollNewsBean.saveBeanList(context, _WinBollNewsBeanList, WinBollNewsBean.class); } - synchronized static void initAPPSOSReportBeanList(Context context) { - if (_SOSReportBeanList == null) { - _SOSReportBeanList = new ArrayList(); - SOSReportBean.loadBeanList(context, _SOSReportBeanList, SOSReportBean.class); + synchronized static void initWinBollNewsBeanList(Context context) { + if (_WinBollNewsBeanList == null) { + _WinBollNewsBeanList = new ArrayList(); + WinBollNewsBean.loadBeanList(context, _WinBollNewsBeanList, WinBollNewsBean.class); } - if (_SOSReportBeanList == null) { - _SOSReportBeanList = new ArrayList(); - SOSReportBean.saveBeanList(context, _SOSReportBeanList, SOSReportBean.class); + if (_WinBollNewsBeanList == null) { + _WinBollNewsBeanList = new ArrayList(); + WinBollNewsBean.saveBeanList(context, _WinBollNewsBeanList, WinBollNewsBean.class); } } private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) { LogUtils.d(TAG, "updateAppWidget(...)"); - RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_sos); + RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_news); //设置按钮点击事件 - Intent intentPre = new Intent(context, SOSWidgetClickListener.class); - intentPre.setAction(SOSWidgetClickListener.ACTION_PRE); + Intent intentPre = new Intent(context, APPNewsWidgetClickListener.class); + intentPre.setAction(APPNewsWidgetClickListener.ACTION_PRE); PendingIntent pendingIntentPre = PendingIntent.getBroadcast(context, 0, intentPre, PendingIntent.FLAG_UPDATE_CURRENT); views.setOnClickPendingIntent(R.id.widget_button_pre, pendingIntentPre); - Intent intentNext = new Intent(context, SOSWidgetClickListener.class); - intentNext.setAction(SOSWidgetClickListener.ACTION_NEXT); + Intent intentNext = new Intent(context, APPNewsWidgetClickListener.class); + intentNext.setAction(APPNewsWidgetClickListener.ACTION_NEXT); PendingIntent pendingIntentNext = PendingIntent.getBroadcast(context, 0, intentNext, PendingIntent.FLAG_UPDATE_CURRENT); views.setOnClickPendingIntent(R.id.widget_button_next, pendingIntentNext); - views.setTextViewText(R.id.infoTextView, getPageInfo()); - views.setTextViewText(R.id.sosReportTextView, getMessage()); + views.setTextViewText(R.id.tv_msg, getPageInfo()); + views.setTextViewText(R.id.tv_news, getMessage()); appWidgetManager.updateAppWidget(appWidgetId, views); } public static String getMessage() { ArrayList msgTemp = new ArrayList(); - if (_SOSReportBeanList != null) { + if (_WinBollNewsBeanList != null) { int start = _OnePageLinesCount * _CurrentPageIndex; - start = _SOSReportBeanList.size() > start ? start : _SOSReportBeanList.size() - 1; - for (int i = start, j = 0; i < _SOSReportBeanList.size() && j < _OnePageLinesCount && start > -1; i++, j++) { - msgTemp.add(_SOSReportBeanList.get(i).getSosReport()); + start = _WinBollNewsBeanList.size() > start ? start : _WinBollNewsBeanList.size() - 1; + for (int i = start, j = 0; i < _WinBollNewsBeanList.size() && j < _OnePageLinesCount && start > -1; i++, j++) { + msgTemp.add(_WinBollNewsBeanList.get(i).getMessage()); } String message = String.join("\n", msgTemp); return message; @@ -152,33 +154,33 @@ public class SOSWidget extends AppWidgetProvider { } public static void prePage(Context context) { - if (_SOSReportBeanList != null) { + if (_WinBollNewsBeanList != null) { if (_CurrentPageIndex > 0) { _CurrentPageIndex = _CurrentPageIndex - 1; } - Intent intentWidget = new Intent(context, SOSWidget.class); - intentWidget.setAction(SOSWidget.ACTION_RELOAD_REPORT); + Intent intentWidget = new Intent(context, APPNewsWidget.class); + intentWidget.setAction(APPNewsWidget.ACTION_RELOAD_REPORT); context.sendBroadcast(intentWidget); } } public static void nextPage(Context context) { - if (_SOSReportBeanList != null) { - if ((_CurrentPageIndex + 1) * _OnePageLinesCount < _SOSReportBeanList.size()) { + if (_WinBollNewsBeanList != null) { + if ((_CurrentPageIndex + 1) * _OnePageLinesCount < _WinBollNewsBeanList.size()) { _CurrentPageIndex = _CurrentPageIndex + 1; } - Intent intentWidget = new Intent(context, SOSWidget.class); - intentWidget.setAction(SOSWidget.ACTION_RELOAD_REPORT); + Intent intentWidget = new Intent(context, APPNewsWidget.class); + intentWidget.setAction(APPNewsWidget.ACTION_RELOAD_REPORT); context.sendBroadcast(intentWidget); } } String getPageInfo() { - if (_SOSReportBeanList == null) { + if (_WinBollNewsBeanList == null) { return "0/0"; } - int leftCount = _SOSReportBeanList.size() % _OnePageLinesCount; - int currentPageCount = _SOSReportBeanList.size() / _OnePageLinesCount + (leftCount == 0 ?0: 1); + int leftCount = _WinBollNewsBeanList.size() % _OnePageLinesCount; + int currentPageCount = _WinBollNewsBeanList.size() / _OnePageLinesCount + (leftCount == 0 ?0: 1); return String.format("%d/%d", _CurrentPageIndex + 1, currentPageCount); } } diff --git a/appbase/src/main/res/layout/activity_main.xml b/appbase/src/main/res/layout/activity_main.xml index a17706a..0c085fa 100644 --- a/appbase/src/main/res/layout/activity_main.xml +++ b/appbase/src/main/res/layout/activity_main.xml @@ -1,149 +1,208 @@ + android:layout_width="match_parent" + android:layout_height="match_parent"> - + android:id="@+id/toolbar"/> - - - - - + android:layout_weight="1.0"> - - - -