diff --git a/aes/build.gradle b/aes/build.gradle index 67c1a20..c9c1271 100644 --- a/aes/build.gradle +++ b/aes/build.gradle @@ -29,7 +29,7 @@ android { // versionName 更新后需要手动设置 // 项目模块目录的 build.gradle 文件的 stageCount=0 // Gradle编译环境下合起来的 versionName 就是 "${versionName}.0" - versionName "15.9" + versionName "15.10" if(true) { versionName = genVersionName("${versionName}") } diff --git a/aes/build.properties b/aes/build.properties index 26d3a6e..14e2b61 100644 --- a/aes/build.properties +++ b/aes/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Sun Aug 31 23:40:17 HKT 2025 -stageCount=4 +#Mon Sep 29 13:04:18 HKT 2025 +stageCount=3 libraryProject=libaes -baseVersion=15.9 -publishVersion=15.9.3 +baseVersion=15.10 +publishVersion=15.10.2 buildCount=0 -baseBetaVersion=15.9.4 +baseBetaVersion=15.10.3 diff --git a/aes/src/main/AndroidManifest.xml b/aes/src/main/AndroidManifest.xml index d123b21..9396685 100644 --- a/aes/src/main/AndroidManifest.xml +++ b/aes/src/main/AndroidManifest.xml @@ -33,6 +33,8 @@ + + - + \ No newline at end of file diff --git a/aes/src/main/java/cc/winboll/studio/aes/AboutActivity.java b/aes/src/main/java/cc/winboll/studio/aes/AboutActivity.java index c2402e5..079b8b5 100644 --- a/aes/src/main/java/cc/winboll/studio/aes/AboutActivity.java +++ b/aes/src/main/java/cc/winboll/studio/aes/AboutActivity.java @@ -12,18 +12,18 @@ import android.view.ViewGroup; import android.widget.LinearLayout; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; -import cc.winboll.studio.libaes.winboll.APPInfo; -import cc.winboll.studio.libaes.winboll.AboutView; -import cc.winboll.studio.libappbase.GlobalApplication; -import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; +import cc.winboll.studio.libaes.models.APPInfo; +import cc.winboll.studio.libaes.utils.WinBoLLActivityManager; +import cc.winboll.studio.libaes.views.AboutView; -public class AboutActivity extends AppCompatActivity implements IWinBoLLActivity { +public class AboutActivity extends WinBoLLActivity implements IWinBoLLActivity { public static final String TAG = "AboutActivity"; Context mContext; Toolbar mToolbar; - + @Override public Activity getActivity() { return this; @@ -33,7 +33,7 @@ public class AboutActivity extends AppCompatActivity implements IWinBoLLActivity public String getTag() { return TAG; } - + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -64,13 +64,13 @@ public class AboutActivity extends AppCompatActivity implements IWinBoLLActivity ); layout.addView(aboutView, params); - GlobalApplication.getWinBoLLActivityManager().add(this); + WinBoLLActivityManager.getInstance().add(this); } @Override protected void onDestroy() { super.onDestroy(); - GlobalApplication.getWinBoLLActivityManager().registeRemove(this); + WinBoLLActivityManager.getInstance().registeRemove(this); } public AboutView CreateAboutView() { diff --git a/aes/src/main/java/cc/winboll/studio/aes/App.java b/aes/src/main/java/cc/winboll/studio/aes/App.java index 3206907..9b0fb3a 100644 --- a/aes/src/main/java/cc/winboll/studio/aes/App.java +++ b/aes/src/main/java/cc/winboll/studio/aes/App.java @@ -6,6 +6,7 @@ package cc.winboll.studio.aes; * @Describe AES应用类 */ import android.view.Gravity; +import cc.winboll.studio.libaes.utils.WinBoLLActivityManager; import cc.winboll.studio.libappbase.GlobalApplication; import com.hjq.toast.ToastUtils; import com.hjq.toast.style.WhiteToastStyle; @@ -18,6 +19,7 @@ public class App extends GlobalApplication { @Override public void onCreate() { super.onCreate(); + WinBoLLActivityManager.init(this); // 初始化 Toast 框架 ToastUtils.init(this); diff --git a/aes/src/main/java/cc/winboll/studio/aes/MainActivity.java b/aes/src/main/java/cc/winboll/studio/aes/MainActivity.java index a3cd54b..40a70db 100644 --- a/aes/src/main/java/cc/winboll/studio/aes/MainActivity.java +++ b/aes/src/main/java/cc/winboll/studio/aes/MainActivity.java @@ -15,9 +15,10 @@ import android.widget.AdapterView; import android.widget.Toast; import cc.winboll.studio.aes.R; import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity; -import cc.winboll.studio.libaes.beans.DrawerMenuBean; import cc.winboll.studio.libaes.dialogs.LocalFileSelectDialog; import cc.winboll.studio.libaes.dialogs.StoragePathDialog; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; +import cc.winboll.studio.libaes.models.DrawerMenuBean; import cc.winboll.studio.libaes.unittests.SecondaryLibraryActivity; import cc.winboll.studio.libaes.unittests.TestAButtonFragment; import cc.winboll.studio.libaes.unittests.TestASupportToolbarActivity; @@ -25,10 +26,10 @@ import cc.winboll.studio.libaes.unittests.TestAToolbarActivity; import cc.winboll.studio.libaes.unittests.TestDrawerFragmentActivity; import cc.winboll.studio.libaes.unittests.TestViewPageFragment; import cc.winboll.studio.libappbase.LogUtils; -import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity; +import cc.winboll.studio.libappbase.ToastUtils; import com.a4455jkjh.colorpicker.ColorPickerDialog; -import com.hjq.toast.ToastUtils; import java.util.ArrayList; +import cc.winboll.studio.libaes.utils.WinBoLLActivityManager; public class MainActivity extends DrawerFragmentActivity implements IWinBoLLActivity { @@ -122,9 +123,10 @@ public class MainActivity extends DrawerFragmentActivity implements IWinBoLLActi @Override public boolean onOptionsItemSelected(MenuItem item) { int nItemId = item.getItemId(); -// if (item.getItemId() == R.id.item_log) { -// WinBoLLActivityManager.getInstance(this).startWinBoLLActivity(getApplicationContext(), LogActivity.class); -// } else + if (item.getItemId() == R.id.item_testactivitymanager) { + WinBoLLActivityManager.getInstance().startWinBoLLActivity(this, TestActivityManagerActivity.class); + //ToastUtils.show("item_testactivitymanager"); + } else if (nItemId == R.id.item_atoast) { Toast.makeText(getApplication(), "item_testatoast", Toast.LENGTH_SHORT).show(); } else if (nItemId == R.id.item_atoolbar) { diff --git a/aes/src/main/java/cc/winboll/studio/aes/TestActivityManagerActivity.java b/aes/src/main/java/cc/winboll/studio/aes/TestActivityManagerActivity.java new file mode 100644 index 0000000..71d114d --- /dev/null +++ b/aes/src/main/java/cc/winboll/studio/aes/TestActivityManagerActivity.java @@ -0,0 +1,33 @@ +package cc.winboll.studio.aes; + +import android.app.Activity; +import android.os.Bundle; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; + +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/09/28 21:07 + * @Describe 窗口管理类测试窗口 + */ +public class TestActivityManagerActivity extends WinBoLLActivity implements IWinBoLLActivity { + + public static final String TAG = "TestActivityManagerActivity"; + + @Override + public Activity getActivity() { + return this; + } + + @Override + public String getTag() { + return TAG; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_testactivitymanager); + + } + +} diff --git a/aes/src/main/java/cc/winboll/studio/aes/WinBoLLActivity.java b/aes/src/main/java/cc/winboll/studio/aes/WinBoLLActivity.java new file mode 100644 index 0000000..76005db --- /dev/null +++ b/aes/src/main/java/cc/winboll/studio/aes/WinBoLLActivity.java @@ -0,0 +1,60 @@ +package cc.winboll.studio.aes; + +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/09/29 00:11 + * @Describe WinBoLL 窗口基础类 + */ +import android.app.Activity; +import android.os.Bundle; +import android.view.MenuItem; +import androidx.appcompat.app.AppCompatActivity; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; +import cc.winboll.studio.libaes.utils.WinBoLLActivityManager; +import cc.winboll.studio.libappbase.LogUtils; + +public class WinBoLLActivity extends AppCompatActivity implements IWinBoLLActivity { + + public static final String TAG = "WinBoLLActivity"; + + @Override + public Activity getActivity() { + return this; + } + + @Override + public String getTag() { + return TAG; + } + + @Override + protected void onResume() { + super.onResume(); + LogUtils.d(TAG, String.format("onResume %s", getTag())); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + /*if (item.getItemId() == R.id.item_log) { + WinBoLLActivityManager.getInstance().startLogActivity(this); + return true; + } else if (item.getItemId() == R.id.item_home) { + startActivity(new Intent(this, MainActivity.class)); + return true; + }*/ + // 在switch语句中处理每个ID,并在处理完后返回true,未处理的情况返回false。 + return super.onOptionsItemSelected(item); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + WinBoLLActivityManager.getInstance().add(this); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + WinBoLLActivityManager.getInstance().registeRemove(this); + } +} diff --git a/aes/src/main/res/layout/activity_testactivitymanager.xml b/aes/src/main/res/layout/activity_testactivitymanager.xml new file mode 100644 index 0000000..e030ebb --- /dev/null +++ b/aes/src/main/res/layout/activity_testactivitymanager.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/aes/src/main/res/menu/toolbar_library.xml b/aes/src/main/res/menu/toolbar_library.xml index b12aef8..7c1a41c 100644 --- a/aes/src/main/res/menu/toolbar_library.xml +++ b/aes/src/main/res/menu/toolbar_library.xml @@ -1,5 +1,8 @@ + diff --git a/libaes/build.gradle b/libaes/build.gradle index c5e54e4..88f73bd 100644 --- a/libaes/build.gradle +++ b/libaes/build.gradle @@ -21,8 +21,8 @@ android { dependencies { api fileTree(dir: 'libs', include: ['*.jar']) - api 'cc.winboll.studio:libapputils:15.8.5' - api 'cc.winboll.studio:libappbase:15.9.5' + api 'cc.winboll.studio:libapputils:15.10.2' + api 'cc.winboll.studio:libappbase:15.10.9' // 吐司类库 api 'com.github.getActivity:ToastUtils:10.5' diff --git a/libaes/build.properties b/libaes/build.properties index b928936..256a906 100644 --- a/libaes/build.properties +++ b/libaes/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Sun Aug 31 05:00:43 CST 2025 -stageCount=4 +#Mon Sep 29 13:04:07 HKT 2025 +stageCount=3 libraryProject=libaes -baseVersion=15.9 -publishVersion=15.9.3 +baseVersion=15.10 +publishVersion=15.10.2 buildCount=0 -baseBetaVersion=15.9.4 +baseBetaVersion=15.10.3 diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/activitys/DrawerFragmentActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/activitys/DrawerFragmentActivity.java index 4436433..812089e 100644 --- a/libaes/src/main/java/cc/winboll/studio/libaes/activitys/DrawerFragmentActivity.java +++ b/libaes/src/main/java/cc/winboll/studio/libaes/activitys/DrawerFragmentActivity.java @@ -23,17 +23,16 @@ import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; import cc.winboll.studio.libaes.DrawerMenuDataAdapter; import cc.winboll.studio.libaes.R; -import cc.winboll.studio.libaes.beans.AESThemeBean; -import cc.winboll.studio.libaes.beans.DrawerMenuBean; +import cc.winboll.studio.libaes.models.AESThemeBean; +import cc.winboll.studio.libaes.models.DrawerMenuBean; import cc.winboll.studio.libaes.utils.AESThemeUtil; import cc.winboll.studio.libaes.views.ADrawerMenuListView; -import cc.winboll.studio.libappbase.GlobalApplication; import cc.winboll.studio.libappbase.LogUtils; -import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity; import com.baoyz.widget.PullRefreshLayout; import java.util.ArrayList; +import cc.winboll.studio.libaes.utils.WinBoLLActivityManager; -public abstract class DrawerFragmentActivity extends AppCompatActivity implements IWinBoLLActivity,AdapterView.OnItemClickListener { +public abstract class DrawerFragmentActivity extends AppCompatActivity implements AdapterView.OnItemClickListener { public static final String TAG = "DrawerFragmentActivity"; @@ -176,8 +175,6 @@ 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_about == item.getItemId()) { LogUtils.d(TAG, "onAbout"); } else if (android.R.id.home == item.getItemId()) { diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/dialogs/YesNoAlertDialog.java b/libaes/src/main/java/cc/winboll/studio/libaes/dialogs/YesNoAlertDialog.java new file mode 100644 index 0000000..f176daa --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/dialogs/YesNoAlertDialog.java @@ -0,0 +1,60 @@ +package cc.winboll.studio.libaes.dialogs; + +/** + * @Author ZhanGSKen + * @Date 2025/03/28 17:40:47 + * @Date 2024/08/12 14:46:25 + * @Describe 询问用户确定与否的选择框 + */ +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; + +public class YesNoAlertDialog { + + public static final String TAG = "YesNoAlertDialog"; + + public static void show(Context context, String szTitle, String szMessage, final OnDialogResultListener listener) { + AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder( + context); + + // set title + alertDialogBuilder.setTitle(szTitle); + + // set dialog message + alertDialogBuilder + .setMessage(szMessage) + .setCancelable(true) + .setOnCancelListener(new DialogInterface.OnCancelListener(){ + @Override + public void onCancel(DialogInterface dialog) { + listener.onNo(); + } + }) + .setPositiveButton("YES", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + // if this button is clicked, close + // current activity + listener.onYes(); + } + }) + .setNegativeButton("NO", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + // if this button is clicked, just close + // the dialog box and do nothing + dialog.cancel(); + } + }); + + // create alert dialog + AlertDialog alertDialog = alertDialogBuilder.create(); + + // show it + alertDialog.show(); + } + + public interface OnDialogResultListener { + abstract void onYes(); + abstract void onNo(); + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/interfaces/IWinBoLLActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/interfaces/IWinBoLLActivity.java new file mode 100644 index 0000000..aa4805b --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/interfaces/IWinBoLLActivity.java @@ -0,0 +1,18 @@ +package cc.winboll.studio.libaes.interfaces; + +/** + * @Author ZhanGSKen + * @Date 2025/05/10 09:34 + * @Describe WinBoLL 窗口操作接口 + */ + import android.app.Activity; + +public abstract interface IWinBoLLActivity { + + public static final String TAG = "IWinBoLLActivity"; + + public static final String ACTION_BIND = IWinBoLLActivity.class.getName() + ".ACTION_BIND"; + + public Activity getActivity(); + public String getTag(); +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/beans/AESThemeBean.java b/libaes/src/main/java/cc/winboll/studio/libaes/models/AESThemeBean.java similarity index 99% rename from libaes/src/main/java/cc/winboll/studio/libaes/beans/AESThemeBean.java rename to libaes/src/main/java/cc/winboll/studio/libaes/models/AESThemeBean.java index eaf61db..50a7876 100644 --- a/libaes/src/main/java/cc/winboll/studio/libaes/beans/AESThemeBean.java +++ b/libaes/src/main/java/cc/winboll/studio/libaes/models/AESThemeBean.java @@ -1,4 +1,4 @@ -package cc.winboll.studio.libaes.beans; +package cc.winboll.studio.libaes.models; /** * @Author ZhanGSKen diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/APPInfo.java b/libaes/src/main/java/cc/winboll/studio/libaes/models/APPInfo.java similarity index 99% rename from libaes/src/main/java/cc/winboll/studio/libaes/winboll/APPInfo.java rename to libaes/src/main/java/cc/winboll/studio/libaes/models/APPInfo.java index 94248e8..cf097e0 100644 --- a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/APPInfo.java +++ b/libaes/src/main/java/cc/winboll/studio/libaes/models/APPInfo.java @@ -1,4 +1,4 @@ -package cc.winboll.studio.libaes.winboll; +package cc.winboll.studio.libaes.models; /** * @Author ZhanGSKen diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/beans/DrawerMenuBean.java b/libaes/src/main/java/cc/winboll/studio/libaes/models/DrawerMenuBean.java similarity index 94% rename from libaes/src/main/java/cc/winboll/studio/libaes/beans/DrawerMenuBean.java rename to libaes/src/main/java/cc/winboll/studio/libaes/models/DrawerMenuBean.java index fd9c862..662d4d4 100644 --- a/libaes/src/main/java/cc/winboll/studio/libaes/beans/DrawerMenuBean.java +++ b/libaes/src/main/java/cc/winboll/studio/libaes/models/DrawerMenuBean.java @@ -1,4 +1,4 @@ -package cc.winboll.studio.libaes.beans; +package cc.winboll.studio.libaes.models; /** * @Author ZhanGSKen diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/beans/WinBoLLClientServiceBean.java b/libaes/src/main/java/cc/winboll/studio/libaes/models/WinBoLLClientServiceBean.java similarity index 98% rename from libaes/src/main/java/cc/winboll/studio/libaes/beans/WinBoLLClientServiceBean.java rename to libaes/src/main/java/cc/winboll/studio/libaes/models/WinBoLLClientServiceBean.java index 32bb757..dcd112b 100644 --- a/libaes/src/main/java/cc/winboll/studio/libaes/beans/WinBoLLClientServiceBean.java +++ b/libaes/src/main/java/cc/winboll/studio/libaes/models/WinBoLLClientServiceBean.java @@ -1,4 +1,4 @@ -package cc.winboll.studio.libaes.beans; +package cc.winboll.studio.libaes.models; /** * @Author ZhanGSKen diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/SecondaryLibraryActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/SecondaryLibraryActivity.java index a605d79..2373d6a 100644 --- a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/SecondaryLibraryActivity.java +++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/SecondaryLibraryActivity.java @@ -7,7 +7,7 @@ import android.view.MenuItem; import android.widget.Toast; import cc.winboll.studio.libaes.R; import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity; -import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; /** * @Author ZhanGSKen diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestASupportToolbarActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestASupportToolbarActivity.java index 9359246..6fa37b6 100644 --- a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestASupportToolbarActivity.java +++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestASupportToolbarActivity.java @@ -10,8 +10,8 @@ import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; import cc.winboll.studio.libaes.utils.AESThemeUtil; -import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity; public class TestASupportToolbarActivity extends AppCompatActivity implements IWinBoLLActivity { diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAToolbarActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAToolbarActivity.java index 64d8ce0..bba25fc 100644 --- a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAToolbarActivity.java +++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAToolbarActivity.java @@ -10,22 +10,11 @@ import android.os.Bundle; import android.widget.Toolbar; import cc.winboll.studio.libaes.R; import cc.winboll.studio.libaes.utils.AESThemeUtil; -import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity; -public class TestAToolbarActivity extends Activity implements IWinBoLLActivity { +public class TestAToolbarActivity extends Activity { public static final String TAG = "TestAToolbarActivity"; - @Override - public Activity getActivity() { - return this; - } - - @Override - public String getTag() { - return TAG; - } - @Override protected void onCreate(Bundle savedInstanceState) { AESThemeUtil.applyAppTheme(this); diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestDrawerFragmentActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestDrawerFragmentActivity.java index e9d1b65..ab4fc2b 100644 --- a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestDrawerFragmentActivity.java +++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestDrawerFragmentActivity.java @@ -14,9 +14,9 @@ import android.widget.Toast; import androidx.fragment.app.Fragment; import cc.winboll.studio.libaes.R; import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity; -import cc.winboll.studio.libaes.beans.DrawerMenuBean; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; +import cc.winboll.studio.libaes.models.DrawerMenuBean; import cc.winboll.studio.libappbase.LogUtils; -import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity; import java.util.ArrayList; public class TestDrawerFragmentActivity extends DrawerFragmentActivity implements IWinBoLLActivity { diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/utils/AESThemeUtil.java b/libaes/src/main/java/cc/winboll/studio/libaes/utils/AESThemeUtil.java index e705f3c..0e7e354 100644 --- a/libaes/src/main/java/cc/winboll/studio/libaes/utils/AESThemeUtil.java +++ b/libaes/src/main/java/cc/winboll/studio/libaes/utils/AESThemeUtil.java @@ -12,7 +12,7 @@ import android.view.MenuItem; import androidx.appcompat.app.AppCompatActivity; import cc.winboll.studio.libaes.R; import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity; -import cc.winboll.studio.libaes.beans.AESThemeBean; +import cc.winboll.studio.libaes.models.AESThemeBean; public class AESThemeUtil { diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/utils/MyActivityLifecycleCallbacks.java b/libaes/src/main/java/cc/winboll/studio/libaes/utils/MyActivityLifecycleCallbacks.java new file mode 100644 index 0000000..d32928d --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/utils/MyActivityLifecycleCallbacks.java @@ -0,0 +1,97 @@ +package cc.winboll.studio.libaes.utils; + +/** + * @Author ZhanGSKen + * @Date 2025/03/25 04:29:19 + */ +import android.app.Activity; +import android.app.Application; +import android.content.Intent; +import android.os.Bundle; +import cc.winboll.studio.libappbase.LogUtils; + +public class MyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks { + + public static final String TAG = "MyActivityLifecycleCallbacks"; + + public String mInfo = ""; + + public MyActivityLifecycleCallbacks() { + + } + + void createActivityeInfo(Activity activity) { + StringBuilder sb = new StringBuilder(); + Intent receivedIntent = activity.getIntent(); + sb.append("\nCallingActivity : \n"); + if (activity.getCallingActivity() != null) { + sb.append(activity.getCallingActivity().getPackageName()); + } + sb.append("\nReceived Intent Package : \n"); + sb.append(receivedIntent.getPackage()); + + Bundle extras = receivedIntent.getExtras(); + if (extras != null) { + for (String key : extras.keySet()) { + sb.append("\nIntentInfo"); + sb.append("\n键: "); + sb.append(key); + sb.append(", 值: "); + sb.append(extras.get(key)); + //Log.d("IntentInfo", "键: " + key + ", 值: " + extras.get(key)); + } + } + mInfo = sb.toString(); + //Log.d("IntentInfo", "发送Intent的应用包名: " + senderPackage); + } + + public void showActivityeInfo() { + //ToastUtils.show("ActivityeInfo : " + mInfo); + LogUtils.d(TAG, "ActivityeInfo : " + mInfo); + } + + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + // 在这里可以做一些初始化相关的操作,例如记录Activity的创建时间等 + //System.out.println(activity.getLocalClassName() + " was created"); + LogUtils.d(TAG, activity.getLocalClassName() + " was created"); + createActivityeInfo(activity); + } + + @Override + public void onActivityStarted(Activity activity) { + //System.out.println(activity.getLocalClassName() + " was started"); + LogUtils.d(TAG, activity.getLocalClassName() + " was started"); + //createActivityeInfo(activity); + } + + @Override + public void onActivityResumed(Activity activity) { + //System.out.println(activity.getLocalClassName() + " was resumed"); + LogUtils.d(TAG, activity.getLocalClassName() + " was resumed"); + //createActivityeInfo(activity); + } + + @Override + public void onActivityPaused(Activity activity) { + //System.out.println(activity.getLocalClassName() + " was paused"); + LogUtils.d(TAG, activity.getLocalClassName() + " was paused"); + } + + @Override + public void onActivityStopped(Activity activity) { + //System.out.println(activity.getLocalClassName() + " was stopped"); + LogUtils.d(TAG, activity.getLocalClassName() + " was stopped"); + } + + @Override + public void onActivitySaveInstanceState(Activity activity, Bundle outState) { + // 可以在这里添加保存状态的自定义逻辑 + } + + @Override + public void onActivityDestroyed(Activity activity) { + //System.out.println(activity.getLocalClassName() + " was destroyed"); + LogUtils.d(TAG, activity.getLocalClassName() + " was destroyed"); + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/utils/WinBoLLActivityManager.java b/libaes/src/main/java/cc/winboll/studio/libaes/utils/WinBoLLActivityManager.java new file mode 100644 index 0000000..c95d302 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/utils/WinBoLLActivityManager.java @@ -0,0 +1,292 @@ +package cc.winboll.studio.libaes.utils; + +/** + * @Author ZhanGSKen + * @Date 2025/05/10 10:02 + * @Describe 应用活动窗口管理器 + * 参考 : + * android 类似微信小程序多任务窗口 及 设置 TaskDescription 修改 icon 和 label + * https://blog.csdn.net/qq_29364417/article/details/109379915?app_version=6.4.2&code=app_1562916241&csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22109379915%22%2C%22source%22%3A%22weixin_38986226%22%7D&uLinkId=usr1mkqgl919blen&utm_source=app + */ +import android.app.Activity; +import android.app.ActivityManager; +import android.content.Context; +import android.content.Intent; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; +import cc.winboll.studio.libappbase.GlobalApplication; +import cc.winboll.studio.libappbase.LogActivity; +import cc.winboll.studio.libappbase.LogUtils; +import cc.winboll.studio.libappbase.ToastUtils; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class WinBoLLActivityManager { + + public static final String TAG = "WinBoLLActivityManager"; + + public static final String EXTRA_TAG = "EXTRA_TAG"; + + + public enum WinBoLLUI_TYPE { Aplication, Service } + + GlobalApplication mGlobalApplication; + volatile static WinBoLLActivityManager _mIWinBoLLActivityManager; + Map mActivityListMap; + + volatile static WinBoLLUI_TYPE _WinBoLLUI_TYPE = WinBoLLUI_TYPE.Service; + public static void setWinBoLLUI_TYPE(WinBoLLUI_TYPE winBoLLUI_TYPE) { + _WinBoLLUI_TYPE = winBoLLUI_TYPE; + } + + public static WinBoLLUI_TYPE getWinBoLLUI_TYPE() { + return _WinBoLLUI_TYPE; + } + + WinBoLLActivityManager(GlobalApplication application) { + mGlobalApplication = application; + mActivityListMap = new HashMap(); + } + + public static WinBoLLActivityManager getInstance() { + return _mIWinBoLLActivityManager; + } + + public static synchronized void init(T application) { + if (_mIWinBoLLActivityManager == null) { + _mIWinBoLLActivityManager = new WinBoLLActivityManager(application); + } + } + + /** + * 把Activity添加到管理中 + */ + public void add(T activity) { + if (isActivityActive(activity.getTag())) { + LogUtils.d(TAG, String.format("add(...) %s is active.", activity.getTag())); + } else { + mActivityListMap.put(activity.getTag(), activity); + LogUtils.d(TAG, String.format("Add activity : %s\n_mapActivityList.size() : %d", activity.getTag(), mActivityListMap.size())); + } + } + + // + // activity: 为 null 时, + // intent.putExtra 函数 "tag" 参数为 tag + // activity: 不为 null 时, + // intent.putExtra 函数 "tag" 参数为 activity.getTag() + // + public void startWinBoLLActivity(Context context, Class clazz) { + // 如果窗口已存在就重启窗口 + if (!resumeActivity(clazz)) { + // 新建一个任务窗口 + 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); + context.startActivity(intent); + } + } + + public void startWinBoLLActivity(Context context, Intent intent, Class clazz) { + // 如果窗口已存在就重启窗口 + if (!resumeActivity(clazz)) { + // 新建一个任务窗口 + //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); + context.startActivity(intent); + } + } + + public void startLogActivity(Context context) { + // 如果窗口已存在就重启窗口 + //if (!resumeActivity(LogActivity.class)) { + // 新建一个任务窗口 + Intent intent = new Intent(context, LogActivity.class); + //打开多任务窗口 flags + // Define the bounds. +// Rect bounds = new Rect(0, 0, 800, 200); +// // Set the bounds as an activity option. +// ActivityOptions options = ActivityOptions.makeBasic(); +// options.setLaunchBounds(bounds); + intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); + intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + + //intent.putExtra(EXTRA_TAG, tag); + + //context.startActivity(intent, options.toBundle()); + context.startActivity(intent); + //} + } + + // + // 判断 tag 绑定的 Activity 是否已经创建 + // + public boolean isActivityActive(String tag) { + return mActivityListMap.get(tag) != null; + } + + Activity getActivityByTag(String tag) { + return (mActivityListMap.get(tag) == null) ?null: mActivityListMap.get(tag).getActivity(); + } + + + // + // 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台 + // + public boolean resumeActivity(Class clazz) { + try { + Activity activity = getActivityByTag(clazz.newInstance().getTag()); + if (activity != null) { + return resumeActivity(activity); + } + } catch (InstantiationException | IllegalAccessException e) { + LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); + } + return false; + } + + // + // 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台 + // + public boolean resumeActivity(String tag) { + Activity activity = getActivityByTag(tag); + if (activity != null) { + return resumeActivity(activity); + } + return false; + } + + // + // 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台 + // + public boolean resumeActivity(Activity activity) { + ActivityManager am = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE); + //返回启动它的根任务(home 或者 MainActivity) + //Intent intent = new Intent(mContext, activity.getClass()); + //TaskStackBuilder stackBuilder = TaskStackBuilder.create(mContext); + //stackBuilder.addNextIntentWithParentStack(intent); + //stackBuilder.startActivities(); + am.moveTaskToFront(activity.getTaskId(), ActivityManager.MOVE_TASK_NO_USER_ACTION); + //ToastUtils.show("resumeActivity"); + return true; + } + + + /** + * 结束所有 Activity + */ + public void finishAll() { + try { + //ToastUtils.show(String.format("finishAll() size : %d", _mIWinBoLLActivityList.size())); + for (int i = mActivityListMap.size() - 1; i > -1; i--) { + IWinBoLLActivity iWinBoLLActivity = mActivityListMap.get(i); + ToastUtils.show("finishAll() activity"); + if (iWinBoLLActivity != null && iWinBoLLActivity.getActivity() != null && !iWinBoLLActivity.getActivity().isFinishing() && !iWinBoLLActivity.getActivity().isDestroyed()) { + //ToastUtils.show("activity != null ..."); + if (getWinBoLLUI_TYPE() == WinBoLLUI_TYPE.Service) { + // 结束窗口和最近任务栏, 建议前台服务类应用使用,可以方便用户再次调用 UI 操作。 + iWinBoLLActivity.getActivity().finishAndRemoveTask(); + //ToastUtils.show("finishAll() activity.finishAndRemoveTask();"); + } else if (getWinBoLLUI_TYPE() == WinBoLLUI_TYPE.Aplication) { + // 结束窗口保留最近任务栏,建议前台服务类应用使用,可以保持应用的系统自觉性。 + iWinBoLLActivity.getActivity().finish(); + //ToastUtils.show("finishAll() activity.finish();"); + } else { + ToastUtils.show("WinBollApplication.WinBollUI_TYPE error."); + } + } + } + } catch (Exception e) { + LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); + } + } + + /** + * 结束指定Activity + */ + public void finish(T iWinBoLLActivity) { + try { + if (iWinBoLLActivity != null && iWinBoLLActivity.getActivity() != null && !iWinBoLLActivity.getActivity().isFinishing() && !iWinBoLLActivity.getActivity().isDestroyed()) { + //根据tag 移除 MyActivity + //String tag= activity.getTag(); + //_mIWinBoLLActivityList.remove(tag); + //ToastUtils.show("remove"); + //ToastUtils.show("_mIWinBoLLActivityArrayMap.size() " + Integer.toString(_mIWinBoLLActivityArrayMap.size())); + + // 窗口回调规则: + // [] 当前窗口位置 >> 调度出的窗口位置 + // ★:[0] 1 2 3 4 >> 1 + // ★:0 1 [2] 3 4 >> 1 + // ★:0 1 2 [3] 4 >> 2 + // ★:0 1 2 3 [4] >> 3 + // ★:[0] >> 直接关闭当前窗口 + Activity preActivity = getPreActivity(iWinBoLLActivity); + iWinBoLLActivity.getActivity().finish(); + if (preActivity != null) { + resumeActivity(preActivity); + } + } + + } catch (Exception e) { + LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); + } + } + + Activity getPreActivity(IWinBoLLActivity iWinBoLLActivity) { + try { + boolean bingo = false; + IWinBoLLActivity preIWinBoLLActivity = null; + for (Map.Entry entity : mActivityListMap.entrySet()) { + if (entity.getKey().equals(iWinBoLLActivity.getTag())) { + bingo = true; + LogUtils.d(TAG, "bingo"); + break; + } + preIWinBoLLActivity = entity.getValue(); + } + + if (bingo) { + return preIWinBoLLActivity.getActivity(); + } + } catch (Exception e) { + LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); + } + + return null; + } + + public boolean registeRemove(T iWinBoLLActivity) { + IWinBoLLActivity iWinBoLLActivityTest = mActivityListMap.get(iWinBoLLActivity.getTag()); + if (iWinBoLLActivityTest != null) { + mActivityListMap.remove(iWinBoLLActivity.getTag()); + return true; + } + return false; + } + + public void printAvtivityListInfo() { + if (!mActivityListMap.isEmpty()) { + StringBuilder sb = new StringBuilder("Map entries : " + Integer.toString(mActivityListMap.size())); + Iterator> iterator = mActivityListMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + sb.append("\nKey: " + entry.getKey() + ", \nValue: " + entry.getValue().getTag()); + //ToastUtils.show("\nKey: " + entry.getKey() + ", Value: " + entry.getValue().getTag()); + } + sb.append("\nMap entries end."); + LogUtils.d(TAG, sb.toString()); + } else { + LogUtils.d(TAG, "The map is empty."); + } + } +} + diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AboutView.java b/libaes/src/main/java/cc/winboll/studio/libaes/views/AboutView.java similarity index 79% rename from libaes/src/main/java/cc/winboll/studio/libaes/winboll/AboutView.java rename to libaes/src/main/java/cc/winboll/studio/libaes/views/AboutView.java index dc11ae5..41ddb8d 100644 --- a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AboutView.java +++ b/libaes/src/main/java/cc/winboll/studio/libaes/views/AboutView.java @@ -1,4 +1,4 @@ -package cc.winboll.studio.libaes.winboll; +package cc.winboll.studio.libaes.views; /** * @Author ZhanGSKen @@ -17,10 +17,12 @@ import android.view.View; import android.widget.EditText; import android.widget.LinearLayout; import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libaes.dialogs.YesNoAlertDialog; +import cc.winboll.studio.libaes.models.APPInfo; import cc.winboll.studio.libaes.utils.AppVersionUtils; +import cc.winboll.studio.libaes.utils.WinBoLLActivityManager; import cc.winboll.studio.libappbase.GlobalApplication; import cc.winboll.studio.libappbase.LogUtils; -import cc.winboll.studio.libappbase.dialogs.YesNoAlertDialog; import cc.winboll.studio.libapputils.utils.PrefUtils; import com.hjq.toast.ToastUtils; import java.io.IOException; @@ -32,7 +34,6 @@ import okhttp3.Credentials; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; -import mehdi.sakout.aboutpage.BuildConfig; public class AboutView extends LinearLayout { @@ -40,10 +41,10 @@ public class AboutView extends LinearLayout { public static final int MSG_APPUPDATE_CHECKED = 0; - Context mContext; + static Context _mContext; APPInfo mAPPInfo; - WinBoLLServiceStatusView mWinBoLLServiceStatusView; + //WinBoLLServiceStatusView mWinBoLLServiceStatusView; OnRequestDevUserInfoAutofillListener mOnRequestDevUserInfoAutofillListener; String mszAppName = ""; String mszAppAPKFolderName = ""; @@ -64,7 +65,7 @@ public class AboutView extends LinearLayout { public AboutView(Context context, APPInfo appInfo) { super(context); - mContext = context; + _mContext = context; setAPPInfo(appInfo); initView(context); @@ -72,7 +73,7 @@ public class AboutView extends LinearLayout { public AboutView(Context context, AttributeSet attrs) { super(context, attrs); - mContext = context; + _mContext = context; initView(context, attrs); } @@ -110,7 +111,7 @@ public class AboutView extends LinearLayout { mszWinBoLLServerHost = GlobalApplication.isDebuging() ? "https://yun-preivew.winboll.cc": "https://yun.winboll.cc"; try { - mszAppVersionName = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName; + mszAppVersionName = _mContext.getPackageManager().getPackageInfo(_mContext.getPackageName(), 0).versionName; } catch (PackageManager.NameNotFoundException e) { LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); } @@ -122,35 +123,8 @@ public class AboutView extends LinearLayout { } else { mszGitea = "https://gitea.winboll.cc/" + mAPPInfo.getAppGitOwner() + "/" + mszAppGitName + "/src/branch/" + mAPPInfo.getAppGitAPPBranch() + "/" + mAPPInfo.getAppGitAPPSubProjectFolder(); } - - - if (GlobalApplication.isDebuging()) { - LayoutInflater inflater = LayoutInflater.from(mContext); - View addedView = inflater.inflate(R.layout.view_about_dev, this, false); - LinearLayout llMain = addedView.findViewById(R.id.viewaboutdevLinearLayout1); - metDevUserName = addedView.findViewById(R.id.viewaboutdevEditText1); - metDevUserPassword = addedView.findViewById(R.id.viewaboutdevEditText2); - metDevUserName.setText(PrefUtils.getString(mContext, "metDevUserName", "")); - metDevUserPassword.setText(PrefUtils.getString(mContext, "metDevUserPassword", "")); - //mDevelopHostConnectionStatusView = new DevelopHostConnectionStatusView(context); - mWinBoLLServiceStatusView = addedView.findViewById(R.id.viewaboutdevWinBoLLServiceStatusView1); - mWinBoLLServiceStatusView.setServerHost(mszWinBoLLServerHost); - mWinBoLLServiceStatusView.setAuthInfo(metDevUserName.getText().toString(), metDevUserPassword.getText().toString()); - //llMain.addView(mDevelopHostConnectionStatusView); - llMain.addView(createAboutPage()); - addView(addedView); - } else { - LayoutInflater inflater = LayoutInflater.from(mContext); - View addedView = inflater.inflate(R.layout.view_about_www, this, false); - LinearLayout llMain = addedView.findViewById(R.id.viewaboutwwwLinearLayout1); - //mDevelopHostConnectionStatusView = new DevelopHostConnectionStatusView(context); - mWinBoLLServiceStatusView = addedView.findViewById(R.id.viewaboutwwwWinBoLLServiceStatusView1); - mWinBoLLServiceStatusView.setServerHost(mszWinBoLLServerHost); - mWinBoLLServiceStatusView.setAuthInfo("", ""); - //llMain.addView(mDevelopHostConnectionStatusView); - llMain.addView(createAboutPage()); - addView(addedView); - } + + addView(createAboutPage()); // 初始化标题栏 //setSubtitle(getContext().getString(R.string.text_about)); @@ -162,9 +136,9 @@ public class AboutView extends LinearLayout { String szReleaseAppVersionName = ""; try { //LogUtils.d(TAG, String.format("mContext.getPackageName() %s", mContext.getPackageName())); - String szSubBetaSuffix = subBetaSuffix(mContext.getPackageName()); + String szSubBetaSuffix = subBetaSuffix(_mContext.getPackageName()); //LogUtils.d(TAG, String.format("szSubBetaSuffix : %s", szSubBetaSuffix)); - szReleaseAppVersionName = mContext.getPackageManager().getPackageInfo(szSubBetaSuffix, 0).versionName; + szReleaseAppVersionName = _mContext.getPackageManager().getPackageInfo(szSubBetaSuffix, 0).versionName; } catch (PackageManager.NameNotFoundException e) { LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); } @@ -205,7 +179,7 @@ public class AboutView extends LinearLayout { String szMsg = "Current app is :\n[ " + mszCurrentAppPackageName + " ]\nThe last app is :\n[ " + mszNewestAppPackageName + " ]\nIs download the last app?"; - YesNoAlertDialog.show(mContext, "Application Update Prompt", szMsg, mIsDownlaodUpdateListener); + YesNoAlertDialog.show(_mContext, "Application Update Prompt", szMsg, mIsDownlaodUpdateListener); } break; } @@ -216,22 +190,22 @@ public class AboutView extends LinearLayout { protected View createAboutPage() { // 定义 GitWeb 按钮 // - Element elementGitWeb = new Element(mContext.getString(R.string.gitea_home), R.drawable.ic_winboll); + Element elementGitWeb = new Element(_mContext.getString(R.string.gitea_home), R.drawable.ic_winboll); elementGitWeb.setOnClickListener(mGitWebOnClickListener); // 定义检查更新按钮 // - Element elementAppUpdate = new Element(mContext.getString(R.string.app_update), R.drawable.ic_winboll); + Element elementAppUpdate = new Element(_mContext.getString(R.string.app_update), R.drawable.ic_winboll); elementAppUpdate.setOnClickListener(mAppUpdateOnClickListener); String szAppInfo = ""; try { szAppInfo = mszAppName + " " - + mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName + + _mContext.getPackageManager().getPackageInfo(_mContext.getPackageName(), 0).versionName + "\n" + mszAppDescription; } catch (PackageManager.NameNotFoundException e) { LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); } - AboutPage aboutPage = new AboutPage(mContext); + AboutPage aboutPage = new AboutPage(_mContext); aboutPage.setDescription(szAppInfo) //.isRTL(false) //.setCustomFont(String) // or Typeface @@ -256,10 +230,10 @@ public class AboutView extends LinearLayout { // Element elementAppMode; if (GlobalApplication.isDebuging()) { - elementAppMode = new Element(mContext.getString(R.string.app_normal), R.drawable.ic_winboll); + elementAppMode = new Element(_mContext.getString(R.string.app_normal), R.drawable.ic_winboll); elementAppMode.setOnClickListener(mAppNormalOnClickListener); } else { - elementAppMode = new Element(mContext.getString(R.string.app_debug), R.drawable.ic_winboll); + elementAppMode = new Element(_mContext.getString(R.string.app_debug), R.drawable.ic_winboll); elementAppMode.setOnClickListener(mAppDebugOnClickListener); } aboutPage.addItem(elementAppMode); @@ -272,7 +246,7 @@ public class AboutView extends LinearLayout { @Override public void onClick(View view) { //ToastUtils.show("mAppDebugOnClickListener"); - setApp2DebugMode(mContext); + setApp2DebugMode(_mContext); } }; @@ -280,7 +254,7 @@ public class AboutView extends LinearLayout { @Override public void onClick(View view) { //ToastUtils.show("mAppNormalOnClickListener"); - setApp2NormalMode(mContext); + setApp2NormalMode(_mContext); } }; @@ -290,9 +264,9 @@ public class AboutView extends LinearLayout { //intent.setAction(cc.winboll.studio.libapputils.intent.action.DEBUGVIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); GlobalApplication.setIsDebuging(true); - GlobalApplication.saveDebugStatus(); + GlobalApplication.saveDebugStatus(_mContext); - GlobalApplication.getWinBoLLActivityManager().finishAll(); + WinBoLLActivityManager.getInstance().finishAll(); context.startActivity(intent); } } @@ -302,9 +276,9 @@ public class AboutView extends LinearLayout { if (intent != null) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); GlobalApplication.setIsDebuging(false); - GlobalApplication.saveDebugStatus(); + GlobalApplication.saveDebugStatus(_mContext); - GlobalApplication.getWinBoLLActivityManager().finishAll(); + WinBoLLActivityManager.getInstance().finishAll(); context.startActivity(intent); } } @@ -313,7 +287,7 @@ public class AboutView extends LinearLayout { @Override public void onClick(View view) { Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(mszGitea)); - mContext.startActivity(browserIntent); + _mContext.startActivity(browserIntent); } }; @@ -329,8 +303,8 @@ public class AboutView extends LinearLayout { String credential = ""; if (GlobalApplication.isDebuging()) { credential = Credentials.basic(metDevUserName.getText().toString(), metDevUserPassword.getText().toString()); - PrefUtils.saveString(mContext, "metDevUserName", metDevUserName.getText().toString()); - PrefUtils.saveString(mContext, "metDevUserPassword", metDevUserPassword.getText().toString()); + PrefUtils.saveString(_mContext, "metDevUserName", metDevUserName.getText().toString()); + PrefUtils.saveString(_mContext, "metDevUserPassword", metDevUserPassword.getText().toString()); } else { String username = "WinBoLL"; String password = "WinBoLLPowerByZhanGSKen"; @@ -387,7 +361,7 @@ public class AboutView extends LinearLayout { public void onYes() { String szUrl = mszWinBoLLServerHost + "/studio/download.php?appname=" + mszAppAPKFolderName + "&apkname=" + mszNewestAppPackageName; Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(szUrl)); - mContext.startActivity(browserIntent); + _mContext.startActivity(browserIntent); } @Override diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AssistantService.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AssistantService.java deleted file mode 100644 index 36fb68b..0000000 --- a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AssistantService.java +++ /dev/null @@ -1,97 +0,0 @@ -package cc.winboll.studio.libaes.winboll; - -/** - * @Author ZhanGSKen - * @Date 2025/03/28 19:12:12 - * @Describe 应用主要服务组件类守护进程服务组件类 - */ -import android.app.Service; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.IBinder; -import cc.winboll.studio.libaes.beans.WinBoLLClientServiceBean; -import cc.winboll.studio.libaes.winboll.AssistantService; -import cc.winboll.studio.libappbase.utils.ServiceUtils; - -public class AssistantService extends Service { - - public final static String TAG = "AssistantService"; - - WinBoLLClientServiceBean mWinBoLLServiceBean; - MyServiceConnection mMyServiceConnection; - volatile boolean mIsServiceRunning; - - @Override - public IBinder onBind(Intent intent) { - return null; - } - - @Override - public void onCreate() { - super.onCreate(); - mWinBoLLServiceBean = WinBoLLClientServiceBean.loadWinBoLLClientServiceBean(this); - if (mMyServiceConnection == null) { - mMyServiceConnection = new MyServiceConnection(); - } - // 设置运行参数 - mIsServiceRunning = false; - run(); - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - run(); - return START_STICKY; - } - - @Override - public void onDestroy() { - mIsServiceRunning = false; - super.onDestroy(); - } - - // - // 运行服务内容 - // - void run() { - mWinBoLLServiceBean = WinBoLLClientServiceBean.loadWinBoLLClientServiceBean(this); - if (mWinBoLLServiceBean.isEnable()) { - if (mIsServiceRunning == false) { - // 设置运行状态 - mIsServiceRunning = true; - // 唤醒和绑定主进程 - wakeupAndBindMain(); - } - } - } - - // - // 唤醒和绑定主进程 - // - void wakeupAndBindMain() { - if (ServiceUtils.isServiceRunning(getApplicationContext(), WinBoLLClientService.class.getName()) == false) { - startForegroundService(new Intent(AssistantService.this, WinBoLLClientService.class)); - } - - bindService(new Intent(AssistantService.this, WinBoLLClientService.class), mMyServiceConnection, Context.BIND_IMPORTANT); - } - - // - // 主进程与守护进程连接时需要用到此类 - // - class MyServiceConnection implements ServiceConnection { - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - } - - @Override - public void onServiceDisconnected(ComponentName name) { - mWinBoLLServiceBean = WinBoLLClientServiceBean.loadWinBoLLClientServiceBean(AssistantService.this); - if (mWinBoLLServiceBean.isEnable()) { - wakeupAndBindMain(); - } - } - } -} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/EWUIStatusIconDrawable.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/EWUIStatusIconDrawable.java deleted file mode 100644 index 86fd15e..0000000 --- a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/EWUIStatusIconDrawable.java +++ /dev/null @@ -1,35 +0,0 @@ -package cc.winboll.studio.libaes.winboll; - -/** - * @Author ZhanGSKen - * @Date 2025/03/28 19:11:27 - * @Describe WinBoLL UI 状态图标枚举 - */ -import cc.winboll.studio.libaes.R; - -public enum EWUIStatusIconDrawable { - NORMAL(0), - NEWS(1) - ; - - static final String TAG = "WUIStatusIconDrawable"; - - static String[] _mlistCNName = { "正常", "新的消息" }; - - private int value = 0; - private EWUIStatusIconDrawable(int value) { //必须是private的,否则编译错误 - this.value = value; - } - - public static int getIconDrawableId(EWUIStatusIconDrawable drawableId) { - int res; - switch(drawableId){ - case NEWS : - res = R.drawable.ic_winbollbeta; - break; - default : - res = R.drawable.ic_winboll; - } - return res; - } -} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBoLLClientService.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBoLLClientService.java deleted file mode 100644 index d4e93a6..0000000 --- a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBoLLClientService.java +++ /dev/null @@ -1,21 +0,0 @@ -package cc.winboll.studio.libaes.winboll; - -import android.app.Service; -import android.content.Intent; -import android.os.IBinder; - -/** - * @Author ZhanGSKen - * @Date 2025/05/03 19:28 - */ -public class WinBoLLClientService extends Service { - - public static final String TAG = "WinBoLLClientService"; - - @Override - public IBinder onBind(Intent intent) { - - return null; - } - -} \ No newline at end of file diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBoLLServiceStatusView.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBoLLServiceStatusView.java deleted file mode 100644 index 14a56e2..0000000 --- a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBoLLServiceStatusView.java +++ /dev/null @@ -1,38 +0,0 @@ -package cc.winboll.studio.libaes.winboll; -import android.content.Context; -import android.util.AttributeSet; -import android.widget.LinearLayout; - -/** - * @Author ZhanGSKen - * @Date 2025/05/03 19:14 - */ -public class WinBoLLServiceStatusView extends LinearLayout { - - public static final String TAG = "WinBoLLServiceStatusView"; - - public WinBoLLServiceStatusView(Context context) { - super(context); - } - - public WinBoLLServiceStatusView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public WinBoLLServiceStatusView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public WinBoLLServiceStatusView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - - void setServerHost(String szWinBoLLServerHost) { - - } - - void setAuthInfo(String szDevUserName, String szDevUserPassword) { - - } -} diff --git a/libaes/src/main/res/layout/view_about_dev.xml b/libaes/src/main/res/layout/view_about_dev.xml deleted file mode 100644 index 1443e19..0000000 --- a/libaes/src/main/res/layout/view_about_dev.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libaes/src/main/res/layout/view_about_www.xml b/libaes/src/main/res/layout/view_about_www.xml deleted file mode 100644 index 8cbe538..0000000 --- a/libaes/src/main/res/layout/view_about_www.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - diff --git a/positions/.gitignore b/positions/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/positions/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/positions/README.md b/positions/README.md new file mode 100644 index 0000000..ae1cc39 --- /dev/null +++ b/positions/README.md @@ -0,0 +1,34 @@ +# Positions + +#### 介绍 +安卓位置应用,有关于地理位置的相关应用。 + +#### 软件架构 +适配安卓应用 [AIDE Pro] 的 Gradle 编译结构。 +也适配安卓应用 [AndroidIDE] 的 Gradle 编译结构。 + + +#### Gradle 编译说明 +调试版编译命令 :gradle assembleBetaDebug +阶段版编译命令 :bash .winboll/bashPublishAPKAddTag.sh positions + +#### 使用说明 + +#### 参与贡献 + +1. Fork 本仓库 +2. 新建 Feat_xxx 分支 +3. 提交代码 : ZhanGSKen(ZhanGSKen) +4. 新建 Pull Request + + +#### 特技 + +1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md +2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) +3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 +4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 +5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) +6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) + +#### 参考文档 diff --git a/positions/app_update_description.txt b/positions/app_update_description.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/positions/app_update_description.txt @@ -0,0 +1 @@ + diff --git a/positions/build.gradle b/positions/build.gradle new file mode 100644 index 0000000..b8401af --- /dev/null +++ b/positions/build.gradle @@ -0,0 +1,73 @@ +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.positions" + 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.9.3' + api 'cc.winboll.studio:libapputils:15.8.5' + api 'cc.winboll.studio:libappbase:15.9.5' +} diff --git a/positions/build.properties b/positions/build.properties new file mode 100644 index 0000000..7d34a4a --- /dev/null +++ b/positions/build.properties @@ -0,0 +1,8 @@ +#Created by .winboll/winboll_app_build.gradle +#Mon Sep 29 09:07:13 GMT 2025 +stageCount=0 +libraryProject= +baseVersion=15.0 +publishVersion=15.0.0 +buildCount=1 +baseBetaVersion=15.0.1 diff --git a/positions/proguard-rules.pro b/positions/proguard-rules.pro new file mode 100644 index 0000000..64b4a05 --- /dev/null +++ b/positions/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/positions/src/beta/AndroidManifest.xml b/positions/src/beta/AndroidManifest.xml new file mode 100644 index 0000000..ee78d9f --- /dev/null +++ b/positions/src/beta/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/positions/src/beta/res/values/strings.xml b/positions/src/beta/res/values/strings.xml new file mode 100644 index 0000000..5dc93b9 --- /dev/null +++ b/positions/src/beta/res/values/strings.xml @@ -0,0 +1,6 @@ + + + + Positions + + + diff --git a/positions/src/main/AndroidManifest.xml b/positions/src/main/AndroidManifest.xml new file mode 100644 index 0000000..ac87126 --- /dev/null +++ b/positions/src/main/AndroidManifest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/positions/src/main/java/cc/winboll/studio/positions/App.java b/positions/src/main/java/cc/winboll/studio/positions/App.java new file mode 100644 index 0000000..08ae159 --- /dev/null +++ b/positions/src/main/java/cc/winboll/studio/positions/App.java @@ -0,0 +1,345 @@ +package cc.winboll.studio.positions; + +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 head = new LinkedHashMap(); + head.put("Time Of Crash", time); + head.put("Device", String.format("%s, %s", Build.MANUFACTURER, Build.MODEL)); + head.put("Android Version", String.format("%s (%d)", Build.VERSION.RELEASE, Build.VERSION.SDK_INT)); + head.put("App Version", String.format("%s (%d)", versionName, versionCode)); + head.put("Kernel", getKernel()); + head.put("Support Abis", Build.VERSION.SDK_INT >= 21 && Build.SUPPORTED_ABIS != null ? Arrays.toString(Build.SUPPORTED_ABIS): "unknown"); + head.put("Fingerprint", Build.FINGERPRINT); + + StringBuilder builder = new StringBuilder(); + + for (String key : head.keySet()) { + if (builder.length() != 0) builder.append("\n"); + builder.append(key); + builder.append(" : "); + builder.append(head.get(key)); + } + + builder.append("\n\n"); + builder.append(Log.getStackTraceString(throwable)); + + return builder.toString(); + } + + private void writeLog(String log) { + String time = DATE_FORMAT.format(new Date()); + File file = new File(mCrashDir, "crash_" + time + ".txt"); + try { + write(file, log.getBytes("UTF-8")); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + private static String getKernel() { + try { + return 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(); + } + } +} diff --git a/positions/src/main/java/cc/winboll/studio/positions/MainActivity.java b/positions/src/main/java/cc/winboll/studio/positions/MainActivity.java new file mode 100644 index 0000000..f824af5 --- /dev/null +++ b/positions/src/main/java/cc/winboll/studio/positions/MainActivity.java @@ -0,0 +1,31 @@ +package cc.winboll.studio.positions; + +import android.os.Bundle; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import cc.winboll.studio.libappbase.LogView; +import com.hjq.toast.ToastUtils; + +public class MainActivity extends AppCompatActivity { + + LogView mLogView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + Toolbar toolbar=(Toolbar)findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + mLogView = findViewById(R.id.logview); + + ToastUtils.show("onCreate"); + } + + @Override + protected void onResume() { + super.onResume(); + mLogView.start(); + } +} diff --git a/positions/src/main/res/drawable-v24/ic_launcher_foreground.xml b/positions/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/positions/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/positions/src/main/res/drawable/ic_launcher_background.xml b/positions/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/positions/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/positions/src/main/res/layout/activity_main.xml b/positions/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..8000fb4 --- /dev/null +++ b/positions/src/main/res/layout/activity_main.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/positions/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/positions/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/positions/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/positions/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/positions/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/positions/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/positions/src/main/res/mipmap-hdpi/ic_launcher.png b/positions/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a2f5908 Binary files /dev/null and b/positions/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/positions/src/main/res/mipmap-hdpi/ic_launcher_round.png b/positions/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..1b52399 Binary files /dev/null and b/positions/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/positions/src/main/res/mipmap-mdpi/ic_launcher.png b/positions/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..ff10afd Binary files /dev/null and b/positions/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/positions/src/main/res/mipmap-mdpi/ic_launcher_round.png b/positions/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..115a4c7 Binary files /dev/null and b/positions/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/positions/src/main/res/mipmap-xhdpi/ic_launcher.png b/positions/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..dcd3cd8 Binary files /dev/null and b/positions/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/positions/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/positions/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..459ca60 Binary files /dev/null and b/positions/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/positions/src/main/res/mipmap-xxhdpi/ic_launcher.png b/positions/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..8ca12fe Binary files /dev/null and b/positions/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/positions/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/positions/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..8e19b41 Binary files /dev/null and b/positions/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/positions/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/positions/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..b824ebd Binary files /dev/null and b/positions/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/positions/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/positions/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..4c19a13 Binary files /dev/null and b/positions/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/positions/src/main/res/values/colors.xml b/positions/src/main/res/values/colors.xml new file mode 100644 index 0000000..479769a --- /dev/null +++ b/positions/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #009688 + #00796B + #FF9800 + \ No newline at end of file diff --git a/positions/src/main/res/values/strings.xml b/positions/src/main/res/values/strings.xml new file mode 100644 index 0000000..81d18c9 --- /dev/null +++ b/positions/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + Positions + + diff --git a/positions/src/main/res/values/styles.xml b/positions/src/main/res/values/styles.xml new file mode 100644 index 0000000..a70e242 --- /dev/null +++ b/positions/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/positions/src/stage/AndroidManifest.xml b/positions/src/stage/AndroidManifest.xml new file mode 100644 index 0000000..ee78d9f --- /dev/null +++ b/positions/src/stage/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/positions/src/stage/res/values/strings.xml b/positions/src/stage/res/values/strings.xml new file mode 100644 index 0000000..ace0c41 --- /dev/null +++ b/positions/src/stage/res/values/strings.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/settings.gradle-demo b/settings.gradle-demo index c208459..cf7adb4 100644 --- a/settings.gradle-demo +++ b/settings.gradle-demo @@ -64,4 +64,8 @@ // WebPageSources 项目编译设置 //include ':webpagesources' -//rootProject.name = "webpagesources" \ No newline at end of file +//rootProject.name = "webpagesources" + +// Positions 项目编译设置 +//include ':positions' +//rootProject.name = "positions"