Compare commits

..

74 Commits

Author SHA1 Message Date
ZhanGSKen
76420ff5f4 <mymessagemanager>APK 15.2.5 release Publish. 2025-05-20 20:39:06 +08:00
ZhanGSKen
ee3553716c 编译调试 2025-05-20 20:31:06 +08:00
ZhanGSKen
d689db61ff 分支合并修整 2025-05-20 20:16:03 +08:00
ZhanGSKen
d7efdb6c02 编译调试 2025-05-20 11:28:25 +08:00
ZhanGSKen
20b36dd63b Merge remote-tracking branch 'origin/androidxdemo' into appbase 2025-05-20 05:46:28 +08:00
ZhanGSKen
a40450c085 Merge remote-tracking branch 'origin/androiddemo' into appbase 2025-05-20 05:46:23 +08:00
ZhanGSKen
e7a7a4438c 更新类库 2025-05-20 05:45:52 +08:00
ZhanGSKen
3e6de13fa3 更新类库 2025-05-20 05:44:07 +08:00
ZhanGSKen
af848809e9 <libappbase>Library Release 15.8.1 2025-05-20 05:41:16 +08:00
ZhanGSKen
2c7026a635 <appbase>APK 15.8.1 release Publish. 2025-05-20 05:40:58 +08:00
ZhanGSKen
6278c3f945 修复次级窗口打开时传递的参数缺失问题 2025-05-20 05:39:48 +08:00
ZhanGSKen
bc3a320433 移除WinBoLL应用模块 2025-05-13 12:01:35 +08:00
ZhanGSKen
e03b8d4745 Merge remote-tracking branch 'origin/androidxdemo' into appbase 2025-05-13 11:52:23 +08:00
ZhanGSKen
d5fb348134 Merge remote-tracking branch 'origin/androiddemo' into appbase 2025-05-13 11:52:17 +08:00
ZhanGSKen
5c7437b19c Merge remote-tracking branch 'origin/aes' into appbase 2025-05-13 11:52:11 +08:00
ZhanGSKen
bf09def10b 更新适配系统版本 2025-05-13 11:44:39 +08:00
ZhanGSKen
8431d7dfa9 更新适配系统版本 2025-05-13 11:43:25 +08:00
ZhanGSKen
6aadaf87af 更新类库版本 2025-05-13 11:40:34 +08:00
ZhanGSKen
6a2943420f 更新类库版本 2025-05-13 11:34:56 +08:00
ZhanGSKen
dc704e292a <libaes>Library Release 15.8.0 2025-05-13 11:22:45 +08:00
ZhanGSKen
1087a7837c <aes>APK 15.8.0 release Publish. 2025-05-13 11:22:24 +08:00
ZhanGSKen
59876a2353 设置基础版本号 2025-05-13 11:21:27 +08:00
ZhanGSKen
053b45e87e <libapputils>Library Release 15.8.1 2025-05-13 11:18:15 +08:00
ZhanGSKen
58e49ed371 <apputils>APK 15.8.1 release Publish. 2025-05-13 11:17:53 +08:00
ZhanGSKen
90a6eb266b 编译调试 2025-05-13 11:17:24 +08:00
ZhanGSKen
f0a564c9bb <apputils>Start New Stage Version. 2025-05-13 11:11:32 +08:00
ZhanGSKen
46b21331af Merge remote-tracking branch 'origin/appbase' into apputils 2025-05-13 11:10:47 +08:00
ZhanGSKen
6221cc30ac <libapputils>Library Release 15.8.0 2025-05-13 11:10:23 +08:00
ZhanGSKen
8489ee6447 <apputils>APK 15.8.0 release Publish. 2025-05-13 11:09:58 +08:00
ZhanGSKen
9205af4aa9 编译调试 2025-05-13 11:08:42 +08:00
ZhanGSKen
780e730a38 设置基础版本号 2025-05-13 11:08:04 +08:00
ZhanGSKen
429499885b <libappbase>Library Release 15.8.0 2025-05-13 11:05:19 +08:00
ZhanGSKen
fcf4ad2fc0 <appbase>APK 15.8.0 release Publish. 2025-05-13 11:05:02 +08:00
ZhanGSKen
7635f6f084 设置基础版本号 2025-05-13 11:03:55 +08:00
ZhanGSKen
e49935f772 <libappbase>Library Release 15.7.7 2025-05-13 10:29:25 +08:00
ZhanGSKen
381ddf9e40 <appbase>APK 15.7.7 release Publish. 2025-05-13 10:28:56 +08:00
ZhanGSKen
ae8da772c0 常驻通知栏UI优化。 2025-05-03 20:50:53 +08:00
ZhanGSKen
b2555ebfd3 类库升级,源码编译整理。 2025-05-03 20:48:33 +08:00
ZhanGSKen
82d9aabf33 Merge remote-tracking branch 'origin/appbase' into mymessagemanager 2025-05-03 16:50:15 +08:00
ZhanGSKen
2c91d32e41 在号码识别对比中,兼容当前区域号码。 2025-04-14 16:36:24 +08:00
ZhanGSKen
fa43d43110 <mymessagemanager>APK 15.2.4 release Publish. 2025-04-01 19:55:49 +08:00
ZhanGSKen
8f8e7d98c7 通知调试完成,添加旧通知设置清理按钮。 2025-04-01 19:54:30 +08:00
ZhanGSKen
af39f98a51 通知模块调试ing... 2025-04-01 15:20:02 +08:00
ZhanGSKen
5a1d557683 <mymessagemanager>APK 15.2.3 release Publish. 2025-03-31 20:04:51 +08:00
ZhanGSKen
39116f0912 更新类库,修复调试模式保存问题。 2025-03-31 20:03:40 +08:00
ZhanGSKen
a6b711b38b <mymessagemanager>APK 15.2.2 release Publish. 2025-03-31 02:36:56 +08:00
ZhanGSKen
d1703551f5 更新应用调试模式设置方法 2025-03-31 02:36:15 +08:00
ZhanGSKen
d63f7d3d83 <mymessagemanager>APK 15.2.1 release Publish. 2025-03-31 02:29:38 +08:00
ZhanGSKen
06b399846d Merge remote-tracking branch 'origin/appbase' into mymessagemanager 2025-03-31 02:27:33 +08:00
ZhanGSKen
e06efea08e <mymessagemanager>APK 15.2.0 release Publish. 2025-03-31 02:27:06 +08:00
ZhanGSKen
890ff6eda9 更新类库,添加更新日志查看方式和应用介绍窗口。 2025-03-31 02:24:50 +08:00
ZhanGSKen
e5a5eda9b6 1225 2025-03-29 12:25:04 +08:00
ZhanGSKen
174a052088 更新类库引用次序,预防资源引用次序混乱。 2025-03-29 12:24:14 +08:00
ZhanGSKen
fbd8441264 更新类库解决应用介绍窗口资源引用冲突问题 2025-03-29 12:19:26 +08:00
ZhanGSKen
fb92e9f673 更新类库 2025-03-29 11:53:35 +08:00
ZhanGSKen
d34d1e2796 设置版本号 2025-03-29 10:20:29 +08:00
ZhanGSKen
36fb8b41a4 1017 2025-03-29 10:17:55 +08:00
ZhanGSKen
fe70a18547 Merge branch 'appbase' into mymessagemanager 2025-03-29 09:45:00 +08:00
ZhanGSKen
46e4ee7fb7 <mymessagemanager>APK 15.0.0 release Publish. 2025-03-26 17:54:55 +08:00
ZhanGSKen
b2b959232c 去掉二级窗口分屏模式 2025-03-26 17:52:10 +08:00
ZhanGSKen
b11f814c41 Merge remote-tracking branch 'origin/appbase' into mymessagemanager 2025-03-26 17:49:04 +08:00
ZhanGSKen
1e991aed7e 适配小米15,设置编译参数。 2025-03-25 19:39:21 +08:00
ZhanGSKen
f56125f82a Merge branch 'appbase' into mymessagemanager 2025-03-25 19:29:33 +08:00
ZhanGSKen
33b7b65239 <mymessagemanager>APK 4.1.18 release Publish. 2025-03-01 14:11:49 +08:00
ZhanGSKen
664d14ad84 编译配置修复 2025-03-01 14:09:49 +08:00
ZhanGSKen
47cb393f76 更新短信接收规则设定:
1.启用了只接受通讯录,通讯录里有记录
2.如果不是数字通讯地址,但是在通讯录内
3.通讯地址是数字,并且在短信接收规则内。
以上3种情况就接收,其他一律放到回收站。
2025-03-01 14:01:13 +08:00
ZhanGSKen
6495f1c66e <mymessagemanager>APK 4.1.17 release Publish. 2025-03-01 13:39:17 +08:00
ZhanGSKen
f0c52d1e02 修复格式化通信录地址后的短信浏览BUG。 2025-03-01 13:38:37 +08:00
ZhanGSKen
d948f31331 <mymessagemanager>APK 4.1.16 release Publish. 2025-03-01 13:27:26 +08:00
ZhanGSKen
e1b3087020 格式化通讯地址显示 2025-03-01 13:25:22 +08:00
ZhanGSKen
03e21ab81c <mymessagemanager>APK 4.1.15 release Publish. 2025-02-25 20:51:01 +08:00
ZhanGSKen
ac72132969 添加电话号码前面有+号的检测兼容。 2025-02-25 20:50:03 +08:00
ZhanGSKen
cedb5f521b <mymessagemanager>APK 4.1.14 release Publish. 2025-02-25 20:25:31 +08:00
ZhanGSKen
396df6713c 添加单元测试模块,增加电话号码是否是数字的检测。 2025-02-25 20:19:54 +08:00
110 changed files with 1077 additions and 1326 deletions

View File

@@ -29,7 +29,7 @@ android {
// versionName 更新后需要手动设置
// 项目模块目录的 build.gradle 文件的 stageCount=0
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
versionName "15.6"
versionName "15.8"
if(true) {
versionName = genVersionName("${versionName}")
}

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Mon May 12 18:10:35 HKT 2025
stageCount=4
#Tue May 13 11:22:39 HKT 2025
stageCount=1
libraryProject=libaes
baseVersion=15.6
publishVersion=15.6.3
baseVersion=15.8
publishVersion=15.8.0
buildCount=0
baseBetaVersion=15.6.4
baseBetaVersion=15.8.1

View File

@@ -24,7 +24,7 @@ android {
defaultConfig {
applicationId "cc.winboll.studio.androiddemo"
minSdkVersion 24
targetSdkVersion 29
targetSdkVersion 30
versionCode 1
// versionName 更新后需要手动设置
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
@@ -67,6 +67,6 @@ dependencies {
// https://mvnrepository.com/artifact/com.android.support/recyclerview-v7
api 'com.android.support:recyclerview-v7:28.0.0'
api 'cc.winboll.studio:libapputils:15.2.2'
api 'cc.winboll.studio:libappbase:15.2.2'
api 'cc.winboll.studio:libapputils:15.8.1'
api 'cc.winboll.studio:libappbase:15.8.1'
}

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Thu Apr 03 03:17:18 GMT 2025
#Mon May 19 21:45:28 GMT 2025
stageCount=0
libraryProject=
baseVersion=15.0
publishVersion=15.0.0
buildCount=21
buildCount=25
baseBetaVersion=15.0.1

View File

@@ -24,7 +24,7 @@ android {
defaultConfig {
applicationId "cc.winboll.studio.androidxdemo"
minSdkVersion 24
targetSdkVersion 29
targetSdkVersion 30
versionCode 1
// versionName 更新后需要手动设置
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
@@ -67,7 +67,7 @@ dependencies {
//api 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
//api 'androidx.fragment:fragment:1.1.0'
api 'cc.winboll.studio:libaes:15.2.6'
api 'cc.winboll.studio:libapputils:15.2.2'
api 'cc.winboll.studio:libappbase:15.2.2'
api 'cc.winboll.studio:libaes:15.8.0'
api 'cc.winboll.studio:libapputils:15.8.1'
api 'cc.winboll.studio:libappbase:15.8.1'
}

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Thu Apr 03 03:15:55 GMT 2025
#Mon May 19 21:43:40 GMT 2025
stageCount=0
libraryProject=
baseVersion=15.0
publishVersion=15.0.0
buildCount=18
buildCount=22
baseBetaVersion=15.0.1

View File

@@ -22,9 +22,9 @@ import android.widget.HorizontalScrollView;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import cc.winboll.studio.androidxdemo.R;
import cc.winboll.studio.libappbase.GlobalApplication;
import com.hjq.toast.ToastUtils;
import com.hjq.toast.style.WhiteToastStyle;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
@@ -53,8 +53,8 @@ public class App extends GlobalApplication {
// 初始化 Toast 框架
ToastUtils.init(this);
// 设置 Toast 布局样式
ToastUtils.setView(R.layout.view_toast);
//ToastUtils.setStyle(new WhiteToastStyle());
//ToastUtils.setView(R.layout.view_toast);
ToastUtils.setStyle(new WhiteToastStyle());
ToastUtils.setGravity(Gravity.BOTTOM, 0, 200);
//CrashHandler.getInstance().registerGlobal(this);

View File

@@ -30,7 +30,7 @@ android {
// versionName 更新后需要手动设置
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
versionName "15.7"
versionName "15.8"
if(true) {
versionName = genVersionName("${versionName}")
}

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Sun May 11 19:36:35 GMT 2025
stageCount=7
#Tue May 20 03:28:00 GMT 2025
stageCount=2
libraryProject=libappbase
baseVersion=15.7
publishVersion=15.7.6
buildCount=15
baseBetaVersion=15.7.7
baseVersion=15.8
publishVersion=15.8.1
buildCount=1
baseBetaVersion=15.8.2

View File

@@ -29,7 +29,7 @@ android {
// versionName 更新后需要手动设置
// 项目模块目录的 build.gradle 文件的 stageCount=0
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
versionName "15.3"
versionName "15.8"
if(true) {
versionName = genVersionName("${versionName}")
}

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Tue Apr 29 15:04:17 HKT 2025
stageCount=5
#Tue May 13 11:18:09 HKT 2025
stageCount=2
libraryProject=libapputils
baseVersion=15.3
publishVersion=15.3.4
baseVersion=15.8
publishVersion=15.8.1
buildCount=0
baseBetaVersion=15.3.5
baseBetaVersion=15.8.2

View File

@@ -20,18 +20,7 @@ import cc.winboll.studio.libapputils.views.SimpleWebView;
import java.io.IOException;
import java.io.InputStream;
public class AssetsHtmlActivity extends WinBoLLActivityBase implements IWinBoLLActivity {
@Override
public Activity getActivity() {
return super.getActivity();
}
@Override
public String getTag() {
return TAG;
}
public class AssetsHtmlActivity extends WinBoLLActivity implements IWinBoLLActivity {
public static final String TAG = "AssetsHtmlActivity";
@@ -43,12 +32,17 @@ public class AssetsHtmlActivity extends WinBoLLActivityBase implements IWinBoLLA
// Assets 文件夹里的 Html 文件的名称
String mszHtmlFileName;
//
// @Override
// public Activity getActivity() {
// return this;
// }
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);

View File

@@ -217,10 +217,10 @@ final public class MainActivity extends Activity {
if (item.getItemId() == R.id.item_exit) {
//exit();
return true;
} else if (item.getItemId() == R.id.item_teststringtoqrcodeview) {
Intent intent = new Intent(this, TestStringToQRCodeViewActivity.class);
startActivityForResult(intent, REQUEST_QRCODEDECODE_ACTIVITY);
//WinBoLLActivityManager.getInstance(this).startWinBoLLActivity(this, TestStringToQrCodeViewActivity.class);
// } else if (item.getItemId() == R.id.item_teststringtoqrcodeview) {
// Intent intent = new Intent(this, TestStringToQRCodeViewActivity.class);
// startActivityForResult(intent, REQUEST_QRCODEDECODE_ACTIVITY);
// //WinBoLLActivityManager.getInstance(this).startWinBoLLActivity(this, TestStringToQrCodeViewActivity.class);
} else if (item.getItemId() == R.id.item_testqrcodedecodeactivity) {
Intent intent = new Intent(this, QRCodeDecodeActivity.class);
startActivityForResult(intent, REQUEST_QRCODEDECODE_ACTIVITY);

View File

@@ -0,0 +1,24 @@
package cc.winboll.studio.apputils;
/**
* @Author ZhanGSKen<zhangsken@188.com>
* @Date 2025/05/13 11:15
* @Describe WinBoLLActivity
*/
import android.app.Activity;
import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity;
public class WinBoLLActivity extends Activity implements IWinBoLLActivity {
public static final String TAG = "WinBoLLActivity";
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
}

View File

@@ -25,14 +25,7 @@ buildscript {
//mavenLocal()
// WinBoLL.CC 紧急备用 Maven 仓库
//maven { url 'https://spare-maven.winboll.cc/repository/' }
maven {
url 'sftp://studio@winboll.cc:2222//winboll/spare-maven/repository/'
credentials {
username 'studio'
password 'winbollstudio'
}
}
maven { url 'https://spare-maven.winboll.cc/repository/' }
}
dependencies {
classpath 'com.android.tools.build:gradle:7.2.1' // 对应 compileSdkVersion 32
@@ -47,6 +40,7 @@ allprojects {
// 设置本地Maven仓库路径
url 'file:///sdcard/.m2/repository/'
}
// Nexus Maven 库地址
// "WinBoLL Release"
maven { url "https://nexus.winboll.cc/repository/maven-public/" }
@@ -67,14 +61,7 @@ allprojects {
//mavenLocal()
// WinBoLL.CC 紧急备用 Maven 仓库
//maven { url 'https://spare-maven.winboll.cc/repository/' }
maven {
url 'sftp://studio@winboll.cc:2222//winboll/spare-maven/repository/'
credentials {
username 'studio'
password 'winbollstudio'
}
}
maven { url 'https://spare-maven.winboll.cc/repository/' }
}
ext {
// 定义全局变量,常用于版本管理

View File

@@ -21,9 +21,8 @@ android {
dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
//api 'cc.winboll.studio:libaes:15.6.0'
api 'cc.winboll.studio:libapputils:15.3.4'
api 'cc.winboll.studio:libappbase:15.7.6'
api 'cc.winboll.studio:libapputils:15.8.1'
api 'cc.winboll.studio:libappbase:15.8.0'
// 吐司类库
api 'com.github.getActivity:ToastUtils:10.5'

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Mon May 12 18:10:35 HKT 2025
stageCount=4
#Tue May 13 11:22:23 HKT 2025
stageCount=1
libraryProject=libaes
baseVersion=15.6
publishVersion=15.6.3
baseVersion=15.8
publishVersion=15.8.0
buildCount=0
baseBetaVersion=15.6.4
baseBetaVersion=15.8.1

View File

@@ -176,8 +176,8 @@ public abstract class DrawerFragmentActivity extends AppCompatActivity implement
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
getString(i);
}
} else if (R.id.item_log == item.getItemId()) {
GlobalApplication.getWinBoLLActivityManager().startLogActivity(this);
// } else if (R.id.item_log == item.getItemId()) {
// GlobalApplication.getWinBoLLActivityManager().startLogActivity(this);
} else if (R.id.item_about == item.getItemId()) {
LogUtils.d(TAG, "onAbout");
} else if (android.R.id.home == item.getItemId()) {

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Sun May 11 19:36:35 GMT 2025
stageCount=7
#Tue May 20 03:28:00 GMT 2025
stageCount=2
libraryProject=libappbase
baseVersion=15.7
publishVersion=15.7.6
buildCount=15
baseBetaVersion=15.7.7
baseVersion=15.8
publishVersion=15.8.1
buildCount=1
baseBetaVersion=15.8.2

View File

@@ -81,6 +81,7 @@ public class WinBoLLActivityManager {
// 新建一个任务窗口
Intent intent = new Intent(context, clazz);
//打开多任务窗口 flags
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
intent.putExtra("tag", tag);
@@ -102,6 +103,7 @@ public class WinBoLLActivityManager {
// 新建一个任务窗口
//Intent intent = new Intent(context, clazz);
//打开多任务窗口 flags
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
intent.putExtra("tag", tag);

View File

@@ -21,7 +21,7 @@ android {
dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
api 'cc.winboll.studio:libappbase:15.7.6'
api 'cc.winboll.studio:libappbase:15.8.0'
// 二维码类库
api 'com.google.zxing:core:3.4.1'

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Tue Apr 29 15:03:54 HKT 2025
stageCount=5
#Tue May 13 11:17:53 HKT 2025
stageCount=2
libraryProject=libapputils
baseVersion=15.3
publishVersion=15.3.4
baseVersion=15.8
publishVersion=15.8.1
buildCount=0
baseBetaVersion=15.3.5
baseBetaVersion=15.8.2

View File

@@ -18,18 +18,18 @@ def genVersionName(def versionName){
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
compileSdkVersion 32
buildToolsVersion "32.0.0"
defaultConfig {
applicationId "cc.winboll.studio.mymessagemanager"
minSdkVersion 26
targetSdkVersion 29
minSdkVersion 24
targetSdkVersion 30
versionCode 8
// versionName 更新后需要手动设置
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
versionName "4.1"
versionName "15.2"
if(true) {
versionName = genVersionName("${versionName}")
}
@@ -44,26 +44,27 @@ android {
}
dependencies {
api 'cc.winboll.studio:winboll-shared:1.6.4'
api 'io.github.medyo:android-about-page:2.0.0'
api fileTree(dir: 'libs', include: ['*.jar'])
api 'cc.winboll.studio:libaes:15.8.0'
api 'cc.winboll.studio:libapputils:15.8.1'
api 'cc.winboll.studio:libappbase:15.8.1'
api 'io.github.medyo:android-about-page:2.0.0'
api 'com.github.getActivity:ToastUtils:10.5'
api 'com.jcraft:jsch:0.1.55'
api 'org.jsoup:jsoup:1.13.1'
api 'com.squareup.okhttp3:okhttp:4.4.1'
api 'androidx.appcompat:appcompat:1.0.0'
api 'androidx.fragment:fragment:1.0.0'
api 'com.google.android.material:material:1.0.0'
// 权限请求框架https://github.com/getActivity/XXPermissions
api 'com.github.getActivity:XXPermissions:18.63'
api 'com.baoyz.pullrefreshlayout:library:1.2.0'
api 'androidx.appcompat:appcompat:1.0.0'
api 'androidx.fragment:fragment:1.0.0'
// AndroidX 类库
api 'androidx.appcompat:appcompat:1.1.0'
api 'com.google.android.material:material:1.4.0'
//api 'androidx.viewpager:viewpager:1.0.0'
//api 'androidx.vectordrawable:vectordrawable:1.1.0'
//api 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
//api 'androidx.fragment:fragment:1.1.0'
api 'com.google.android.material:material:1.0.0'
api 'cc.winboll.studio:libaes:7.6.0'
api fileTree(dir: 'libs', include: ['*.jar'])
}

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Tue Feb 25 10:52:41 GMT 2025
stageCount=14
#Tue May 20 20:39:06 HKT 2025
stageCount=6
libraryProject=
baseVersion=4.1
publishVersion=4.1.13
buildCount=5
baseBetaVersion=4.1.14
baseVersion=15.2
publishVersion=15.2.5
buildCount=0
baseBetaVersion=15.2.6

View File

@@ -53,30 +53,28 @@
</queries>
<application
android:name=".GlobalApplication"
android:name=".App"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:roundIcon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/WinBoll.SupportThemeNoActionBar"
android:theme="@style/MyAppTheme"
android:persistent="true"
android:resizeableActivity="true"
android:supportsRtl="true"
android:requestLegacyExternalStorage="true">
android:requestLegacyExternalStorage="true"
android:networkSecurityConfig="@xml/network_security_config">
<activity
android:name=".activitys.SMSActivity"
android:process=":sms"/>
android:name=".activitys.SMSActivity"/>
<activity
android:name=".activitys.SMSReceiveRuleActivity"
android:process=":smsars">
android:name=".activitys.SMSReceiveRuleActivity">
</activity>
<activity
android:name=".activitys.SharedJSONReceiveActivity"
android:process=":smssjr"
android:exported="true">
<intent-filter>
@@ -98,17 +96,14 @@
</activity>
<activity
android:name=".activitys.TTSPlayRuleActivity"
android:process=":ttsrule"/>
android:name=".activitys.TTSPlayRuleActivity"/>
<activity
android:name=".activitys.AboutActivity"
android:process=":about"/>
android:name=".activitys.AboutActivity"/>
<activity
android:name=".activitys.MainActivity"
android:exported="true"
android:process=":main">
android:exported="true">
<intent-filter>
@@ -122,8 +117,7 @@
<activity
android:name=".activitys.ComposeSMSActivity"
android:exported="true"
android:process=":csms">
android:exported="true">
<intent-filter>
@@ -226,6 +220,8 @@
<activity android:name="cc.winboll.studio.mymessagemanager.activitys.SMSRecycleActivity"/>
<activity android:name="cc.winboll.studio.mymessagemanager.unittest.UnitTestActivity"/>
</application>
</manifest>

View File

@@ -1,18 +1,17 @@
package cc.winboll.studio.mymessagemanager;
/**
* @Author ZhanGSKen<zhangsken@188.com>
* @Author ZhanGSKen@QQ.COM
* @Date 2023/07/24 01:46:59
* @Describe 全局应用类
*/
import android.view.Gravity;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.shared.app.WinBollApplication;
import cc.winboll.studio.shared.log.LogUtils;
import com.hjq.toast.ToastUtils;
import java.io.File;
public class GlobalApplication extends WinBollApplication {
public class App extends GlobalApplication {
public static final String TAG = "GlobalApplication";
@@ -30,7 +29,6 @@ public class GlobalApplication extends WinBollApplication {
@Override
public void onCreate() {
super.onCreate();
//setIsDebug(cc.winboll.studio.mymessagemanager.BuildConfig.DEBUG);
// 初始化 Toast 框架
ToastUtils.init(this);
@@ -45,8 +43,4 @@ public class GlobalApplication extends WinBollApplication {
_mszConfigUtilPath = _mszAppExternalFilesDir + File.separator + _mszConfigUtilFileName;
_mszSMSReceiveRuleUtilPath = _mszAppExternalFilesDir + File.separator + _mszSMSReceiveRuleUtilFileName;
}
public static void showApplicationMessage(String szMessage) {
LogUtils.i(TAG, szMessage);
}
}

View File

@@ -3,72 +3,89 @@ package cc.winboll.studio.mymessagemanager.activitys;
/**
* @Author ZhanGSKen<zhangsken@188.com>
* @Date 2024/07/14 13:20:33
* @Describe 应用关于对话窗口
* @Describe 应用介绍窗口
*/
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.shared.app.WinBollActivity;
import cc.winboll.studio.shared.app.WinBollActivityManager;
import com.hjq.toast.ToastUtils;
import cc.winboll.studio.libaes.utils.AESThemeUtil;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.libaes.winboll.APPInfo;
import cc.winboll.studio.libaes.winboll.AboutView;
import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity;
import cc.winboll.studio.mymessagemanager.App;
import cc.winboll.studio.mymessagemanager.R;
final public class AboutActivity extends WinBollActivity {
public class AboutActivity extends WinBollActivity implements IWinBoLLActivity {
public static final String TAG = "AboutActivity";
Context mContext;
Toolbar mToolbar;
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
@Override
protected boolean isEnableDisplayHomeAsUp() {
return false;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(AESThemeUtil.getThemeTypeID(getApplicationContext()));
super.onCreate(savedInstanceState);
mContext = this;
setContentView(R.layout.activity_about);
mContext = getApplicationContext();
mToolbar = findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
mToolbar.setSubtitle(TAG);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
AboutView aboutView = CreateAboutView();
// 在 Activity 的 onCreate 或其他生命周期方法中调用
// LinearLayout layout = new LinearLayout(this);
// layout.setOrientation(LinearLayout.VERTICAL);
// // 创建布局参数(宽度和高度)
// ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
// ViewGroup.LayoutParams.MATCH_PARENT,
// ViewGroup.LayoutParams.MATCH_PARENT
// );
// addContentView(aboutView, params);
LinearLayout layout = findViewById(R.id.aboutviewroot_ll);
// 创建布局参数(宽度和高度)
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
);
layout.addView(aboutView, params);
App.getWinBoLLActivityManager().add(this);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
setTitle(mContext.getString(R.string.text_about) + mContext.getString(R.string.app_name));
protected void onDestroy() {
super.onDestroy();
App.getWinBoLLActivityManager().registeRemove(this);
}
@Override
protected boolean isAddWinBollToolBar() {
return false;
}
@Override
protected Toolbar initToolBar() {
return findViewById(R.id.activityaboutASupportToolbar1);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar_about, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
/*if (item.getItemId() == R.id.item_help) {
ToastUtils.show("R.id.item_help");
} else */if (item.getItemId() == android.R.id.home) {
WinBollActivityManager.getInstance(getApplicationContext()).finish(this);
}
return super.onOptionsItemSelected(item);
public AboutView CreateAboutView() {
String szBranchName = "mymessagemanager";
APPInfo appInfo = new APPInfo();
appInfo.setAppName(getString(R.string.app_name));
appInfo.setAppIcon(cc.winboll.studio.libaes.R.drawable.ic_winboll);
appInfo.setAppDescription(getString(R.string.app_description));
appInfo.setAppGitName("APP");
appInfo.setAppGitOwner("Studio");
appInfo.setAppGitAPPBranch(szBranchName);
appInfo.setAppGitAPPSubProjectFolder(szBranchName);
appInfo.setAppHomePage("https://www.winboll.cc/studio/details.php?app=MyMessageManager");
appInfo.setAppAPKName("MyMessageManager");
appInfo.setAppAPKFolderName("MyMessageManager");
return new AboutView(mContext, appInfo);
}
}

View File

@@ -17,6 +17,8 @@ import cc.winboll.studio.libaes.views.AToolbar;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.utils.AppConfigUtil;
import cc.winboll.studio.mymessagemanager.utils.PermissionUtil;
import cc.winboll.studio.mymessagemanager.utils.NotificationHelper;
import cc.winboll.studio.libappbase.dialogs.YesNoAlertDialog;
public class AppSettingsActivity extends BaseActivity {
@@ -96,4 +98,18 @@ public class AppSettingsActivity extends BaseActivity {
Toast.makeText(getApplication(), "应用已获得所需权限。", Toast.LENGTH_SHORT).show();
}
}
public void onCleanOldChannels(View view) {
YesNoAlertDialog.show(this, "通知设置清理", "是否清理旧的通知设置?", new YesNoAlertDialog.OnDialogResultListener(){
@Override
public void onNo() {
}
@Override
public void onYes() {
NotificationHelper notificationHelper = new NotificationHelper(AppSettingsActivity.this);
notificationHelper.cleanOldChannels();
}
});
}
}

View File

@@ -1,6 +1,5 @@
package cc.winboll.studio.mymessagemanager.activitys;
import cc.winboll.studio.mymessagemanager.R;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -8,9 +7,8 @@ import android.view.Menu;
import android.view.MenuItem;
import androidx.appcompat.app.AppCompatActivity;
import cc.winboll.studio.libaes.utils.AESThemeUtil;
import cc.winboll.studio.shared.log.LogUtils;
import com.hjq.toast.ToastUtils;
import cc.winboll.studio.libaes.beans.AESThemeBean;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.R;
abstract public class BaseActivity extends AppCompatActivity {
@@ -103,7 +101,7 @@ abstract public class BaseActivity extends AppCompatActivity {
AESThemeUtil.saveThemeStyleID(this, R.style.MyTaoAESTheme);
recreate();
} else if (R.id.item_defaulttheme == item.getItemId()) {
AESThemeUtil.saveThemeStyleID(this, R.style.MyDefaultAESTheme);
AESThemeUtil.saveThemeStyleID(this, R.style.MyAppTheme);
recreate();
}
//ToastUtils.show("nThemeStyleID " + Integer.toString(nThemeStyleID));

View File

@@ -10,7 +10,6 @@ import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.Toolbar;
import cc.winboll.studio.libaes.views.AOHPCTCSeekBar;
import cc.winboll.studio.mymessagemanager.R;

View File

@@ -10,28 +10,25 @@ import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ScrollView;
import cc.winboll.studio.libaes.views.AToolbar;
import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.LogView;
import cc.winboll.studio.mymessagemanager.App;
import cc.winboll.studio.mymessagemanager.BuildConfig;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.activitys.MainActivity;
import cc.winboll.studio.mymessagemanager.adapters.PhoneArrayAdapter;
import cc.winboll.studio.mymessagemanager.services.MainService;
import cc.winboll.studio.mymessagemanager.unittest.UnitTestActivity;
import cc.winboll.studio.mymessagemanager.utils.AppConfigUtil;
import cc.winboll.studio.mymessagemanager.utils.AppGoToSettingsUtil;
import cc.winboll.studio.mymessagemanager.utils.NotificationUtil;
import cc.winboll.studio.mymessagemanager.utils.PermissionUtil;
import cc.winboll.studio.mymessagemanager.utils.SMSUtil;
import cc.winboll.studio.mymessagemanager.utils.ThemeUtil;
import cc.winboll.studio.mymessagemanager.utils.ViewUtil;
import cc.winboll.studio.mymessagemanager.views.ConfirmSwitchView;
import cc.winboll.studio.mymessagemanager.views.PhoneListViewForScrollView;
import cc.winboll.studio.shared.log.LogUtils;
import cc.winboll.studio.shared.log.LogView;
import com.baoyz.widget.PullRefreshLayout;
import java.util.ArrayList;
import cc.winboll.studio.libaes.utils.AESThemeUtil;
import cc.winboll.studio.libaes.views.ASupportToolbar;
import androidx.appcompat.widget.Toolbar;
public class MainActivity extends BaseActivity {
@@ -45,7 +42,7 @@ public class MainActivity extends BaseActivity {
public static final int MY_PERMISSIONS_REQUEST = 0;
static MainActivity _mMainActivity;
LogView mLogView;
//LogView mLogView;
AppConfigUtil mAppConfigUtil;
ConfirmSwitchView msvEnableService;
ConfirmSwitchView msvOnlyReceiveContacts;
@@ -121,8 +118,8 @@ public class MainActivity extends BaseActivity {
//
void initView() {
// 设置调试日志
mLogView = findViewById(R.id.logview);
mLogView.start();
// mLogView = findViewById(R.id.logview);
// mLogView.start();
// 设置消息处理函数
setOnActivityMessageReceived(mIOnActivityMessageReceived);
@@ -131,12 +128,7 @@ public class MainActivity extends BaseActivity {
mToolbar = findViewById(R.id.activitymainASupportToolbar1);
mToolbar.setSubtitle(getString(R.string.activity_name_main));
setSupportActionBar(mToolbar);
// 创建通知频道
NotificationUtil nu = new NotificationUtil();
nu.createServiceNotificationChannel(MainActivity.this);
nu.createSMSNotificationChannel(MainActivity.this);
boolean isEnableService = mAppConfigUtil.mAppConfigBean.isEnableService();
msvEnableService = findViewById(R.id.activitymainSwitchView1);
msvEnableService.setChecked(isEnableService);
@@ -270,7 +262,7 @@ public class MainActivity extends BaseActivity {
protected void onResume() {
super.onResume();
reloadSMS();
mLogView.start();
//mLogView.start();
}
@Override
@@ -303,27 +295,33 @@ public class MainActivity extends BaseActivity {
int nItemId = item.getItemId();
if (nItemId == R.id.app_ttsrule) {
Intent i = new Intent(MainActivity.this, TTSPlayRuleActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
} else if (nItemId == R.id.app_smsrule) {
Intent i = new Intent(MainActivity.this, SMSReceiveRuleActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
} else if (nItemId == R.id.app_appsettings) {
Intent i = new Intent(MainActivity.this, AppSettingsActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
} else if (nItemId == R.id.app_crashtest) {
} else if (nItemId == R.id.app_log) {
//App.getWinBoLLActivityManager().startLogActivity(this);
} else if (nItemId == R.id.app_unittest) {
Intent i = new Intent(MainActivity.this, UnitTestActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
} else if (nItemId == R.id.app_crashtest) {
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
getString(i);
}
} else if (nItemId == R.id.app_about) {
Intent i = new Intent(MainActivity.this, AboutActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
} else if (nItemId == R.id.app_smsrecycle) {
Intent i = new Intent(MainActivity.this, SMSRecycleActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}

View File

@@ -18,10 +18,10 @@ import cc.winboll.studio.libaes.views.AOHPCTCSeekBar;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.activitys.SMSActivity;
import cc.winboll.studio.mymessagemanager.adapters.SMSArrayAdapter;
import cc.winboll.studio.mymessagemanager.utils.AddressUtils;
import cc.winboll.studio.mymessagemanager.utils.SMSUtil;
import cc.winboll.studio.mymessagemanager.utils.ViewUtil;
import cc.winboll.studio.mymessagemanager.views.SMSListViewForScrollView;
import cc.winboll.studio.mymessagemanager.views.SMSView;
import java.lang.ref.WeakReference;
public class SMSActivity extends BaseActivity {
@@ -102,7 +102,7 @@ public class SMSActivity extends BaseActivity {
// 初始化标题栏
mToolbar = findViewById(R.id.activitysmsASupportToolbar1);
mToolbar.setSubtitle(getString(R.string.activity_name_smsinphone) + " < Phone : " + mszPhoneTo + " >");
mToolbar.setSubtitle(getString(R.string.activity_name_smsinphone) + " < Phone : " + AddressUtils.getFormattedAddress(mszPhoneTo) + " >");
setActionBar(mToolbar);
// 初始化滚动窗口

View File

@@ -21,7 +21,7 @@ import android.widget.Toast;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import cc.winboll.studio.mymessagemanager.GlobalApplication;
import cc.winboll.studio.mymessagemanager.App;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.activitys.SMSReceiveRuleActivity;
import cc.winboll.studio.mymessagemanager.adapters.SMSAcceptRuleArrayAdapter;
@@ -114,7 +114,7 @@ public class SMSReceiveRuleActivity extends BaseActivity {
}
void initSMSAcceptRuleBeanAdd() {
mSMSAcceptRuleBeanAdd = new SMSAcceptRuleBean(GlobalApplication.USER_ID, "", true, SMSAcceptRuleBean.RuleType.REFUSE, true);
mSMSAcceptRuleBeanAdd = new SMSAcceptRuleBean(App.USER_ID, "", true, SMSAcceptRuleBean.RuleType.REFUSE, true);
}
@Override

View File

@@ -8,16 +8,16 @@ package cc.winboll.studio.mymessagemanager.activitys;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import cc.winboll.studio.libappbase.dialogs.YesNoAlertDialog;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.activitys.SMSRecycleActivity;
import cc.winboll.studio.mymessagemanager.adapters.SMSRecycleAdapter;
import cc.winboll.studio.mymessagemanager.utils.SMSRecycleUtil;
import cc.winboll.studio.shared.view.YesNoAlertDialog;
import com.baoyz.widget.PullRefreshLayout;
import java.io.File;
import androidx.appcompat.widget.Toolbar;
public class SMSRecycleActivity extends BaseActivity {

View File

@@ -0,0 +1,60 @@
package cc.winboll.studio.mymessagemanager.activitys;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/31 01:31:17
* @Describe 应用活动窗口基类
*/
import android.app.Activity;
import android.os.Bundle;
import android.view.MenuItem;
import androidx.appcompat.app.AppCompatActivity;
import cc.winboll.studio.libaes.beans.AESThemeBean;
import cc.winboll.studio.libaes.utils.AESThemeUtil;
import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity;
public class WinBollActivity extends AppCompatActivity implements IWinBoLLActivity {
public static final String TAG = "WinBollActivity";
protected volatile AESThemeBean.ThemeType mThemeType;
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
mThemeType = getThemeType();
setThemeStyle();
super.onCreate(savedInstanceState);
}
AESThemeBean.ThemeType getThemeType() {
/*SharedPreferences sharedPreferences = getSharedPreferences(
SHAREDPREFERENCES_NAME, MODE_PRIVATE);
return AESThemeBean.ThemeType.values()[((sharedPreferences.getInt(DRAWER_THEME_TYPE, AESThemeBean.ThemeType.DEFAULT.ordinal())))];
*/
return AESThemeBean.getThemeStyleType(AESThemeUtil.getThemeTypeID(getApplicationContext()));
}
void setThemeStyle() {
//setTheme(AESThemeBean.getThemeStyle(getThemeType()));
setTheme(AESThemeUtil.getThemeTypeID(getApplicationContext()));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}

View File

@@ -9,13 +9,14 @@ import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.activitys.SMSActivity;
import cc.winboll.studio.mymessagemanager.beans.PhoneBean;
import cc.winboll.studio.mymessagemanager.beans.SMSBean;
import cc.winboll.studio.mymessagemanager.utils.AddressUtils;
import cc.winboll.studio.mymessagemanager.utils.PhoneUtil;
import cc.winboll.studio.mymessagemanager.utils.SMSUtil;
import cc.winboll.studio.shared.log.LogUtils;
import java.util.ArrayList;
import java.util.List;
@@ -74,9 +75,9 @@ public class PhoneArrayAdapter extends BaseAdapter {
viewHolder = (ViewHolder) convertView.getTag();
}
String szAddress = ((SMSBean)getItem(position)).getAddress();
final String szAddress = ((SMSBean)getItem(position)).getAddress();
viewHolder.tvAddress.setText(szAddress);
viewHolder.tvAddress.setText(AddressUtils.getFormattedAddress(szAddress));
viewHolder.tvName.setText(getName(szAddress));
//Drawable drawableFrame = AppCompatResources.getDrawable(mContext, R.drawable.bg_frame);
@@ -87,7 +88,7 @@ public class PhoneArrayAdapter extends BaseAdapter {
//Toast.makeText(mContext, tv.getText(), Toast.LENGTH_SHORT).show();
Intent intent = new Intent(mContext, SMSActivity.class);
intent.putExtra(SMSActivity.EXTRA_PHONE, viewHolder.tvAddress.getText());
intent.putExtra(SMSActivity.EXTRA_PHONE, szAddress);
mContext.startActivity(intent);
}

View File

@@ -18,7 +18,6 @@ import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.activitys.TTSPlayRuleActivity;
import cc.winboll.studio.mymessagemanager.beans.SMSBean;
import cc.winboll.studio.mymessagemanager.dialogs.YesNoAlertDialog;
import cc.winboll.studio.mymessagemanager.utils.NotificationUtil;
import cc.winboll.studio.mymessagemanager.utils.SMSReceiveRuleUtil;
import cc.winboll.studio.mymessagemanager.utils.SMSRecycleUtil;
import cc.winboll.studio.mymessagemanager.utils.SMSUtil;
@@ -28,6 +27,7 @@ import cc.winboll.studio.mymessagemanager.views.SMSView;
import com.hjq.toast.ToastUtils;
import java.util.ArrayList;
import cc.winboll.studio.mymessagemanager.beans.SMSAcceptRuleBean;
import cc.winboll.studio.mymessagemanager.utils.NotificationHelper;
public class SMSArrayAdapter extends BaseAdapter {
@@ -54,7 +54,8 @@ public class SMSArrayAdapter extends BaseAdapter {
public void cancelMessageNotification() {
for (SMSBean bean : mData) {
NotificationUtil.cancelNotification(mContext, bean.getId());
NotificationHelper notificationHelper = new NotificationHelper(mContext);
notificationHelper.cancelNotification(bean.getId());
}
}

View File

@@ -34,6 +34,7 @@ import cc.winboll.studio.mymessagemanager.views.DateAgoTextView;
import cc.winboll.studio.mymessagemanager.views.SMSView;
import com.hjq.toast.ToastUtils;
import java.util.ArrayList;
import cc.winboll.studio.mymessagemanager.utils.AddressUtils;
public class SMSRecycleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@@ -154,7 +155,7 @@ public class SMSRecycleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
final SMSRecycleBean item = mDataList.get(position);
if (holder.getItemViewType() == 0) {
SimpleViewHolder viewHolder = (SimpleViewHolder) holder;
viewHolder.mtvAddress.setText(item.getAddress());
viewHolder.mtvAddress.setText(AddressUtils.getFormattedAddress(item.getAddress()));
viewHolder.mbtnViewBody.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
@@ -179,7 +180,7 @@ public class SMSRecycleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
viewHolder.mvRight.setVisibility(View.GONE);
viewHolder.mSMSView.setSMSType(SMSView.SMSType.SEND);
}
viewHolder.mtvAddress.setText(item.getAddress());
viewHolder.mtvAddress.setText(AddressUtils.getFormattedAddress(item.getAddress()));
viewHolder.mdatvDeleteDate.setDate(item.getDeleteDate());
viewHolder.mdatvDate.setDate(item.getDate());
if(mAppConfigUtil.mAppConfigBean.isSMSRecycleProtectMode()) {

View File

@@ -7,8 +7,7 @@ package cc.winboll.studio.mymessagemanager.beans;
*/
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.mymessagemanager.utils.ThemeUtil;
import cc.winboll.studio.shared.app.BaseBean;
import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException;
public class AppConfigBean extends BaseBean {

View File

@@ -7,7 +7,7 @@ package cc.winboll.studio.mymessagemanager.beans;
*/
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.shared.app.BaseBean;
import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException;
public class SMSAcceptRuleBean extends BaseBean {

View File

@@ -34,7 +34,7 @@ package cc.winboll.studio.mymessagemanager.beans;
import android.content.ContentValues;
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.shared.app.BaseBean;
import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException;
import java.text.Collator;
import java.util.ArrayList;

View File

@@ -7,7 +7,7 @@ package cc.winboll.studio.mymessagemanager.beans;
*/
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.shared.app.BaseBean;
import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException;
import java.text.Collator;
import java.util.ArrayList;

View File

@@ -7,7 +7,7 @@ package cc.winboll.studio.mymessagemanager.beans;
*/
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.shared.app.BaseBean;
import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException;
public class TTSPlayRuleBean extends BaseBean {

View File

@@ -8,8 +8,8 @@ package cc.winboll.studio.mymessagemanager.beans;
import android.content.Context;
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.utils.FileUtil;
import cc.winboll.studio.shared.log.LogUtils;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;

View File

@@ -10,9 +10,9 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.services.MainService;
import cc.winboll.studio.mymessagemanager.utils.AppConfigUtil;
import cc.winboll.studio.shared.log.LogUtils;
public class MainReceiver extends BroadcastReceiver {

View File

@@ -4,17 +4,17 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import cc.winboll.studio.mymessagemanager.GlobalApplication;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.App;
import cc.winboll.studio.mymessagemanager.activitys.SMSActivity;
import cc.winboll.studio.mymessagemanager.beans.SMSBean;
import cc.winboll.studio.mymessagemanager.utils.AppConfigUtil;
import cc.winboll.studio.mymessagemanager.utils.NotificationUtil;
import cc.winboll.studio.mymessagemanager.utils.PhoneUtil;
import cc.winboll.studio.mymessagemanager.utils.SMSReceiveRuleUtil;
import cc.winboll.studio.mymessagemanager.utils.SMSRecycleUtil;
import cc.winboll.studio.mymessagemanager.utils.SMSUtil;
import cc.winboll.studio.mymessagemanager.utils.TTSPlayRuleUtil;
import cc.winboll.studio.mymessagemanager.utils.RegexPPiUtils;
import cc.winboll.studio.mymessagemanager.utils.NotificationHelper;
public class SMSRecevier extends BroadcastReceiver {
@@ -36,34 +36,20 @@ public class SMSRecevier extends BroadcastReceiver {
String szAction = intent.getAction();
if (szAction.equals(ACTION_SMS_RECEIVED)) {
//LogUtils.d(TAG, "ACTION_SMS_RECEIVED");
LogUtils.d(TAG, "ACTION_SMS_RECEIVED");
String szSmsBody = SMSUtil.getSmsBody(intent);
String szSmsAddress = SMSUtil.getSmsAddress(intent);
PhoneUtil phoneUtil = new PhoneUtil(context);
boolean isPhoneInContacts = phoneUtil.isPhoneInContacts(szSmsAddress);
AppConfigUtil configUtil = AppConfigUtil.getInstance(context);
boolean isOnlyReceiveContacts = configUtil.mAppConfigBean.isEnableOnlyReceiveContacts();
boolean isEnableTTS = configUtil.mAppConfigBean.isEnableTTS();
boolean isEnableTTSAnalyzeMode = configUtil.mAppConfigBean.isEnableTTSRuleMode();
boolean isInSMSAcceptRule = SMSReceiveRuleUtil.getInstance(context, false).checkIsSMSAcceptInRule(context, szSmsBody);
//LogUtils.d(TAG, "isInSMSAcceptRule is : " + Boolean.toString(isInSMSAcceptRule));
if (!isPhoneInContacts) {
GlobalApplication.showApplicationMessage(" The phone number " + szSmsAddress + " is not in contacts.");
if (isOnlyReceiveContacts) {
GlobalApplication.showApplicationMessage("Close the \"Only Receive Contacts\" switch will be receive The " + szSmsAddress + "'s message in future.");
}
}
if ((!isOnlyReceiveContacts)
|| isPhoneInContacts
|| isInSMSAcceptRule) {
if (checkIsSMSOK(context, szSmsBody, szSmsAddress)) {
int nResultId = SMSUtil.saveReceiveSms(context, szSmsAddress, szSmsBody, "0", System.currentTimeMillis(), "inbox");
if (nResultId >= 0) {
NotificationUtil nu = new NotificationUtil();
nu.sendSMSReceivedMessage(context, nResultId, szSmsAddress, szSmsBody);
NotificationHelper notificationHelper = new NotificationHelper(context);
notificationHelper.sendSMSReceivedMessage(nResultId, szSmsAddress, szSmsBody);
LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(SMSActivity.ACTION_NOTIFY_SMS_CHANGED));
GlobalApplication.showApplicationMessage("<" + szSmsAddress + "> : ( " + szSmsBody + " ) [SAVED]");
LogUtils.d(TAG, "<" + szSmsAddress + "> : ( " + szSmsBody + " ) [SAVED]");
if (isEnableTTS) {
if (isEnableTTSAnalyzeMode) {
TTSPlayRuleUtil ttsPlayRuleUtil = TTSPlayRuleUtil.getInstance(context);
@@ -81,12 +67,41 @@ public class SMSRecevier extends BroadcastReceiver {
SMSRecycleUtil.addSMSRecycleItem(context, bean);
}
}
}
//
// 检查短信是否在接收设定规则内
//
public static boolean checkIsSMSOK(Context context, String szSmsBody, String szSmsAddress) {
PhoneUtil phoneUtil = new PhoneUtil(context);
boolean isPhoneInContacts = phoneUtil.isPhoneInContacts(szSmsAddress);
LogUtils.d(TAG, String.format("isPhoneInContacts %s", isPhoneInContacts));
boolean isPhoneByDigit = phoneUtil.isPhoneByDigit(szSmsAddress);
LogUtils.d(TAG, String.format("isPhoneByDigit %s", isPhoneByDigit));
AppConfigUtil configUtil = AppConfigUtil.getInstance(context);
boolean isOnlyReceiveContacts = configUtil.mAppConfigBean.isEnableOnlyReceiveContacts();
LogUtils.d(TAG, String.format("isOnlyReceiveContacts %s", isOnlyReceiveContacts));
boolean isInSMSAcceptRule = SMSReceiveRuleUtil.getInstance(context, false).checkIsSMSAcceptInRule(context, szSmsBody);
LogUtils.d(TAG, String.format("isInSMSAcceptRule %s", isInSMSAcceptRule));
// 启用了只接受通讯录,通讯录里有记录
if (isOnlyReceiveContacts && isPhoneInContacts) {
return true;
}
// 如果不是数字通讯地址,但是在通讯录内
if (!isPhoneByDigit && isPhoneInContacts) {
return true;
}
// 通讯地址是数字,并且在短信接收规则内。
if (isPhoneByDigit && isInSMSAcceptRule) {
return true;
}
return false;
}
}

View File

@@ -5,6 +5,7 @@ package cc.winboll.studio.mymessagemanager.services;
* @Date 2024/07/19 14:30:57
* @Describe 应用主要服务组件类
*/
import android.app.Notification;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
@@ -12,20 +13,24 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.IBinder;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.activitys.MainActivity;
import cc.winboll.studio.mymessagemanager.beans.MessageNotificationBean;
import cc.winboll.studio.mymessagemanager.receivers.SMSRecevier;
import cc.winboll.studio.mymessagemanager.services.MainService;
import cc.winboll.studio.mymessagemanager.utils.AppConfigUtil;
import cc.winboll.studio.mymessagemanager.utils.NotificationUtil;
import cc.winboll.studio.mymessagemanager.utils.NotificationHelper;
import cc.winboll.studio.mymessagemanager.utils.ServiceUtil;
import cc.winboll.studio.shared.log.LogUtils;
import com.hjq.toast.ToastUtils;
public class MainService extends Service {
public static String TAG = "ManagerService";
// 前台服务通知工具
NotificationHelper mNotificationHelper;
Notification notification;
AppConfigUtil mConfigUtil;
//MyBinder mMyBinder;
MyServiceConnection mMyServiceConnection;
@@ -73,17 +78,12 @@ public class MainService extends Service {
mSMSRecevier = new SMSRecevier();
registerReceiver(mSMSRecevier, localIntentFilter);
// 显示前台通知栏
MessageNotificationBean notificationMessage = createNotificationMessage();
NotificationUtil nu = new NotificationUtil();
nu.sendForegroundNotification(MainService.this, notificationMessage);
NotificationHelper helper = new NotificationHelper(this);
Intent intent = new Intent(this, MainActivity.class);
notification = helper.showForegroundNotification(intent, getString(R.string.app_name), getString(R.string.text_aboutservernotification));
startForeground(NotificationHelper.FOREGROUND_NOTIFICATION_ID, notification);
/*if (mConfigUtil.isEnableTTS()) {
TTSPlayRuleUtil.speakText(ManagerService.this, getString(R.string.text_iamhere), 0);
GlobalApplication.showApplicationMessage(getString(R.string.text_iamhere));
}*/
ToastUtils.show("Service is start.");
LogUtils.i(TAG, "Service is start.");
}
@@ -101,13 +101,6 @@ public class MainService extends Service {
}
private MessageNotificationBean createNotificationMessage() {
String szTitle = getApplicationContext().getString(R.string.app_name);
String szContent = getString(R.string.text_aboutservernotification);
return new MessageNotificationBean(NotificationUtil.ID_MSG_SERVICE, "", szTitle, szContent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//return super.onStartCommand(intent, flags, startId);
@@ -116,12 +109,12 @@ public class MainService extends Service {
return mConfigUtil.mAppConfigBean.isEnableService() ? Service.START_STICKY: super.onStartCommand(intent, flags, startId);
}
/*private class MyBinder extends IMyAidlInterface.Stub {
@Override
public String getServiceName() {
return MainService.class.getSimpleName();
}
}*/
/*private class MyBinder extends IMyAidlInterface.Stub {
@Override
public String getServiceName() {
return MainService.class.getSimpleName();
}
}*/
// 主进程与守护进程连接时需要用到此类
//

View File

@@ -0,0 +1,28 @@
package cc.winboll.studio.mymessagemanager.unittest;
import android.content.Context;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.utils.AddressUtils;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/01 13:07:32
* @Describe AddressUtils Test
*/
public class AddressUtils_Test {
public static final String TAG = "AddressUtils_Test";
public static void main(Context context) {
String szSmsBody = "无影无迹";
String szSmsAddress = "无名小辈";
LogUtils.d(TAG, String.format("szSmsAddress %s\n getFormattedAddress : %s", szSmsAddress, AddressUtils.getFormattedAddress(szSmsAddress)));
szSmsAddress = "13172887736";
LogUtils.d(TAG, String.format("szSmsAddress %s\n getFormattedAddress : %s", szSmsAddress, AddressUtils.getFormattedAddress(szSmsAddress)));
szSmsAddress = "+8613172887736";
LogUtils.d(TAG, String.format("szSmsAddress %s\n getFormattedAddress : %s", szSmsAddress, AddressUtils.getFormattedAddress(szSmsAddress)));
szSmsAddress = "8613172887736";
LogUtils.d(TAG, String.format("szSmsAddress %s\n getFormattedAddress : %s", szSmsAddress, AddressUtils.getFormattedAddress(szSmsAddress)));
}
}

View File

@@ -0,0 +1,56 @@
package cc.winboll.studio.mymessagemanager.unittest;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/25 19:02:15
* @Describe SMSRecevier 测试类
*/
import android.content.Context;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.receivers.SMSRecevier;
public class SMSRecevier_Test {
public static final String TAG = "SMSRecevier_Test";
public static void main(Context context) {
String szSmsBody = "无影无迹";
String szSmsAddress = "无名小辈";
test1(context, szSmsBody, szSmsAddress);
szSmsBody = "无影无迹";
szSmsAddress = "淘宝物流";
test1(context, szSmsBody, szSmsAddress);
szSmsBody = "无影无迹";
szSmsAddress = "1?0";
test1(context, szSmsBody, szSmsAddress);
szSmsBody = "无影无迹";
szSmsAddress = "10000";
test1(context, szSmsBody, szSmsAddress);
szSmsBody = "【UC】无影无迹";
szSmsAddress = "无名小辈";
test1(context, szSmsBody, szSmsAddress);
szSmsBody = "【UC】无影无迹";
szSmsAddress = "10000";
test1(context, szSmsBody, szSmsAddress);
szSmsBody = "【UC】无影无迹";
szSmsAddress = "13172887736";
test1(context, szSmsBody, szSmsAddress);
szSmsBody = "【UC】无影无迹";
szSmsAddress = "+8613172887736";
test1(context, szSmsBody, szSmsAddress);
}
public static void test1(Context context, String szSmsBody, String szSmsAddress) {
boolean isSMSOK = SMSRecevier.checkIsSMSOK(context, szSmsBody, szSmsAddress);
LogUtils.d(TAG, String.format("szSmsBody : %s\nszSmsAddress : %s\nisSMSOK : %s", szSmsBody, szSmsAddress, isSMSOK));
}
}

View File

@@ -0,0 +1,36 @@
package cc.winboll.studio.mymessagemanager.unittest;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/25 19:00:10
* @Describe 应用单元测试窗口
*/
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.LogView;
import cc.winboll.studio.mymessagemanager.R;
public class UnitTestActivity extends Activity {
public static final String TAG = "UnitTestActivity";
LogView mLogView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_unittest);
mLogView = findViewById(R.id.logview);
mLogView.start();
}
public void onMain(View view) {
LogUtils.d(TAG, "SMSRecevier_Test");
SMSRecevier_Test.main(this);
LogUtils.d(TAG, "AddressUtils_Test");
AddressUtils_Test.main(this);
}
}

View File

@@ -0,0 +1,20 @@
package cc.winboll.studio.mymessagemanager.utils;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/01 13:03:16
* @Describe 通信录地址工具
*/
public class AddressUtils {
public static final String TAG = "AddressUtils";
public static String getFormattedAddress(String address) {
if (address != null && address.matches("[+]?\\d+")) {
return address;
} else {
return "" + address + "";
}
}
}

View File

@@ -10,7 +10,7 @@ import android.content.Intent;
import android.content.res.AssetManager;
import android.net.Uri;
import androidx.core.content.FileProvider;
import cc.winboll.studio.shared.log.LogUtils;
import cc.winboll.studio.libappbase.LogUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

View File

@@ -0,0 +1,202 @@
package cc.winboll.studio.mymessagemanager.utils;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/04/01 14:10:35
* @Describe 应用通知工具类
*/
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.widget.RemoteViews;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.activitys.SMSActivity;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class NotificationHelper {
public static final String TAG = "NotificationHelper";
// 渠道ID和名称
private static final String CHANNEL_ID_FOREGROUND = "foreground_channel";
private static final String CHANNEL_NAME_FOREGROUND = "Foreground Service";
private static final String CHANNEL_ID_TEMPORARY = "temporary_channel";
private static final String CHANNEL_NAME_TEMPORARY = "Temporary Notifications";
// 通知ID
public static final int FOREGROUND_NOTIFICATION_ID = 1001;
public static final int TEMPORARY_NOTIFICATION_ID = 2001;
private final Context mContext;
private final NotificationManager mNotificationManager;
// 示例维护当前使用的渠道ID列表
// 键渠道ID渠道重要性级别
Map<String, Integer> activeChannelConfigs = new HashMap<>();
public NotificationHelper(Context context) {
mContext = context;
mNotificationManager = context.getSystemService(NotificationManager.class);
// 初始化配置
activeChannelConfigs.put(
CHANNEL_ID_FOREGROUND,
NotificationManager.IMPORTANCE_HIGH
);
activeChannelConfigs.put(
CHANNEL_ID_TEMPORARY,
NotificationManager.IMPORTANCE_DEFAULT
);
createNotificationChannels();
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void createNotificationChannels() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createForegroundChannel();
createTemporaryChannel();
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void createForegroundChannel() {
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID_FOREGROUND,
CHANNEL_NAME_FOREGROUND,
NotificationManager.IMPORTANCE_LOW
);
channel.setDescription("Persistent service notifications");
channel.setSound(null, null);
channel.enableVibration(false);
mNotificationManager.createNotificationChannel(channel);
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void createTemporaryChannel() {
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID_TEMPORARY,
CHANNEL_NAME_TEMPORARY,
NotificationManager.IMPORTANCE_HIGH
);
channel.setDescription("Temporary alert notifications");
channel.setSound(null, null);
channel.enableVibration(true);
channel.setVibrationPattern(new long[]{100, 200, 300, 400});
channel.setBypassDnd(true);
mNotificationManager.createNotificationChannel(channel);
}
// 显示常驻通知(通常用于前台服务)
public Notification showForegroundNotification(Intent intent, String title, String content) {
PendingIntent pendingIntent = createPendingIntent(intent);
Notification notification = new NotificationCompat.Builder(mContext, CHANNEL_ID_FOREGROUND)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_launcher))
//.setContentTitle(title)
.setContentTitle(content)
//.setContentText(content)
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setOngoing(true)
.build();
mNotificationManager.notify(FOREGROUND_NOTIFICATION_ID, notification);
return notification;
}
// 显示临时通知(自动消失)
public void showTemporaryNotification(Intent intent, String title, String content) {
showTemporaryNotification(intent, TEMPORARY_NOTIFICATION_ID, title, content);
}
// 显示临时通知(自动消失)
public void showTemporaryNotification(Intent intent, int notificationID, String title, String content) {
PendingIntent pendingIntent = createPendingIntent(intent);
Notification notification = new NotificationCompat.Builder(mContext, CHANNEL_ID_TEMPORARY)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_launcher))
.setContentTitle(title)
.setContentText(content)
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.setVibrate(new long[]{100, 200, 300, 400})
.build();
mNotificationManager.notify(notificationID, notification);
}
// 创建自定义布局通知(可扩展)
public void showCustomNotification(Intent intent, RemoteViews contentView, RemoteViews bigContentView) {
PendingIntent pendingIntent = createPendingIntent(intent);
Notification notification = new NotificationCompat.Builder(mContext, CHANNEL_ID_TEMPORARY)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pendingIntent)
.setContent(contentView)
.setCustomBigContentView(bigContentView)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.build();
mNotificationManager.notify(TEMPORARY_NOTIFICATION_ID + 1, notification);
}
// 取消所有通知
public void cancelAllNotifications() {
mNotificationManager.cancelAll();
}
// 取消指定通知
public void cancelNotification(int notificationID) {
mNotificationManager.cancel(notificationID);
}
// 创建PendingIntent兼容不同API版本
private PendingIntent createPendingIntent(Intent intent) {
int flags = PendingIntent.FLAG_UPDATE_CURRENT;
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// flags |= PendingIntent.FLAG_IMMUTABLE;
// }
return PendingIntent.getActivity(
mContext,
0,
intent,
flags
);
}
public void sendSMSReceivedMessage(int notificationID, String szPhone, String szBody) {
Intent intent = new Intent(mContext, SMSActivity.class);
intent.putExtra(SMSActivity.EXTRA_PHONE, szPhone);
String szTitle = mContext.getString(R.string.text_smsfrom) + "<" + szPhone + ">";
String szContent = "[ " + szBody + " ]";
showTemporaryNotification(intent, notificationID, szTitle, szContent);
}
public void cleanOldChannels() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
List<NotificationChannel> allChannels = mNotificationManager.getNotificationChannels();
for (NotificationChannel channel : allChannels) {
LogUtils.d(TAG, "Clean channel : " + channel.getId());
if (!activeChannelConfigs.containsKey(channel.getId())) {
// 安全删除渠道
mNotificationManager.deleteNotificationChannel(channel.getId());
LogUtils.d(TAG, String.format("Deleted Channel %s", channel.getId()));
}
}
}
}
}

View File

@@ -15,12 +15,12 @@ import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.media.RingtoneManager;
import android.widget.RemoteViews;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.activitys.MainActivity;
import cc.winboll.studio.mymessagemanager.activitys.SMSActivity;
import cc.winboll.studio.mymessagemanager.beans.MessageNotificationBean;
import cc.winboll.studio.mymessagemanager.services.MainService;
import cc.winboll.studio.shared.log.LogUtils;
public class NotificationUtil {

View File

@@ -0,0 +1,168 @@
package cc.winboll.studio.mymessagemanager.utils;
/**
* @Author ZhanGSKen@QQ.COM
* @Date 2024/07/19 14:30:57
* @Describe 应用通知栏工具类
*/
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.media.RingtoneManager;
import android.widget.RemoteViews;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.activitys.MainActivity;
import cc.winboll.studio.mymessagemanager.activitys.SMSActivity;
import cc.winboll.studio.mymessagemanager.beans.MessageNotificationBean;
import cc.winboll.studio.mymessagemanager.services.MainService;
public class NotificationUtil_Bck {
public static final String TAG = "NotificationUtil";
public static final int ID_MSG_SERVICE = 10000;
static final String szSMSChannelID = "1";
static final String szServiceChannelID = "0";
//static int mNumSendForegroundNotification = 10000;
//static int mNumSendSMSNotification = 20000;
public NotificationManager createServiceNotificationChannel(Context context) {
//创建通知渠道ID
String channelId = szServiceChannelID;
//创建通知渠道名称
String channelName = "Service Message";
//创建通知渠道重要性
int importance = NotificationManager.IMPORTANCE_MIN;
NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
channel.setSound(null, null);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(
Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
return notificationManager;
}
public NotificationManager createSMSNotificationChannel(Context context) {
//创建通知渠道ID
String channelId = szSMSChannelID;
//创建通知渠道名称
String channelName = "SMS Message";
//创建通知渠道重要性
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
channel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE), Notification.AUDIO_ATTRIBUTES_DEFAULT);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(
Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
return notificationManager;
}
// 创建通知
//
public void sendForegroundNotification(MainService service, MessageNotificationBean nessageNotificationBean) {
//创建Notification传入Context和channelId
Intent intent = new Intent();//这个intent会传给目标,可以使用getIntent来获取
intent.setClass(service, MainActivity.class);
//这里放一个count用来区分每一个通知
//intent.putExtra("intent", "intent--->" + count);//这里设置一个数据,带过去
//参数1:context 上下文对象
//参数2:发送者私有的请求码(Private request code for the sender)
//参数3:intent 意图对象
//参数4:必须为FLAG_ONE_SHOT,FLAG_NO_CREATE,FLAG_CANCEL_CURRENT,FLAG_UPDATE_CURRENT,中的一个
PendingIntent mForegroundPendingIntent = PendingIntent.getActivity(service, nessageNotificationBean.getMessageId(), intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT);
Notification mForegroundNotification = new Notification.Builder(service, szServiceChannelID)
.setAutoCancel(true)
.setContentTitle(nessageNotificationBean.getTitle())
.setContentText(nessageNotificationBean.getContent())
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.ic_launcher)
//设置红色
.setColor(Color.parseColor("#F00606"))
.setLargeIcon(BitmapFactory.decodeResource(service.getResources(), R.drawable.ic_launcher))
.setContentIntent(mForegroundPendingIntent)
.build();
RemoteViews mrvForegroundNotificationView = new RemoteViews(service.getPackageName(), R.layout.remoteview);
mrvForegroundNotificationView.setTextViewText(R.id.remoteviewTextView1, nessageNotificationBean.getTitle());
mrvForegroundNotificationView.setTextViewText(R.id.remoteviewTextView2, nessageNotificationBean.getContent());
mrvForegroundNotificationView.setImageViewResource(R.id.remoteviewImageView1, R.drawable.ic_launcher);
mForegroundNotification.contentView = mrvForegroundNotificationView;
mForegroundNotification.bigContentView = mrvForegroundNotificationView;
service.startForeground(nessageNotificationBean.getMessageId(), mForegroundNotification);
}
public void sendSMSNotification(Context context, MessageNotificationBean messageNotificationBean) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(
Context.NOTIFICATION_SERVICE);
/*NotificationManager notificationManager = createSMSNotificationChannel(context);
if (notificationManager == null) {
LogUtils.d(TAG, "createSMSNotificationChannel failed.");
return;
}*/
//创建Notification传入Context和channelId
Intent intent = new Intent(context, SMSActivity.class);
intent.putExtra(SMSActivity.EXTRA_PHONE, messageNotificationBean.getPhone());
LogUtils.d(TAG, "sendSMSNotification(...) message.getPhone() is : " + messageNotificationBean.getPhone());
//Intent intent = new Intent();//这个intent会传给目标,可以使用getIntent来获取
//intent.setClass(context, MainActivity.class);
//这里放一个count用来区分每一个通知
//intent.putExtra("intent", "intent--->" + count);//这里设置一个数据,带过去
//参数1:context 上下文对象
//参数2:发送者私有的请求码(Private request code for the sender)
//参数3:intent 意图对象
//参数4:必须为FLAG_ONE_SHOT,FLAG_NO_CREATE,FLAG_CANCEL_CURRENT,FLAG_UPDATE_CURRENT,中的一个
PendingIntent mRemindPendingIntent = PendingIntent.getActivity(context, messageNotificationBean.getMessageId(), intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT);
Notification mSMSNotification = new Notification.Builder(context, szSMSChannelID)
.setAutoCancel(true)
.setContentTitle(messageNotificationBean.getTitle())
.setContentText(messageNotificationBean.getContent())
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.ic_launcher)
//设置红色
.setColor(Color.parseColor("#F00606"))
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher))
.setContentIntent(mRemindPendingIntent)
.build();
RemoteViews mrvSMSNotificationView = new RemoteViews(context.getPackageName(), R.layout.remoteview);
mrvSMSNotificationView.setTextViewText(R.id.remoteviewTextView1, messageNotificationBean.getTitle());
mrvSMSNotificationView.setTextViewText(R.id.remoteviewTextView2, messageNotificationBean.getContent());
mrvSMSNotificationView.setImageViewResource(R.id.remoteviewImageView1, R.drawable.ic_launcher);
mSMSNotification.contentView = mrvSMSNotificationView;
mSMSNotification.bigContentView = mrvSMSNotificationView;
notificationManager.notify(messageNotificationBean.getMessageId(), mSMSNotification);
LogUtils.d(TAG, "getMessageId is : " + Integer.toString(messageNotificationBean.getMessageId()));
}
public void sendSMSReceivedMessage(Context context, int nMessageId, String szPhone, String szBody) {
String szTitle = context.getString(R.string.text_smsfrom) + "<" + szPhone + ">";
String szContent = "[ " + szBody + " ]";
sendSMSNotification(context, new MessageNotificationBean(nMessageId, szPhone, szTitle, szContent));
}
public static void cancelNotification(Context context, int notificationId) {
// 获取 NotificationManager 实例
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// 撤回指定 ID 的通知栏消息
notificationManager.cancel(notificationId);
}
}

View File

@@ -10,9 +10,9 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.activitys.BaseActivity;
import cc.winboll.studio.shared.log.LogUtils;
import com.hjq.permissions.OnPermissionCallback;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;

View File

@@ -10,11 +10,14 @@ import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.beans.PhoneBean;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PhoneUtil {
@@ -59,12 +62,57 @@ public class PhoneUtil {
public boolean isPhoneInContacts(String szPhone) {
List<PhoneBean> listPhoneDto = getPhoneList();
LogUtils.d(TAG, String.format("isPhoneInContacts(...) listPhoneDto.size() %d", listPhoneDto.size()));
for (int i = 0; i < listPhoneDto.size(); i++) {
if (listPhoneDto.get(i).getTelPhone().equals(szPhone)) {
if (isTheSamePhoneNumber(listPhoneDto.get(i).getTelPhone(), szPhone)) {
return true;
}
}
return false;
}
boolean isTheSamePhoneNumber(String szNum1, String szNum2) {
//LogUtils.d(TAG, String.format("szNum1 %s\nszNum2 %s", szNum1, szNum2));
if(szNum1.equals(szNum2)) {
LogUtils.d(TAG, "szNum1.equals(szNum2)");
return true;
}
if(UnitAreaUtils.getInstance(mContext).isCurrentUnitAreaNumber(szNum1)) {
if(szNum1.equals(UnitAreaUtils.getInstance(mContext).genCurrentUnitAreaNumber(szNum2))) {
LogUtils.d(TAG, "szNum1.equals(UnitAreaUtils.genCurrentUnitAreaNumber(szNum2))");
return true;
}
}
if(UnitAreaUtils.getInstance(mContext).isCurrentUnitAreaNumber(szNum2)) {
if(szNum2.equals(UnitAreaUtils.getInstance(mContext).genCurrentUnitAreaNumber(szNum1))) {
LogUtils.d(TAG, "szNum2.equals(UnitAreaUtils.genCurrentUnitAreaNumber(szNum1))");
return true;
}
}
LogUtils.d(TAG, "isTheSamePhoneNumber(...) return false;");
return false;
}
//
// 检验电话号码是否是数字
//
public static boolean isPhoneByDigit(String szPhone) {
if(!RegexPPiUtils.isPPiOK(szPhone)) {
return false;
}
//String text = "这里是一些任意的文本内容";
String regex = "[+]?\\d+";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(szPhone);
LogUtils.d(TAG, String.format("matcher.matches() : %s", matcher.matches()));
/*if (matcher.matches()) {
System.out.println("文本满足该正则表达式模式");
} else {
System.out.println("文本不满足该正则表达式模式");
}*/
return matcher.matches();
}
}

View File

@@ -7,9 +7,9 @@ package cc.winboll.studio.mymessagemanager.utils;
*/
import android.content.Context;
import android.util.JsonReader;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.beans.SMSAcceptRuleBean;
import cc.winboll.studio.mymessagemanager.beans.SMSAcceptRuleBean_V1;
import cc.winboll.studio.shared.log.LogUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -18,7 +18,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.nio.channels.AcceptPendingException;
public class SMSReceiveRuleUtil {
@@ -194,9 +193,9 @@ public class SMSReceiveRuleUtil {
public ArrayList<SMSAcceptRuleBean> loadConfigData() {
ArrayList<SMSAcceptRuleBean> list = new ArrayList<SMSAcceptRuleBean>();
SMSAcceptRuleBean.loadBeanList(mContext, list, SMSAcceptRuleBean.class);
for (int i = 0; i < list.size(); i++) {
LogUtils.d(TAG, "loadConfigData isEnable : " + Boolean.toString(list.get(i).isEnable()));
}
// for (int i = 0; i < list.size(); i++) {
// LogUtils.d(TAG, "loadConfigData isEnable : " + Boolean.toString(list.get(i).isEnable()));
// }
mDataList.clear();
mDataList.addAll(list);
return mDataList;

View File

@@ -6,7 +6,7 @@ package cc.winboll.studio.mymessagemanager.utils;
* @Describe 短信回收站工具类
*/
import android.content.Context;
import cc.winboll.studio.mymessagemanager.GlobalApplication;
import cc.winboll.studio.mymessagemanager.App;
import cc.winboll.studio.mymessagemanager.beans.SMSBean;
import cc.winboll.studio.mymessagemanager.beans.SMSRecycleBean;
import java.util.ArrayList;

View File

@@ -17,8 +17,8 @@ import android.os.Bundle;
import android.provider.Telephony;
import android.telephony.gsm.SmsManager;
import android.telephony.gsm.SmsMessage;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.beans.SMSBean;
import cc.winboll.studio.shared.log.LogUtils;
import com.hjq.toast.ToastUtils;
import java.util.ArrayList;

View File

@@ -10,6 +10,7 @@ import android.content.Intent;
import android.os.Message;
import android.util.JsonReader;
import android.widget.Toast;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.activitys.TTSPlayRuleActivity;
import cc.winboll.studio.mymessagemanager.beans.TTSPlayRuleBean;
@@ -17,7 +18,6 @@ import cc.winboll.studio.mymessagemanager.beans.TTSPlayRuleBean_V1;
import cc.winboll.studio.mymessagemanager.beans.TTSSpeakTextBean;
import cc.winboll.studio.mymessagemanager.dialogs.YesNoAlertDialog;
import cc.winboll.studio.mymessagemanager.services.TTSPlayService;
import cc.winboll.studio.shared.log.LogUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

View File

@@ -14,9 +14,9 @@ import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.beans.TTSSpeakTextBean;
import cc.winboll.studio.shared.log.LogUtils;
import java.util.ArrayList;
public class TextToSpeechUtil {

View File

@@ -0,0 +1,47 @@
package cc.winboll.studio.mymessagemanager.utils;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/04/14 15:55:36
* @Describe 电话号码区域管理辅助类
*/
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.beans.AppConfigBean;
import android.content.Context;
public class UnitAreaUtils {
public static final String TAG = "UnitAreaUtils";
static UnitAreaUtils _UnitAreaUtils;
Context mContext;
UnitAreaUtils(Context context) {
mContext = context;
}
public static UnitAreaUtils getInstance(Context context) {
if (_UnitAreaUtils == null) {
_UnitAreaUtils = new UnitAreaUtils(context);
}
return _UnitAreaUtils;
}
public boolean isCurrentUnitAreaNumber(String szPhoneNumer) {
String szUnitArea = getUnitArea();
LogUtils.d(TAG, String.format("szPhoneNumer.substring(1,3) %s", szPhoneNumer.substring(1,3)));
return szPhoneNumer.substring(1,3).equals(szUnitArea);
}
public String genCurrentUnitAreaNumber(String szPhoneNumer) {
String szUnitArea = getUnitArea();
LogUtils.d(TAG, String.format("szUnitArea %s", szUnitArea));
return "+" + szUnitArea + szPhoneNumer;
}
String getUnitArea() {
String szUnitArea = AppConfigUtil.getInstance(mContext).mAppConfigBean.getCountryCode();
LogUtils.d(TAG, String.format("szUnitArea %s", szUnitArea));
return szUnitArea;
}
}

View File

@@ -8,8 +8,8 @@ import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Switch;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.dialogs.YesNoAlertDialog;
import cc.winboll.studio.shared.log.LogUtils;
public class ConfirmSwitchView extends Switch {

View File

@@ -1,29 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/activityaboutToolbar1"/>-->
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<cc.winboll.studio.libaes.views.ASupportToolbar
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height"
android:id="@+id/activityaboutASupportToolbar1"/>
android:layout_height="wrap_content"
android:id="@+id/toolbar"/>
<cc.winboll.studio.shared.view.AboutView
app:appname="MyMessageManager"
app:appprojectname="MyMessageManager"
app:appdescription="用正则表达式方法自定义短信过滤和语音播报的短信应用。"
app:appicon="@drawable/ic_winboll"
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/activityaboutAboutView1"/>
android:layout_height="0dp"
android:layout_weight="1.0"
android:id="@+id/aboutviewroot_ll"/>
</LinearLayout>

View File

@@ -213,6 +213,12 @@
android:text="检查应用权限"
android:onClick="onCheckAndGetAppPermission"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="清理通知设置"
android:onClick="onCleanOldChannels"/>
</LinearLayout>
</LinearLayout>

View File

@@ -72,11 +72,5 @@
</com.baoyz.widget.PullRefreshLayout>
<cc.winboll.studio.shared.log.LogView
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="120dp"
android:id="@+id/logview"/>
</LinearLayout>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="500dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test Main"
android:onClick="onMain"
android:textAllCaps="false"/>
</LinearLayout>
</LinearLayout>
</ScrollView>
<cc.winboll.studio.shared.log.LogView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0"
android:id="@+id/logview"/>
</LinearLayout>

View File

@@ -19,6 +19,12 @@
android:title="@string/text_smsrule"/>
<item android:title="@string/app_developoptions">
<menu>
<item
android:id="@+id/app_log"
android:title="@string/app_log"/>
<item
android:id="@+id/app_unittest"
android:title="@string/app_unittest"/>
<item
android:id="@+id/app_crashtest"
android:title="@string/app_crashtest"/>

View File

@@ -9,6 +9,7 @@
<string name="app_goldentheme">辉煌历程主题</string>
<string name="app_developoptions">开发选项</string>
<string name="app_default_app_settings">默认应用设置</string>
<string name="app_unittest">单元测试</string>
<string name="app_crashtest">应用异常崩溃处理测试</string>
<string name="app_about">关于应用</string>
<string name="app_smsrecycle">短信回收站</string>

View File

@@ -9,6 +9,7 @@
<string name="app_goldentheme">Golden Theme</string>
<string name="app_developoptions">Develop Options</string>
<string name="app_default_app_settings">Default App Settings</string>
<string name="app_unittest">Unit Test</string>
<string name="app_crashtest">Crash Test</string>
<string name="app_about">About APP</string>
<string name="app_smsrecycle">SMS Recycle</string>

View File

@@ -1,6 +1,6 @@
<resources>
<style name="MyDefaultAESTheme" parent="DefaultAESTheme">
<style name="MyAppTheme" parent="AESTheme">
<item name="android:textSize">20sp</item>
<item name="attrSMSViewSendColor">@color/colorSMSSendColor</item>
<item name="attrSMSViewInboxColor">@color/colorSMSInboxColor</item>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">winboll.cc</domain>
</domain-config>
</network-security-config>

View File

@@ -48,8 +48,3 @@
// AndroidXDemo 项目编译设置
//include ':androidxdemo'
//rootProject.name = "androidxdemo"
// WinBoLL 项目编译设置
//include ':winboll'
//rootProject.name = "winboll"

1
winboll/.gitignore vendored
View File

@@ -1 +0,0 @@
/build

View File

@@ -1 +0,0 @@

View File

@@ -1,73 +0,0 @@
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 {
compileSdkVersion 32
buildToolsVersion "32.0.0"
defaultConfig {
applicationId "cc.winboll.studio.winboll"
minSdkVersion 24
targetSdkVersion 30
versionCode 1
// versionName 更新后需要手动设置
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
versionName "15.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
api 'com.jcraft:jsch:0.1.55'
// Html 解析
api 'org.jsoup:jsoup:1.13.1'
// 二维码类库
api 'com.google.zxing:core:3.4.1'
api 'com.journeyapps:zxing-android-embedded:3.6.0'
// 应用介绍页类库
api 'io.github.medyo:android-about-page:2.0.0'
// 吐司类库
api 'com.github.getActivity:ToastUtils:10.5'
// 网络连接类库
api 'com.squareup.okhttp3:okhttp:4.4.1'
// AndroidX 类库
api 'androidx.appcompat:appcompat:1.1.0'
api 'com.google.android.material:material:1.4.0'
//api 'androidx.viewpager:viewpager:1.0.0'
//api 'androidx.vectordrawable:vectordrawable:1.1.0'
//api 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
//api 'androidx.fragment:fragment:1.1.0'
api 'cc.winboll.studio:libaes:15.8.0'
api 'cc.winboll.studio:libapputils:15.8.1'
api 'cc.winboll.studio:libappbase:15.8.0'
}

View File

@@ -1,8 +0,0 @@
#Created by .winboll/winboll_app_build.gradle
#Thu May 22 13:37:34 HKT 2025
stageCount=3
libraryProject=
baseVersion=15.0
publishVersion=15.0.2
buildCount=0
baseBetaVersion=15.0.3

View File

@@ -1,21 +0,0 @@
# 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

View File

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

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">WinBoLL+</string>
</resources>

View File

@@ -1,37 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="cc.winboll.studio.winboll">
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher_stage"
android:roundIcon="@drawable/ic_launcher_stage"
android:label="@string/app_name"
android:theme="@style/MyAppTheme"
android:resizeableActivity="true"
android:name=".App">
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<meta-data
android:name="android.max_aspect"
android:value="4.0"/>
<activity android:name=".GlobalApplication$CrashActivity"/>
</application>
</manifest>

View File

@@ -1,345 +0,0 @@
package cc.winboll.studio.winboll;
import android.app.Activity;
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.Gravity;
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 cc.winboll.studio.libappbase.GlobalApplication;
import com.hjq.toast.ToastUtils;
import com.hjq.toast.style.WhiteToastStyle;
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 App extends GlobalApplication {
private static Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
@Override
public void onCreate() {
super.onCreate();
// 初始化 Toast 框架
ToastUtils.init(this);
// 设置 Toast 布局样式
//ToastUtils.setView(R.layout.view_toast);
ToastUtils.setStyle(new WhiteToastStyle());
ToastUtils.setGravity(Gravity.BOTTOM, 0, 200);
//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<String, String> head = new LinkedHashMap<String, String>();
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 App.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();
}
}
}

View File

@@ -1,53 +0,0 @@
package cc.winboll.studio.winboll;
/**
* @Author ZhanGSKen<zhangsken@188.com>
* @Date 2025/05/22 13:08
*/
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
public class CustomToolbar extends Toolbar {
private View viewMain;
public CustomToolbar(Context context) {
this(context, null);
}
public CustomToolbar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomToolbar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context, attrs);
}
private void initView(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomToolbar);
// 获取属性值
String toolbarTitle = typedArray.getString(R.styleable.CustomToolbar_toolbarTitle);
int toolbarTitleColor = typedArray.getColor(R.styleable.CustomToolbar_toolbarTitleColor, android.graphics.Color.WHITE);
int toolbarBackgroundColor = typedArray.getColor(R.styleable.CustomToolbar_toolbarBackgroundColor, android.graphics.Color.BLUE);
// 加载布局
viewMain = LayoutInflater.from(context).inflate(R.layout.view_toolbar, this, true);
// 应用属性值
TextView toolbarTitleTextView = viewMain.findViewById(R.id.toolbar_title);
toolbarTitleTextView.setText(toolbarTitle);
toolbarTitleTextView.setTextColor(toolbarTitleColor);
viewMain.setBackgroundColor(toolbarBackgroundColor);
// 释放 TypedArray
typedArray.recycle();
}
}

View File

@@ -1,50 +0,0 @@
package cc.winboll.studio.winboll;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.LogView;
import com.hjq.toast.ToastUtils;
public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainActivity";
LogView mLogView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
// 先设置 Toolbar 为支持 ActionBar
setSupportActionBar(toolbar);
// 为导航图标设置点击事件
toolbar.setNavigationOnClickListener(new android.view.View.OnClickListener() {
@Override
public void onClick(android.view.View v) {
// 这里可以添加点击事件的逻辑
}
});
//getSupportActionBar().setDisplayHomeAsUpEnabled(true);
//getSupportActionBar().setHomeButtonEnabled(true);
// 如果要设置其他图标(如菜单图标等),可根据具体需求进行设置
// 例如,有些情况下可以通过 MenuInflater 来 inflate 菜单资源,然后在菜单的 onMenuItemClick 中处理图标点击事件
mLogView = findViewById(R.id.logview);
ToastUtils.show("onCreate");
}
@Override
protected void onResume() {
super.onResume();
mLogView.start();
}
}

View File

@@ -1,34 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeColor="#00000000"
android:strokeWidth="1">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeColor="#00000000"
android:strokeWidth="1" />
</vector>

View File

@@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="1565dp"
android:height="1565dp"
android:viewportWidth="1565"
android:viewportHeight="1565">
<path
android:fillColor="#FFFFFFFF"
android:strokeColor="#FFFFFFFF"
android:strokeWidth="4.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M793.8 222.7C782.5 239.2 736.3 298.6 685.6 361.9 647 410.2 633.3 428.9 633.6 432.7 633.7 433.4 633.8 434.6 633.9 435.3 634.1 437.8 647.9 440.7 663.8 441.5 706.7 443.8 717 445.3 724.9 450.6 733.7 456.4 735.9 467.4 736 504.2 736 504.2 736 521.9 736 521.9 736 521.9 730.8 522.4 730.8 522.4 727.9 522.8 691.8 525.3 650.5 528 609.3 530.8 571.9 533.3 567.5 533.6 531.8 536 503.4 540.5 487.4 546 475 550.3 442.2 566.5 428.2 575.2 392.1 597.6 360.1 629.2 338 664.3 317 697.7 304.6 729.6 292.5 781 287.8 801 283.9 805.6 267.2 811 255.1 814.9 248.7 818.3 243.4 823.5 239.7 827.2 239.2 828.4 237.7 836.5 236.7 841.5 235.5 850 235 855.5 234.3 863.9 232.6 911.1 232.6 924.5 232.6 934.6 234.2 959.8 235 963 237.4 972 242.3 975.8 258.7 981.7 271.7 986.3 277.4 989.5 280.4 993.9 283.1 997.9 286.5 1008.7 287.4 1016.5 289.3 1031.7 293.3 1050.2 297.7 1064 306.4 1091.9 317.6 1107.7 330 1109.5 332.4 1109.9 334.7 1110.3 335 1110.5 335.3 1110.6 339.1 1111.1 343.5 1111.4 347.9 1111.8 353.8 1112.3 356.5 1112.5 370 1113.7 407.8 1115.8 430 1116.5 439.6 1116.8 453.4 1117.3 460.5 1117.5 467.7 1117.8 482.3 1118.2 493 1118.5 503.7 1118.8 520.8 1119.2 531 1119.5 587.8 1121.1 683 1122 794.5 1122 918.8 1122 996.1 1121 1075 1118.5 1083.5 1118.2 1098.6 1117.8 1108.5 1117.4 1118.4 1117.1 1129.4 1116.7 1133 1116.5 1136.6 1116.3 1144.7 1115.8 1151 1115.5 1183.3 1114 1207.5 1110.9 1221.5 1106.3 1235.3 1101.9 1244.8 1094.1 1249.9 1083.2 1253.5 1075.4 1253.7 1074.4 1259 1044 1266.4 1001.7 1269.1 993.5 1276.9 989.2 1278.9 988.1 1284.7 986.1 1289.9 984.6 1305.8 980.1 1313.3 975.5 1314.4 969.7 1316.2 959.5 1317.1 881.4 1315.7 859.5 1314 834.8 1313.1 831.4 1307 824.7 1301.2 818.3 1295 814.8 1283 811 1278 809.5 1272.4 807 1270.5 805.6 1264 800.6 1259.5 790.1 1252.5 763 1243.5 728.4 1235.9 706.8 1224.6 683.5 1202.3 637.7 1167.5 602.5 1111.8 569.1 1087.6 554.7 1054.4 542.7 1028.1 539 1024.1 538.4 1020.5 537.8 1020.1 537.6 1019.8 537.4 1016.4 536.9 1012.7 536.5 1009 536.2 1005.1 535.7 1004.2 535.5 999.7 534.7 988.4 533.6 973.5 532.5 969.7 532.2 964.5 531.8 962 531.5 959.5 531.2 940.4 530.1 919.5 529 851.7 525.4 836.1 523.7 829.5 519.4 821.2 514 825.2 495.6 837.6 481.8 843.8 474.9 844.2 474.3 856.8 448 862.6 436 868.9 425.2 879.9 408.7 888.2 396.2 895 385.5 895 385.1 895 384.6 889.7 383.3 883.3 382 851.1 375.9 812.7 367.8 806.9 365.9 792.4 361.2 790.7 358.7 790.2 342.5 789.7 326.8 792.4 303.4 800 258.5 802.1 246.1 803.3 220.9 801.9 219.6 801.7 219.4 800.5 218.9 799.3 218.6 797.4 218 796.5 218.7 793.8 222.7Z"/>
<path
android:fillColor="#FF62686C"
android:strokeColor="#FF62686C"
android:strokeWidth="4.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M570.4 704.1C553.5 706.1 539.7 713 532.9 722.7 523.5 736.3 519.9 764.2 519.6 826 519.5 859.4 519.7 860.6 530.1 872.9 543.4 888.6 560.4 900 574.1 902.1 586.7 904 601.5 898.9 615.7 887.5 632.5 874.1 633.5 868.9 632.7 793.6 632.2 742.5 631.6 736 627 725.2 620.5 710 596.2 700.9 570.4 704.1Z"/>
<path
android:fillColor="#FF62686C"
android:strokeColor="#FF62686C"
android:strokeWidth="4.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M949.2 705.5C935.1 708.7 927 716.8 922.6 732.4 918.4 746.7 917.8 757.3 917.3 816.5 917.1 847.8 917.3 874 917.7 874.6 919.2 876.7 945.3 892.3 955.5 897.1 973.4 905.5 983.5 905.4 978.9 896.8 977.1 893.4 979.1 892.6 985.9 893.9 993.6 895.4 997.8 894.3 1005.2 889.1 1010.9 885 1020.2 873.6 1023.8 866.5 1029.6 854.9 1031.1 841.6 1031.1 800.5 1031.1 750.1 1028.6 737.6 1014.9 720.4 1009.4 713.5 1004.6 709.8 996.9 706.8 992.2 704.9 989.1 704.6 973.5 704.4 960.6 704.1 953.7 704.5 949.2 705.5Z"/>
<path
android:fillColor="#FF62686C"
android:strokeColor="#FF62686C"
android:strokeWidth="4.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M717 988.7C671.1 990.4 640.9 994.2 635.6 998.8 631.5 1002.5 636.3 1017.5 643.6 1024 650.9 1030.3 661.7 1032.5 694 1034 721.9 1035.3 829.3 1035.3 857 1034 891.4 1032.4 901.4 1029.9 908.9 1021.3 914.5 1015 917.9 1003.4 915.2 999.4 910.4 992.1 856 987.9 772 988.2 745.9 988.3 721.1 988.5 717 988.7Z"/>
</vector>

View File

@@ -1,170 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillColor="#26A69A"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
</vector>

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:clickable="true"
android:layout_width="48dp"
android:layout_height="48dp">
<item android:drawable="@drawable/ic_launcher_background"/>
<item
android:left="0dp"
android:top="0dp"
android:right="0dp"
android:bottom="0dp"
android:drawable="@drawable/ic_iw"/>
</layer-list>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,46 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<cc.winboll.studio.winboll.CustomToolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:toolbarTitle="@string/app_name"
app:toolbarTitleColor="@color/colorAccent"
app:toolbarBackgroundColor="@color/colorPrimary"
android:id="@+id/toolbar"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0"
android:gravity="center_vertical|center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, WinBoLL!"
android:textAppearance="?android:attr/textAppearanceLarge"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0">
<cc.winboll.studio.libappbase.LogView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/logview"/>
</LinearLayout>
</LinearLayout>

View File

@@ -1,29 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/toolbar_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_iw"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_marginStart="6dp"
android:contentDescription="@string/toolbar_icon_description" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:textSize="18sp"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/toolbar_icon"
android:layout_marginStart="16dp" />
</RelativeLayout>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Some files were not shown because too many files have changed in this diff Show More