Compare commits
56 Commits
apputils-v
...
appbase-v1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
36af7947e8 | ||
![]() |
805edcf9c4 | ||
![]() |
11005e3356 | ||
![]() |
75361b2313 | ||
![]() |
1d29ce81e8 | ||
![]() |
0297e81090 | ||
![]() |
df7203e985 | ||
![]() |
8c4e8b8e23 | ||
![]() |
d9c02f55e3 | ||
![]() |
a9cb6b471b | ||
![]() |
e694063867 | ||
![]() |
0ee13986dc | ||
![]() |
3239778922 | ||
![]() |
13510f45cf | ||
![]() |
49d300dd33 | ||
![]() |
c42f677d48 | ||
![]() |
9052a3924b | ||
![]() |
9642ad1966 | ||
![]() |
6686da0e8f | ||
![]() |
9e7aff09d1 | ||
![]() |
494b2b7fbc | ||
![]() |
b1f9b74e28 | ||
![]() |
32287e17c0 | ||
![]() |
8a0605c12e | ||
![]() |
5768881a47 | ||
![]() |
6e02c130b2 | ||
![]() |
fb9443bbc7 | ||
![]() |
bfc1180822 | ||
![]() |
ee52a6c28c | ||
![]() |
2f72f1795e | ||
![]() |
db28447c0f | ||
![]() |
ad2c29d8ff | ||
![]() |
b0e3bfe243 | ||
![]() |
7b1aeeae8b | ||
![]() |
54cceeed3b | ||
![]() |
a72c5e1e6e | ||
![]() |
26fcd9b584 | ||
![]() |
ea7a0bda14 | ||
![]() |
b26b9dbbc4 | ||
![]() |
8a405d33a7 | ||
![]() |
2b92da3e01 | ||
![]() |
ac1c9fb9f5 | ||
![]() |
16dd559c5b | ||
![]() |
3793ae3252 | ||
![]() |
dc8f127a8d | ||
![]() |
3cf4155eab | ||
![]() |
7ca144bfc4 | ||
![]() |
73222d3272 | ||
![]() |
b9c9eb926d | ||
![]() |
35efcdddcd | ||
![]() |
fc5ac32514 | ||
![]() |
afa8a97dba | ||
![]() |
fe004c7b82 | ||
![]() |
b9582cb99d | ||
![]() |
b3a69283ab | ||
![]() |
36e10db8e3 |
@@ -29,7 +29,7 @@ android {
|
||||
// versionName 更新后需要手动设置
|
||||
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
|
||||
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
|
||||
versionName "1.0"
|
||||
versionName "1.4"
|
||||
if(true) {
|
||||
versionName = genVersionName("${versionName}")
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Sun Jan 05 02:30:11 GMT 2025
|
||||
stageCount=0
|
||||
libraryProject=
|
||||
baseVersion=1.0
|
||||
publishVersion=1.0.0
|
||||
buildCount=2
|
||||
baseBetaVersion=1.0.1
|
||||
#Wed Feb 12 18:03:55 HKT 2025
|
||||
stageCount=2
|
||||
libraryProject=libappbase
|
||||
baseVersion=1.4
|
||||
publishVersion=1.4.1
|
||||
buildCount=0
|
||||
baseBetaVersion=1.4.2
|
||||
|
@@ -5,12 +5,19 @@ package cc.winboll.studio.appbase;
|
||||
* @Date 2025/01/05 09:54:42
|
||||
* @Describe APPbase 应用类
|
||||
*/
|
||||
import cc.winboll.studio.GlobalApplication;
|
||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
|
||||
public class App extends GlobalApplication {
|
||||
|
||||
|
||||
public static final String TAG = "App";
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
GlobalApplication.setIsDebuging(this, BuildConfig.DEBUG);
|
||||
super.onCreate();
|
||||
LogUtils.setLogLevel(LogUtils.LOG_LEVEL.Debug);
|
||||
LogUtils.setALlTAGListEnable(true);
|
||||
LogUtils.d(TAG, "LogUtils init");
|
||||
}
|
||||
}
|
||||
|
@@ -1,15 +1,30 @@
|
||||
package cc.winboll.studio.appbase;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class MainActivity extends Activity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
package cc.winboll.studio.appbase;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
ToastUtils.show("onCreate");
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
Toolbar toolbar = findViewById(R.id.activitymainToolbar1);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
CheckBox cbIsDebugMode = findViewById(R.id.activitymainCheckBox1);
|
||||
cbIsDebugMode.setChecked(GlobalApplication.isDebuging());
|
||||
|
||||
}
|
||||
|
||||
public void onSwitchDebugMode(View view) {
|
||||
GlobalApplication.setIsDebuging(this, ((CheckBox)view).isChecked());
|
||||
}
|
||||
}
|
||||
|
@@ -4,13 +4,50 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello, WinBoll!"
|
||||
android:onClick="onHello"/>
|
||||
android:id="@+id/activitymainToolbar1"/>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1.0"
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello, WinBoll!"/>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="right|center_vertical">
|
||||
|
||||
<CheckBox
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Debug Mode"
|
||||
android:layout_weight="1.0"
|
||||
android:onClick="onSwitchDebugMode"
|
||||
android:id="@+id/activitymainCheckBox1"/>
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Test Application CrashReport"
|
||||
android:textAllCaps="false"
|
||||
android:onClick="onTestApplicationCrashReport"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="AppTheme" parent="@android:style/Theme.Material.Light.DarkActionBar">
|
||||
<item name="android:colorPrimary">@color/colorPrimary</item>
|
||||
<item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="android:colorAccent">@color/colorAccent</item>
|
||||
<item name="android:navigationBarColor">?android:colorPrimary</item>
|
||||
</style>
|
||||
</resources>
|
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#009688</color>
|
||||
<color name="colorPrimaryDark">#00796B</color>
|
||||
<color name="colorAccent">#FF9800</color>
|
||||
</resources>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#005800FF</color>
|
||||
<color name="colorPrimaryDark">#005800FF</color>
|
||||
<color name="colorAccent">#005800FF</color>
|
||||
</resources>
|
||||
|
@@ -1,5 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="AppTheme" parent="@android:style/Theme.Holo.Light.DarkActionBar">
|
||||
</style>
|
||||
</resources>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="AppTheme" parent="APPBaseTheme">
|
||||
<item name="themeGlobalCrashActivity">@style/MyGlobalCrashActivityTheme</item>
|
||||
</style>
|
||||
|
||||
<style name="MyGlobalCrashActivityTheme" parent="GlobalCrashActivityTheme">
|
||||
<item name="colorTittle">#FFFFFFFF</item>
|
||||
<item name="colorTittleBackgound">#FF00A4B3</item>
|
||||
<item name="colorText">#FFFFFFFF</item>
|
||||
<item name="colorTextBackgound">#FF000000</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
@@ -29,7 +29,7 @@ android {
|
||||
// versionName 更新后需要手动设置
|
||||
// 项目模块目录的 build.gradle 文件的 stageCount=0
|
||||
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
|
||||
versionName "9.3"
|
||||
versionName "9.2"
|
||||
if(true) {
|
||||
versionName = genVersionName("${versionName}")
|
||||
}
|
||||
@@ -50,6 +50,6 @@ android {
|
||||
|
||||
dependencies {
|
||||
api project(':libapputils')
|
||||
|
||||
api 'cc.winboll.studio:libappbase:1.0.3'
|
||||
api fileTree(dir: 'libs', include: ['*.jar'])
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Tue Feb 04 08:54:03 HKT 2025
|
||||
stageCount=1
|
||||
#Sat Jan 18 13:03:10 HKT 2025
|
||||
stageCount=2
|
||||
libraryProject=libapputils
|
||||
baseVersion=9.3
|
||||
publishVersion=9.3.0
|
||||
baseVersion=9.2
|
||||
publishVersion=9.2.1
|
||||
buildCount=0
|
||||
baseBetaVersion=9.3.1
|
||||
baseBetaVersion=9.2.2
|
||||
|
@@ -5,19 +5,27 @@ package cc.winboll.studio.apputils;
|
||||
* @Date 2024/12/08 15:10:51
|
||||
* @Describe 全局应用类
|
||||
*/
|
||||
import android.widget.Toast;
|
||||
import cc.winboll.studio.libapputils.app.WinBollGlobalApplication;
|
||||
import android.view.Gravity;
|
||||
import cc.winboll.studio.libapputils.app.WinBollApplication;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import com.hjq.toast.style.WhiteToastStyle;
|
||||
|
||||
public class App extends WinBollGlobalApplication {
|
||||
public class App extends WinBollApplication {
|
||||
|
||||
public static final String TAG = "App";
|
||||
|
||||
public static final String _ACTION_DEBUGVIEW = App.class.getName() + "_ACTION_DEBUGVIEW";
|
||||
public static final String _ACTION_DEBUGVIEW = WinBollApplication.class.getName() + "_ACTION_DEBUGVIEW";
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Toast.makeText(getApplication(), "Toast Test", Toast.LENGTH_SHORT).show();
|
||||
// 初始化 Toast 框架
|
||||
//
|
||||
ToastUtils.init(this);
|
||||
// 设置 Toast 布局样式
|
||||
//ToastUtils.setView(R.layout.view_toast);
|
||||
ToastUtils.setStyle(new WhiteToastStyle());
|
||||
ToastUtils.setGravity(Gravity.BOTTOM, 0, 200);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -14,8 +14,6 @@ import cc.winboll.studio.libapputils.app.WinBollActivityManager;
|
||||
import cc.winboll.studio.libapputils.log.LogActivity;
|
||||
import cc.winboll.studio.libapputils.log.LogUtils;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import cc.winboll.studio.libapputils.activities.AboutActivity;
|
||||
import cc.winboll.studio.libapputils.bean.APPInfo;
|
||||
|
||||
final public class MainActivity extends WinBollActivity {
|
||||
|
||||
@@ -52,13 +50,10 @@ final public class MainActivity extends WinBollActivity {
|
||||
}
|
||||
|
||||
public void onLogUtilsClick(View view) {
|
||||
// Intent intent = new Intent(this, LogActivity.class);
|
||||
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
|
||||
// intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
|
||||
// startActivity(intent);
|
||||
|
||||
//WinBollActivityManager.getInstance().printAvtivityListInfo();
|
||||
WinBollActivityManager.getInstance(this).startWinBollActivity(this, LogActivity.class);
|
||||
Intent intent = new Intent(this, LogActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -160,35 +155,9 @@ final public class MainActivity extends WinBollActivity {
|
||||
} else if (item.getItemId() == R.id.item_testqrcodedecodeactivity) {
|
||||
Intent intent = new Intent(this, QRCodeDecodeActivity.class);
|
||||
startActivityForResult(intent, REQUEST_QRCODEDECODE_ACTIVITY);
|
||||
} else if(item.getItemId() == R.id.item_about) {
|
||||
openAboutActivity();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
void openAboutActivity() {
|
||||
Intent intent = new Intent(this, AboutActivity.class);
|
||||
APPInfo appInfo = new APPInfo();
|
||||
appInfo.setAppName("APPUtils");
|
||||
appInfo.setAppIcon(cc.winboll.studio.libapputils.R.drawable.ic_winboll);
|
||||
appInfo.setAppDescription("APPUtils Description");
|
||||
appInfo.setAppGitName("APP");
|
||||
appInfo.setAppGitOwner("Studio");
|
||||
appInfo.setAppGitAPPBranch("apputils");
|
||||
appInfo.setAppGitAPPSubProjectFolder("apputils");
|
||||
appInfo.setAppHomePage("https://www.winboll.cc/studio/details.php?app=APP");
|
||||
appInfo.setAppAPKName("APPUtils");
|
||||
appInfo.setAppAPKFolderName("APPUtils");
|
||||
intent.putExtra(AboutActivity.EXTRA_APPINFO, appInfo);
|
||||
WinBollActivityManager.getInstance(this).startWinBollActivity(this, intent, AboutActivity.class);
|
||||
}
|
||||
|
||||
|
||||
public void onTestAboutActivity(View view) {
|
||||
//ToastUtils.show("onTestAboutActivity");
|
||||
openAboutActivity();
|
||||
}
|
||||
|
||||
public void onTestJavascriptHtmlActivity(View view) {
|
||||
Intent intent = new Intent(this, AssetsHtmlActivity.class);
|
||||
|
@@ -54,21 +54,6 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<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:textAllCaps="false"
|
||||
android:text="Test AboutActivity"
|
||||
android:onClick="onTestAboutActivity"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
@@ -4,7 +4,7 @@ apply from: '../.winboll/winboll_lib_build.gradle'
|
||||
apply from: '../.winboll/winboll_lint_build.gradle'
|
||||
|
||||
android {
|
||||
namespace 'cc.winboll.studio'
|
||||
namespace 'cc.winboll.studio.libappbase'
|
||||
|
||||
compileSdkVersion 32
|
||||
buildToolsVersion "33.0.3"
|
||||
@@ -26,5 +26,11 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api 'com.github.getActivity:ToastUtils:10.5'
|
||||
|
||||
api 'androidx.appcompat:appcompat:1.3.1'
|
||||
//api 'androidx.vectordrawable:vectordrawable:1.1.0'
|
||||
//api 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
|
||||
|
||||
api fileTree(dir: 'libs', include: ['*.jar'])
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Sun Jan 05 07:55:11 HKT 2025
|
||||
stageCount=17
|
||||
libraryProject=winboll-shared
|
||||
baseVersion=1.8
|
||||
publishVersion=1.8.16
|
||||
#Wed Feb 12 18:03:55 HKT 2025
|
||||
stageCount=2
|
||||
libraryProject=libappbase
|
||||
baseVersion=1.4
|
||||
publishVersion=1.4.1
|
||||
buildCount=0
|
||||
baseBetaVersion=1.8.17
|
||||
baseBetaVersion=1.4.2
|
||||
|
@@ -1,18 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="cc.winboll.studio" >
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="cc.winboll.studio.libappbase">
|
||||
|
||||
<!-- 拥有完全的网络访问权限 -->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<application>
|
||||
|
||||
<activity
|
||||
android:name=".CrashHandler$CrashActiviy"
|
||||
android:label="CrashActiviy"
|
||||
android:name=".CrashHandler$CrashActivity"
|
||||
android:label="CrashActivity"
|
||||
android:launchMode="standard"/>
|
||||
|
||||
|
||||
<activity
|
||||
android:name=".libappbase.LibraryActivity"
|
||||
android:label="@string/lib_name" >
|
||||
</activity>
|
||||
android:name=".GlobalCrashActivity"
|
||||
android:label="GlobalCrashActivity"
|
||||
android:launchMode="standard"/>
|
||||
|
||||
<service android:name=".SimpleOperateSignalCenterService"/>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
</manifest>
|
@@ -1,215 +0,0 @@
|
||||
package cc.winboll.studio;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@QQ.COM
|
||||
* @Date 2024/08/12 13:22:12
|
||||
* @Describe 异常处理类
|
||||
*/
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
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 java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class CrashHandler {
|
||||
|
||||
public static final UncaughtExceptionHandler DEFAULT_UNCAUGHT_EXCEPTION_HANDLER = Thread.getDefaultUncaughtExceptionHandler();
|
||||
|
||||
public static void init(Application app) {
|
||||
init(app, null);
|
||||
}
|
||||
|
||||
public static void init(final Application app, final String crashDir) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler(){
|
||||
|
||||
@Override
|
||||
public void uncaughtException(Thread thread, Throwable throwable) {
|
||||
try {
|
||||
tryUncaughtException(thread, throwable);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
if (DEFAULT_UNCAUGHT_EXCEPTION_HANDLER != null)
|
||||
DEFAULT_UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(thread, throwable);
|
||||
}
|
||||
}
|
||||
|
||||
private void tryUncaughtException(Thread thread, Throwable throwable) {
|
||||
final String time = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss", Locale.getDefault()).format(new Date());
|
||||
File crashFile = new File(TextUtils.isEmpty(crashDir) ? new File(app.getExternalFilesDir(null), "crash")
|
||||
: new File(crashDir), "crash_" + time + ".txt");
|
||||
|
||||
String versionName = "unknown";
|
||||
long versionCode = 0;
|
||||
try {
|
||||
PackageInfo packageInfo = app.getPackageManager().getPackageInfo(app.getPackageName(), 0);
|
||||
versionName = packageInfo.versionName;
|
||||
versionCode = Build.VERSION.SDK_INT >= 28 ? packageInfo.getLongVersionCode()
|
||||
: packageInfo.versionCode;
|
||||
} catch (PackageManager.NameNotFoundException ignored) {}
|
||||
|
||||
String fullStackTrace; {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
throwable.printStackTrace(pw);
|
||||
fullStackTrace = sw.toString();
|
||||
pw.close();
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("************* Crash Head ****************\n");
|
||||
sb.append("Time Of Crash : ").append(time).append("\n");
|
||||
sb.append("Device Manufacturer: ").append(Build.MANUFACTURER).append("\n");
|
||||
sb.append("Device Model : ").append(Build.MODEL).append("\n");
|
||||
sb.append("Android Version : ").append(Build.VERSION.RELEASE).append("\n");
|
||||
sb.append("Android SDK : ").append(Build.VERSION.SDK_INT).append("\n");
|
||||
sb.append("App VersionName : ").append(versionName).append("\n");
|
||||
sb.append("App VersionCode : ").append(versionCode).append("\n");
|
||||
sb.append("************* Crash Head ****************\n");
|
||||
sb.append("\n").append(fullStackTrace);
|
||||
|
||||
String errorLog = sb.toString();
|
||||
|
||||
try {
|
||||
writeFile(crashFile, errorLog);
|
||||
} catch (IOException ignored) {}
|
||||
|
||||
gotoCrashActiviy: {
|
||||
Intent intent = new Intent(app, CrashActiviy.class);
|
||||
intent.addFlags(
|
||||
Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
);
|
||||
intent.putExtra(CrashActiviy.EXTRA_CRASH_INFO, errorLog);
|
||||
try {
|
||||
app.startActivity(intent);
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
System.exit(0);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
if (DEFAULT_UNCAUGHT_EXCEPTION_HANDLER != null)
|
||||
DEFAULT_UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(thread, throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeFile(File file, String content) throws IOException {
|
||||
File parentFile = file.getParentFile();
|
||||
if (parentFile != null && !parentFile.exists()) {
|
||||
parentFile.mkdirs();
|
||||
}
|
||||
file.createNewFile();
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
fos.write(content.getBytes());
|
||||
try {
|
||||
fos.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public static final class CrashActiviy extends Activity implements MenuItem.OnMenuItemClickListener {
|
||||
|
||||
private static final String EXTRA_CRASH_INFO = "crashInfo";
|
||||
|
||||
private static final int MENUITEM_COPY = 0;
|
||||
private static final int MENUITEM_RESTART = 1;
|
||||
|
||||
private String mLog;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mLog = getIntent().getStringExtra(EXTRA_CRASH_INFO);
|
||||
setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
|
||||
setContentView: {
|
||||
ScrollView contentView = new ScrollView(this);
|
||||
contentView.setFillViewport(true);
|
||||
HorizontalScrollView hw = new HorizontalScrollView(this);
|
||||
hw.setBackgroundColor(Color.GRAY);
|
||||
TextView message = new TextView(this); {
|
||||
int padding = dp2px(16);
|
||||
message.setPadding(padding, padding, padding, padding);
|
||||
message.setText(mLog);
|
||||
message.setTextIsSelectable(true);
|
||||
}
|
||||
hw.addView(message);
|
||||
contentView.addView(hw, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
setContentView(contentView);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
restart();
|
||||
}
|
||||
|
||||
private void restart() {
|
||||
PackageManager pm = getPackageManager();
|
||||
Intent intent = pm.getLaunchIntentForPackage(getPackageName());
|
||||
if (intent != null) {
|
||||
intent.addFlags(
|
||||
Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
);
|
||||
startActivity(intent);
|
||||
}
|
||||
finish();
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private int dp2px(final float dpValue) {
|
||||
final float scale = Resources.getSystem().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case MENUITEM_COPY:
|
||||
ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cm.setPrimaryClip(ClipData.newPlainText(getPackageName(), mLog));
|
||||
break;
|
||||
case MENUITEM_RESTART:
|
||||
restart();
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
menu.add(0, MENUITEM_COPY, 0, "Copy").setOnMenuItemClickListener(this)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
menu.add(0, MENUITEM_RESTART, 0, "Restart").setOnMenuItemClickListener(this)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,95 +0,0 @@
|
||||
package cc.winboll.studio;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@QQ.COM
|
||||
* @Date 2025/01/05 10:10:23
|
||||
* @Describe 全局应用类
|
||||
*/
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.HorizontalScrollView;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class GlobalApplication extends Application {
|
||||
|
||||
private static Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
CrashHandler.init(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) {}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,283 @@
|
||||
package cc.winboll.studio.libappbase;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@QQ.COM
|
||||
* @Date 2025/01/15 11:11:52
|
||||
* @Describe Json Bean 基础类。
|
||||
*/
|
||||
import android.content.Context;
|
||||
import android.util.JsonReader;
|
||||
import android.util.JsonWriter;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public abstract class BaseBean<T extends BaseBean> {
|
||||
|
||||
public static final String TAG = "BaseBean";
|
||||
static final String BEAN_NAME = "BeanName";
|
||||
|
||||
public BaseBean() {}
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
public String getBeanJsonFilePath(Context context) {
|
||||
|
||||
return context.getExternalFilesDir(TAG) + "/" + getName() + ".json";
|
||||
}
|
||||
|
||||
public String getBeanListJsonFilePath(Context context) {
|
||||
|
||||
return context.getExternalFilesDir(TAG) + "/" + getName() + "_List.json";
|
||||
}
|
||||
|
||||
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
|
||||
jsonWriter.name(BEAN_NAME).value(getName());
|
||||
}
|
||||
|
||||
public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
abstract public T readBeanFromJsonReader(JsonReader jsonReader) throws IOException;
|
||||
|
||||
public static <T extends BaseBean> String checkIsTheSameBeanListAndFile(String szFilePath, Class<T> clazz) {
|
||||
StringBuilder sbResult = new StringBuilder();
|
||||
String szErrorInfo = "Check Is The Same Bean List And File Error : ";
|
||||
|
||||
try {
|
||||
int nSameCount = 0;
|
||||
int nBeanListCout = 0;
|
||||
|
||||
T beanTemp = clazz.newInstance();
|
||||
String szBeanSimpleName = beanTemp.getName();
|
||||
String szListJson = UTF8FileUtils.readStringFromFile(szFilePath);
|
||||
StringReader stringReader = new StringReader(szListJson);
|
||||
JsonReader jsonReader = new JsonReader(stringReader);
|
||||
jsonReader.beginArray();
|
||||
while (jsonReader.hasNext()) {
|
||||
nBeanListCout++;
|
||||
jsonReader.beginObject();
|
||||
while (jsonReader.hasNext()) {
|
||||
String name = jsonReader.nextName();
|
||||
if (name.equals(BEAN_NAME)) {
|
||||
if (szBeanSimpleName.equals(jsonReader.nextString())) {
|
||||
nSameCount++;
|
||||
}
|
||||
} else {
|
||||
jsonReader.skipValue();
|
||||
}
|
||||
}
|
||||
jsonReader.endObject();
|
||||
}
|
||||
jsonReader.endArray();
|
||||
|
||||
// 返回检查结果
|
||||
if (nSameCount == nBeanListCout) {
|
||||
// 检查一致直接返回空串
|
||||
return "";
|
||||
} else {
|
||||
// 检查不一致返回对比信息
|
||||
sbResult.append("Total : ");
|
||||
sbResult.append(nBeanListCout);
|
||||
sbResult.append(" Diff : ");
|
||||
sbResult.append(nBeanListCout - nSameCount);
|
||||
}
|
||||
} catch (InstantiationException e) {
|
||||
sbResult.append(szErrorInfo);
|
||||
sbResult.append(e);
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
} catch (IllegalAccessException e) {
|
||||
sbResult.append(szErrorInfo);
|
||||
sbResult.append(e);
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
} catch (IOException e) {
|
||||
sbResult.append(szErrorInfo);
|
||||
sbResult.append(e);
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
}
|
||||
return sbResult.toString();
|
||||
}
|
||||
|
||||
public static <T extends BaseBean> T parseStringToBean(String szBean, Class<T> clazz) throws IOException {
|
||||
// 创建 JsonWriter 对象
|
||||
StringReader stringReader = new StringReader(szBean);
|
||||
JsonReader jsonReader = new JsonReader(stringReader);
|
||||
try {
|
||||
T beanTemp = clazz.newInstance();
|
||||
return (T)beanTemp.readBeanFromJsonReader(jsonReader);
|
||||
} catch (InstantiationException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
} catch (IllegalAccessException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends BaseBean> boolean parseStringToBeanList(String szBeanList, ArrayList<T> beanList, Class<T> clazz) {
|
||||
try {
|
||||
beanList.clear();
|
||||
StringReader stringReader = new StringReader(szBeanList);
|
||||
JsonReader jsonReader = new JsonReader(stringReader);
|
||||
jsonReader.beginArray();
|
||||
while (jsonReader.hasNext()) {
|
||||
T beanTemp = clazz.newInstance();
|
||||
T bean = (T)beanTemp.readBeanFromJsonReader(jsonReader);
|
||||
if (bean != null) {
|
||||
beanList.add(bean);
|
||||
//LogUtils.d(TAG, "beanList.add(bean)");
|
||||
}
|
||||
}
|
||||
jsonReader.endArray();
|
||||
return true;
|
||||
//LogUtils.d(TAG, "beanList.size() is " + Integer.toString(beanList.size()));
|
||||
} catch (InstantiationException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
} catch (IllegalAccessException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// 创建 JsonWriter 对象
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
JsonWriter jsonWriter = new JsonWriter(stringWriter);
|
||||
jsonWriter.setIndent(" ");
|
||||
try {// 开始 JSON 对象
|
||||
jsonWriter.beginObject();
|
||||
// 写入键值对
|
||||
writeThisToJsonWriter(jsonWriter);
|
||||
// 结束 JSON 对象
|
||||
jsonWriter.endObject();
|
||||
return stringWriter.toString();
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
}
|
||||
// 获取 JSON 字符串
|
||||
return "";
|
||||
}
|
||||
|
||||
public static <T extends BaseBean> String toStringByBeanList(ArrayList<T> beanList) {
|
||||
try {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
JsonWriter jsonWriter = new JsonWriter(stringWriter);
|
||||
jsonWriter.setIndent(" ");
|
||||
jsonWriter.beginArray();
|
||||
for (int i = 0; i < beanList.size(); i++) {
|
||||
// 开始 JSON 对象
|
||||
jsonWriter.beginObject();
|
||||
// 写入键值对
|
||||
beanList.get(i).writeThisToJsonWriter(jsonWriter);
|
||||
// 结束 JSON 对象
|
||||
jsonWriter.endObject();
|
||||
}
|
||||
jsonWriter.endArray();
|
||||
jsonWriter.close();
|
||||
return stringWriter.toString();
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
public static <T extends BaseBean> T loadBean(Context context, Class<T> clazz) {
|
||||
try {
|
||||
T beanTemp = clazz.newInstance();
|
||||
return loadBeanFromFile(beanTemp.getBeanJsonFilePath(context), clazz);
|
||||
} catch (InstantiationException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
} catch (IllegalAccessException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends BaseBean> T loadBeanFromFile(String szFilePath, Class<T> clazz) {
|
||||
try {
|
||||
try {
|
||||
File fTemp = new File(szFilePath);
|
||||
if (fTemp.exists()) {
|
||||
T beanTemp = clazz.newInstance();String szJson = UTF8FileUtils.readStringFromFile(szFilePath);
|
||||
return beanTemp.parseStringToBean(szJson, clazz);
|
||||
}
|
||||
} catch (InstantiationException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
} catch (IllegalAccessException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends BaseBean> boolean saveBean(Context context, T bean) {
|
||||
return saveBeanToFile(bean.getBeanJsonFilePath(context), bean);
|
||||
}
|
||||
|
||||
public static <T extends BaseBean> boolean saveBeanToFile(String szFilePath, T bean) {
|
||||
try {
|
||||
String szJson = bean.toString();
|
||||
UTF8FileUtils.writeStringToFile(szFilePath, szJson);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static <T extends BaseBean> boolean loadBeanList(Context context, ArrayList<T> beanListDst, Class<T> clazz) {
|
||||
try {
|
||||
T beanTemp = clazz.newInstance();
|
||||
return loadBeanListFromFile(beanTemp.getBeanListJsonFilePath(context), beanListDst, clazz);
|
||||
} catch (InstantiationException e) {} catch (IllegalAccessException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static <T extends BaseBean> boolean loadBeanListFromFile(String szFilePath, ArrayList<T> beanList, Class<T> clazz) {
|
||||
try {
|
||||
File fTemp = new File(szFilePath);
|
||||
if (fTemp.exists()) {
|
||||
String szListJson = UTF8FileUtils.readStringFromFile(szFilePath);
|
||||
return parseStringToBeanList(szListJson, beanList, clazz);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static <T extends BaseBean> boolean saveBeanList(Context context, ArrayList<T> beanList, Class<T> clazz) {
|
||||
try {
|
||||
T beanTemp = clazz.newInstance();
|
||||
return saveBeanListToFile(beanTemp.getBeanListJsonFilePath(context), beanList);
|
||||
} catch (InstantiationException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
} catch (IllegalAccessException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static <T extends BaseBean> boolean saveBeanListToFile(String szFilePath, ArrayList<T> beanList) {
|
||||
try {
|
||||
String szJson = toStringByBeanList(beanList);
|
||||
UTF8FileUtils.writeStringToFile(szFilePath, szJson);
|
||||
//LogUtils.d(TAG, "FileUtil.writeFile beanList.size() is " + Integer.toString(beanList.size()));
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -0,0 +1,404 @@
|
||||
package cc.winboll.studio.libappbase;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@QQ.COM
|
||||
* @Date 2024/08/12 13:22:12
|
||||
* @Describe 异常处理类
|
||||
*/
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.SpannableString;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.HorizontalScrollView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.Toolbar;
|
||||
import cc.winboll.studio.libappbase.R;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class CrashHandler {
|
||||
|
||||
public static final String TAG = "CrashHandler";
|
||||
|
||||
public static final String TITTLE = "CrashReport";
|
||||
|
||||
public static final String EXTRA_CRASH_INFO = "crashInfo";
|
||||
|
||||
final static String PREFS = CrashHandler.class.getName() + "PREFS";
|
||||
final static String PREFS_CRASHHANDLER_ISCRASHHAPPEN = "PREFS_CRASHHANDLER_ISCRASHHAPPEN";
|
||||
|
||||
public static String _CrashCountFilePath;
|
||||
|
||||
public static final UncaughtExceptionHandler DEFAULT_UNCAUGHT_EXCEPTION_HANDLER = Thread.getDefaultUncaughtExceptionHandler();
|
||||
|
||||
public static void init(Application app) {
|
||||
_CrashCountFilePath = app.getExternalFilesDir("CrashHandler") + "/IsCrashHandlerCrashHappen.dat";
|
||||
LogUtils.d(TAG, String.format("_CrashCountFilePath %s", _CrashCountFilePath));
|
||||
init(app, null);
|
||||
}
|
||||
|
||||
public static void init(final Application app, final String crashDir) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler(){
|
||||
|
||||
@Override
|
||||
public void uncaughtException(Thread thread, Throwable throwable) {
|
||||
try {
|
||||
tryUncaughtException(thread, throwable);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
if (DEFAULT_UNCAUGHT_EXCEPTION_HANDLER != null)
|
||||
DEFAULT_UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(thread, throwable);
|
||||
}
|
||||
}
|
||||
|
||||
private void tryUncaughtException(Thread thread, Throwable throwable) {
|
||||
// 每到这里就燃烧一次保险丝
|
||||
AppCrashSafetyWire.getInstance().burnSafetyWire();
|
||||
|
||||
final String time = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss", Locale.getDefault()).format(new Date());
|
||||
File crashFile = new File(TextUtils.isEmpty(crashDir) ? new File(app.getExternalFilesDir(null), "crash")
|
||||
: new File(crashDir), "crash_" + time + ".txt");
|
||||
|
||||
String versionName = "unknown";
|
||||
long versionCode = 0;
|
||||
try {
|
||||
PackageInfo packageInfo = app.getPackageManager().getPackageInfo(app.getPackageName(), 0);
|
||||
versionName = packageInfo.versionName;
|
||||
versionCode = Build.VERSION.SDK_INT >= 28 ? packageInfo.getLongVersionCode()
|
||||
: packageInfo.versionCode;
|
||||
} catch (PackageManager.NameNotFoundException ignored) {}
|
||||
|
||||
String fullStackTrace; {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
throwable.printStackTrace(pw);
|
||||
fullStackTrace = sw.toString();
|
||||
pw.close();
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("************* Crash Head ****************\n");
|
||||
sb.append("Time Of Crash : ").append(time).append("\n");
|
||||
sb.append("Device Manufacturer : ").append(Build.MANUFACTURER).append("\n");
|
||||
sb.append("Device Model : ").append(Build.MODEL).append("\n");
|
||||
sb.append("Android Version : ").append(Build.VERSION.RELEASE).append("\n");
|
||||
sb.append("Android SDK : ").append(Build.VERSION.SDK_INT).append("\n");
|
||||
sb.append("App VersionName : ").append(versionName).append("\n");
|
||||
sb.append("App VersionCode : ").append(versionCode).append("\n");
|
||||
sb.append("************* Crash Head ****************\n");
|
||||
sb.append("\n").append(fullStackTrace);
|
||||
|
||||
String errorLog = sb.toString();
|
||||
|
||||
try {
|
||||
writeFile(crashFile, errorLog);
|
||||
} catch (IOException ignored) {}
|
||||
|
||||
gotoCrashActiviy: {
|
||||
Intent intent = new Intent();
|
||||
LogUtils.d(TAG, "gotoCrashActiviy: ");
|
||||
if (AppCrashSafetyWire.getInstance().isAppCrashSafetyWireOK()) {
|
||||
LogUtils.d(TAG, "gotoCrashActiviy: isAppCrashSafetyWireOK");
|
||||
intent.setClass(app, GlobalCrashActivity.class);
|
||||
intent.putExtra(EXTRA_CRASH_INFO, errorLog);
|
||||
// 如果发生了 CrashHandler 内部崩溃, 就调用基础的应用崩溃显示类
|
||||
// intent.setClass(app, GlobalCrashActiviy.class);
|
||||
// intent.putExtra(GlobalCrashActiviy.EXTRA_CRASH_INFO, errorLog);
|
||||
} else {
|
||||
LogUtils.d(TAG, "gotoCrashActiviy: else");
|
||||
// 正常状态调用进阶的应用崩溃显示页
|
||||
intent.setClass(app, CrashActivity.class);
|
||||
intent.putExtra(EXTRA_CRASH_INFO, errorLog);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// intent.setClass(app, CrashActiviy.class);
|
||||
// intent.putExtra(CrashActiviy.EXTRA_CRASH_INFO, errorLog);
|
||||
|
||||
|
||||
intent.addFlags(
|
||||
Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
);
|
||||
|
||||
try {
|
||||
app.startActivity(intent);
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
System.exit(0);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
if (DEFAULT_UNCAUGHT_EXCEPTION_HANDLER != null)
|
||||
DEFAULT_UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(thread, throwable);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (DEFAULT_UNCAUGHT_EXCEPTION_HANDLER != null)
|
||||
DEFAULT_UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(thread, throwable);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void writeFile(File file, String content) throws IOException {
|
||||
File parentFile = file.getParentFile();
|
||||
if (parentFile != null && !parentFile.exists()) {
|
||||
parentFile.mkdirs();
|
||||
}
|
||||
file.createNewFile();
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
fos.write(content.getBytes());
|
||||
try {
|
||||
fos.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// 应用崩溃保险丝
|
||||
//
|
||||
public static final class AppCrashSafetyWire {
|
||||
|
||||
volatile static AppCrashSafetyWire _AppCrashSafetyWire;
|
||||
|
||||
volatile Integer currentSafetyLevel; // 熔断值,为 0 表示熔断了。
|
||||
private static final int _MINI = 1;
|
||||
private static final int _MAX = 2;
|
||||
|
||||
AppCrashSafetyWire() {
|
||||
LogUtils.d(TAG, "AppCrashSafetyWire()");
|
||||
currentSafetyLevel = loadCurrentSafetyLevel();
|
||||
}
|
||||
|
||||
public static synchronized AppCrashSafetyWire getInstance() {
|
||||
if (_AppCrashSafetyWire == null) {
|
||||
_AppCrashSafetyWire = new AppCrashSafetyWire();
|
||||
}
|
||||
return _AppCrashSafetyWire;
|
||||
}
|
||||
|
||||
public void setCurrentSafetyLevel(int currentSafetyLevel) {
|
||||
this.currentSafetyLevel = currentSafetyLevel;
|
||||
}
|
||||
|
||||
public int getCurrentSafetyLevel() {
|
||||
return currentSafetyLevel;
|
||||
}
|
||||
|
||||
public void saveCurrentSafetyLevel(int currentSafetyLevel) {
|
||||
LogUtils.d(TAG, "saveCurrentSafetyLevel()");
|
||||
this.currentSafetyLevel = currentSafetyLevel;
|
||||
try {
|
||||
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(_CrashCountFilePath));
|
||||
oos.writeInt(currentSafetyLevel);
|
||||
oos.flush();
|
||||
oos.close();
|
||||
LogUtils.d(TAG, String.format("saveCurrentSafetyLevel writeInt currentSafetyLevel %d", currentSafetyLevel));
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
}
|
||||
|
||||
public int loadCurrentSafetyLevel() {
|
||||
LogUtils.d(TAG, "loadCurrentSafetyLevel()");
|
||||
try {
|
||||
File f = new File(_CrashCountFilePath);
|
||||
if (f.exists()) {
|
||||
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(_CrashCountFilePath));
|
||||
currentSafetyLevel = ois.readInt();
|
||||
LogUtils.d(TAG, String.format("loadCurrentSafetyLevel() readInt currentSafetyLevel %d", currentSafetyLevel));
|
||||
} else {
|
||||
currentSafetyLevel = _MAX;
|
||||
LogUtils.d(TAG, String.format("loadCurrentSafetyLevel() currentSafetyLevel init to _MAX->%d", _MAX));
|
||||
saveCurrentSafetyLevel(currentSafetyLevel);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
return currentSafetyLevel;
|
||||
}
|
||||
|
||||
boolean burnSafetyWire() {
|
||||
LogUtils.d(TAG, "burnSafetyWire()");
|
||||
// 崩溃计数进入崩溃保险值
|
||||
int safeLevel = loadCurrentSafetyLevel();
|
||||
if (isSafetyWireWorking(safeLevel)) {
|
||||
// 如果保险丝未熔断, 就增加一次熔断值
|
||||
LogUtils.d(TAG, "burnSafetyWire() use");
|
||||
saveCurrentSafetyLevel(safeLevel - 1);
|
||||
return isSafetyWireWorking(safeLevel - 1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isSafetyWireWorking(int safetyLevel) {
|
||||
LogUtils.d(TAG, "isSafetyWireOK()");
|
||||
//safetyLevel = _MINI;
|
||||
//safetyLevel = _MINI - 1;
|
||||
//safetyLevel = _MINI + 1;
|
||||
//safetyLevel = _MAX;
|
||||
//safetyLevel = _MAX + 1;
|
||||
LogUtils.d(TAG, String.format("SafetyLevel %d", safetyLevel));
|
||||
|
||||
if (safetyLevel >= _MINI && safetyLevel <= _MAX) {
|
||||
// 如果在保险值之内
|
||||
LogUtils.d(TAG, String.format("In Safety Level"));
|
||||
return true;
|
||||
}
|
||||
LogUtils.d(TAG, String.format("Out of Safety Level"));
|
||||
return false;
|
||||
}
|
||||
|
||||
void resumeToMaximumImmediately() {
|
||||
LogUtils.d(TAG, "resumeToMaximumImmediately() call saveCurrentSafetyLevel(_MAX)");
|
||||
AppCrashSafetyWire.getInstance().saveCurrentSafetyLevel(_MAX);
|
||||
}
|
||||
|
||||
void off() {
|
||||
LogUtils.d(TAG, "off()");
|
||||
saveCurrentSafetyLevel(_MINI);
|
||||
}
|
||||
|
||||
boolean isAppCrashSafetyWireOK() {
|
||||
LogUtils.d(TAG, "isAppCrashSafetyWireOK()");
|
||||
currentSafetyLevel = loadCurrentSafetyLevel();
|
||||
return isSafetyWireWorking(currentSafetyLevel);
|
||||
}
|
||||
|
||||
// 调用函数以启用持续崩溃保险,从而调用 CrashHandler 内部崩溃处理窗口
|
||||
void postResumeCrashSafetyWireHandler(final Context context) {
|
||||
new Handler(Looper.getMainLooper()).postDelayed(new Runnable(){
|
||||
@Override
|
||||
public void run() {
|
||||
LogUtils.d(TAG, "Handler run()");
|
||||
if (!AppCrashSafetyWire.getInstance().isSafetyWireWorking(currentSafetyLevel - 1)) {
|
||||
// 如果下一次应用崩溃时,保险丝熔断,则先恢复保险丝满能状态
|
||||
// 进程持续运行时,恢复保险丝熔断值
|
||||
//Resume to maximum
|
||||
AppCrashSafetyWire.getInstance().resumeToMaximumImmediately();
|
||||
LogUtils.d(TAG, "postResumeCrashSafetyWireHandler");
|
||||
}
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class CrashActivity extends Activity implements MenuItem.OnMenuItemClickListener {
|
||||
private static final int MENUITEM_COPY = 0;
|
||||
private static final int MENUITEM_RESTART = 1;
|
||||
|
||||
private String mLog;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
AppCrashSafetyWire.getInstance().postResumeCrashSafetyWireHandler(getApplicationContext());
|
||||
|
||||
mLog = getIntent().getStringExtra(EXTRA_CRASH_INFO);
|
||||
setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
|
||||
setContentView: {
|
||||
ScrollView contentView = new ScrollView(this);
|
||||
contentView.setFillViewport(true);
|
||||
|
||||
HorizontalScrollView hw = new HorizontalScrollView(this);
|
||||
hw.setBackgroundColor(Color.GRAY);
|
||||
TextView message = new TextView(this); {
|
||||
int padding = dp2px(16);
|
||||
message.setPadding(padding, padding, padding, padding);
|
||||
message.setText(mLog);
|
||||
message.setTextIsSelectable(true);
|
||||
}
|
||||
hw.addView(message);
|
||||
|
||||
contentView.addView(hw, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
setContentView(contentView);
|
||||
getActionBar().setTitle(TITTLE);
|
||||
getActionBar().setSubtitle(GlobalApplication.class.getSimpleName() + " Error");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
restart();
|
||||
}
|
||||
|
||||
private void restart() {
|
||||
PackageManager pm = getPackageManager();
|
||||
Intent intent = pm.getLaunchIntentForPackage(getPackageName());
|
||||
if (intent != null) {
|
||||
intent.addFlags(
|
||||
Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
);
|
||||
startActivity(intent);
|
||||
}
|
||||
finish();
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private int dp2px(final float dpValue) {
|
||||
final float scale = Resources.getSystem().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case MENUITEM_COPY:
|
||||
ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cm.setPrimaryClip(ClipData.newPlainText(getPackageName(), mLog));
|
||||
Toast.makeText(getApplication(), "The text is copied.", Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
case MENUITEM_RESTART:
|
||||
AppCrashSafetyWire.getInstance().resumeToMaximumImmediately();
|
||||
restart();
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
menu.add(0, MENUITEM_COPY, 0, "Copy").setOnMenuItemClickListener(this)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
menu.add(0, MENUITEM_RESTART, 0, "Restart").setOnMenuItemClickListener(this)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,94 @@
|
||||
package cc.winboll.studio.libappbase;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@QQ.COM
|
||||
* @Date 2025/01/05 10:10:23
|
||||
* @Describe 全局应用类
|
||||
*/
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.Gravity;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import com.hjq.toast.style.WhiteToastStyle;
|
||||
|
||||
public class GlobalApplication extends Application {
|
||||
|
||||
public static final String TAG = "GlobalApplication";
|
||||
|
||||
final static String PREFS = GlobalApplication.class.getName() + "PREFS";
|
||||
final static String PREFS_ISDEBUGING = "PREFS_ISDEBUGING";
|
||||
|
||||
|
||||
private static Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
|
||||
|
||||
// 是否处于调试状态
|
||||
volatile static boolean isDebuging = false;
|
||||
|
||||
public static void setIsDebuging(Context context, boolean isDebuging) {
|
||||
GlobalApplication.isDebuging = isDebuging;
|
||||
// 获取SharedPreferences实例
|
||||
SharedPreferences sharedPreferences = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
|
||||
// 获取编辑器
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
// 保存数据
|
||||
editor.putBoolean(PREFS_ISDEBUGING, GlobalApplication.isDebuging);
|
||||
// 提交更改
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public static boolean isDebuging() {
|
||||
return isDebuging;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getApplicationContext() {
|
||||
return super.getApplicationContext();
|
||||
}
|
||||
|
||||
public Application getApplication() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
//GlobalApplication.isDebuging = true;
|
||||
//GlobalApplication.setIsDebuging(this, true);
|
||||
LogUtils.init(this);
|
||||
//LogUtils.setLogLevel(LogUtils.LOG_LEVEL.Debug);
|
||||
//LogUtils.setTAGListEnable(GlobalApplication.TAG, true);
|
||||
//LogUtils.setALlTAGListEnable(true);
|
||||
//LogUtils.d(TAG, "LogUtils init");
|
||||
|
||||
// 设置应用异常处理窗口
|
||||
CrashHandler.init(this);
|
||||
|
||||
// 设置应用调试状态
|
||||
//SharedPreferences sharedPreferences = getSharedPreferences(PREFS, Context.MODE_PRIVATE);
|
||||
//GlobalApplication.isDebuging = sharedPreferences.getBoolean(PREFS_ISDEBUGING, GlobalApplication.isDebuging);
|
||||
|
||||
// 初始化 Toast 框架
|
||||
ToastUtils.init(this);
|
||||
// 设置 Toast 布局样式
|
||||
//ToastUtils.setView(R.layout.toast_custom_view);
|
||||
ToastUtils.setStyle(new WhiteToastStyle());
|
||||
ToastUtils.setGravity(Gravity.BOTTOM, 0, 200);
|
||||
}
|
||||
|
||||
public static String getAppName(Context context) {
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
try {
|
||||
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(
|
||||
context.getPackageName(), 0);
|
||||
return (String) packageManager.getApplicationLabel(applicationInfo);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,119 @@
|
||||
package cc.winboll.studio.libappbase;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/11 00:14:05
|
||||
*/
|
||||
import android.app.Activity;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import cc.winboll.studio.libappbase.R;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public final class GlobalCrashActivity extends AppCompatActivity implements MenuItem.OnMenuItemClickListener {
|
||||
|
||||
private static final int MENUITEM_COPY = 0;
|
||||
private static final int MENUITEM_RESTART = 1;
|
||||
|
||||
GlobalCrashReportView mGlobalCrashReportView;
|
||||
String mLog;
|
||||
|
||||
|
||||
public static final String TAG = "GlobalCrashActivity";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
CrashHandler.AppCrashSafetyWire.getInstance().postResumeCrashSafetyWireHandler(getApplicationContext());
|
||||
|
||||
mLog = getIntent().getStringExtra(CrashHandler.EXTRA_CRASH_INFO);
|
||||
//setTheme(android.R.style.Theme_Holo_Light_NoActionBar);
|
||||
//setTheme(R.style.APPBaseTheme);
|
||||
setContentView(R.layout.activity_globalcrash);
|
||||
mGlobalCrashReportView = findViewById(R.id.activityglobalcrashGlobalCrashReportView1);
|
||||
mGlobalCrashReportView.setReport(mLog);
|
||||
setSupportActionBar(mGlobalCrashReportView.getToolbar());
|
||||
|
||||
getSupportActionBar().setTitle(CrashHandler.TITTLE);
|
||||
getSupportActionBar().setSubtitle(GlobalApplication.getAppName(getApplicationContext()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
restart();
|
||||
}
|
||||
|
||||
private void restart() {
|
||||
PackageManager pm = getPackageManager();
|
||||
Intent intent = pm.getLaunchIntentForPackage(getPackageName());
|
||||
if (intent != null) {
|
||||
intent.addFlags(
|
||||
Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
);
|
||||
startActivity(intent);
|
||||
}
|
||||
finish();
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case MENUITEM_COPY:
|
||||
ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cm.setPrimaryClip(ClipData.newPlainText(getPackageName(), mLog));
|
||||
Toast.makeText(getApplication(), "The text is copied.", Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
case MENUITEM_RESTART:
|
||||
CrashHandler.AppCrashSafetyWire.getInstance().resumeToMaximumImmediately();
|
||||
restart();
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
menu.add(0, MENUITEM_COPY, 0, "Copy").setOnMenuItemClickListener(this)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
menu.add(0, MENUITEM_RESTART, 0, "Restart").setOnMenuItemClickListener(this)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
|
||||
// 更新菜单文字风格
|
||||
mGlobalCrashReportView.updateMenuStyle();
|
||||
return true;
|
||||
}
|
||||
|
||||
void joinQQGroup(String key) {
|
||||
// 创建Intent
|
||||
Intent intent = new Intent();
|
||||
// 设置动作
|
||||
intent.setAction("android.intent.action.VIEW");
|
||||
// 设置数据为网址的URI
|
||||
Uri content_url = Uri.parse("https://www.winboll.cc");
|
||||
intent.setData(content_url);
|
||||
// 添加标志
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
// 设置类名和活动名
|
||||
intent.setClassName("com.android.browser", "com.android.browser.BrowserActivity");
|
||||
// 启动Activity
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
@@ -0,0 +1,138 @@
|
||||
package cc.winboll.studio.libappbase;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/11 20:18:30
|
||||
* @Describe 应用崩溃报告视图
|
||||
*/
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import cc.winboll.studio.libappbase.R;
|
||||
|
||||
public class GlobalCrashReportView extends LinearLayout {
|
||||
|
||||
public static final String TAG = "GlobalCrashReportView";
|
||||
|
||||
Context mContext;
|
||||
Toolbar mToolbar;
|
||||
int colorTittle;
|
||||
int colorTittleBackground;
|
||||
int colorText;
|
||||
int colorTextBackground;
|
||||
TextView mtvReport;
|
||||
|
||||
public GlobalCrashReportView(Context context) {
|
||||
super(context);
|
||||
mContext = context;
|
||||
//initView();
|
||||
}
|
||||
|
||||
public GlobalCrashReportView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mContext = context;
|
||||
initView(attrs);
|
||||
}
|
||||
|
||||
public GlobalCrashReportView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mContext = context;
|
||||
//initView();
|
||||
}
|
||||
|
||||
public GlobalCrashReportView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
mContext = context;
|
||||
//initView();
|
||||
}
|
||||
|
||||
public void setColorTittle(int colorTittle) {
|
||||
this.colorTittle = colorTittle;
|
||||
}
|
||||
|
||||
public int getColorTittle() {
|
||||
return colorTittle;
|
||||
}
|
||||
|
||||
public void setColorTittleBackground(int colorTittleBackground) {
|
||||
this.colorTittleBackground = colorTittleBackground;
|
||||
}
|
||||
|
||||
public int getColorTittleBackground() {
|
||||
return colorTittleBackground;
|
||||
}
|
||||
|
||||
public void setColorText(int colorText) {
|
||||
this.colorText = colorText;
|
||||
}
|
||||
|
||||
public int getColorText() {
|
||||
return colorText;
|
||||
}
|
||||
|
||||
public void setColorTextBackground(int colorTextBackground) {
|
||||
this.colorTextBackground = colorTextBackground;
|
||||
}
|
||||
|
||||
public int getColorTextBackground() {
|
||||
return colorTextBackground;
|
||||
}
|
||||
|
||||
void initView(AttributeSet attrs) {
|
||||
TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.GlobalCrashActivity, R.attr.themeGlobalCrashActivity, 0);
|
||||
this.colorTittle = a.getColor(R.styleable.GlobalCrashActivity_colorTittle, Color.WHITE);
|
||||
this.colorTittleBackground = a.getColor(R.styleable.GlobalCrashActivity_colorTittleBackgound, Color.BLACK);
|
||||
this.colorText = a.getColor(R.styleable.GlobalCrashActivity_colorText, Color.BLACK);
|
||||
this.colorTextBackground = a.getColor(R.styleable.GlobalCrashActivity_colorTextBackgound, Color.WHITE);
|
||||
// 返回一个绑定资源结束的信号给资源
|
||||
a.recycle();
|
||||
|
||||
/*this.colorTittle = Color.WHITE;
|
||||
this.colorTittleBackground = Color.BLACK;
|
||||
this.colorText = Color.BLACK;
|
||||
this.colorTextBackground = Color.WHITE;
|
||||
*/
|
||||
|
||||
inflate(mContext, R.layout.view_globalcrashreport, this);
|
||||
|
||||
LinearLayout llMain = findViewById(R.id.viewglobalcrashreportLinearLayout1);
|
||||
llMain.setBackgroundColor(this.colorTextBackground);
|
||||
mToolbar = findViewById(R.id.viewglobalcrashreportToolbar1);
|
||||
mToolbar.setBackgroundColor(this.colorTittleBackground);
|
||||
mToolbar.setTitleTextColor(this.colorTittle);
|
||||
mToolbar.setSubtitleTextColor(this.colorTittle);
|
||||
mtvReport = findViewById(R.id.viewglobalcrashreportTextView1);
|
||||
mtvReport.setTextColor(this.colorText);
|
||||
mtvReport.setBackgroundColor(this.colorTextBackground);
|
||||
}
|
||||
|
||||
public void setReport(String report) {
|
||||
mtvReport.setText(report);
|
||||
}
|
||||
|
||||
public Toolbar getToolbar() {
|
||||
return mToolbar;
|
||||
}
|
||||
|
||||
//
|
||||
// 更新菜单文字风格
|
||||
//
|
||||
public void updateMenuStyle() {
|
||||
// 设置菜单文本颜色
|
||||
Menu menu = mToolbar.getMenu();
|
||||
for (int i = 0; i < menu.size(); i++) {
|
||||
MenuItem item = menu.getItem(i);
|
||||
SpannableString spanString = new SpannableString(item.getTitle().toString());
|
||||
spanString.setSpan(new ForegroundColorSpan(this.colorTittle), 0, spanString.length(), 0);
|
||||
item.setTitle(spanString);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
package cc.winboll.studio.libappbase;
|
||||
|
||||
import android.app.*;
|
||||
import android.os.*;
|
||||
import cc.winboll.studio.R;
|
||||
|
||||
public class LibraryActivity extends Activity
|
||||
{
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.library);
|
||||
}
|
||||
}
|
@@ -0,0 +1,370 @@
|
||||
package cc.winboll.studio.libappbase;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@QQ.COM
|
||||
* @Date 2024/08/12 13:44:06
|
||||
* @Describe LogUtils
|
||||
* @Describe 应用日志类
|
||||
*/
|
||||
import android.content.Context;
|
||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
||||
import dalvik.system.DexFile;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class LogUtils {
|
||||
|
||||
public static final String TAG = "LogUtils";
|
||||
|
||||
public static enum LOG_LEVEL { Off, Error, Warn, Info, Debug, Verbose }
|
||||
|
||||
static volatile boolean _IsInited = false;
|
||||
static Context _mContext;
|
||||
// 日志显示时间格式
|
||||
static SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("[yyyyMMdd_HHmmSS]", Locale.getDefault());
|
||||
// 应用日志文件夹
|
||||
static File _mfLogCacheDir;
|
||||
static File _mfLogDataDir;
|
||||
// 应用日志文件
|
||||
static File _mfLogCatchFile;
|
||||
static File _mfLogUtilsBeanFile;
|
||||
static LogUtilsBean _mLogUtilsBean;
|
||||
public static Map<String, Boolean> mapTAGList = new HashMap<String, Boolean>();
|
||||
|
||||
//
|
||||
// 初始化函数
|
||||
//
|
||||
public static void init(Context context) {
|
||||
_mContext = context;
|
||||
init(context, LOG_LEVEL.Off);
|
||||
}
|
||||
|
||||
//
|
||||
// 初始化函数
|
||||
//
|
||||
public static void init(Context context, LOG_LEVEL logLevel) {
|
||||
if (GlobalApplication.isDebuging()) {
|
||||
// 初始化日志缓存文件路径
|
||||
_mfLogCacheDir = new File(context.getApplicationContext().getExternalCacheDir(), TAG);
|
||||
if (!_mfLogCacheDir.exists()) {
|
||||
_mfLogCacheDir.mkdirs();
|
||||
}
|
||||
_mfLogCatchFile = new File(_mfLogCacheDir, "log.txt");
|
||||
|
||||
// 初始化日志配置文件路径
|
||||
_mfLogDataDir = context.getApplicationContext().getExternalFilesDir(TAG);
|
||||
if (!_mfLogDataDir.exists()) {
|
||||
_mfLogDataDir.mkdirs();
|
||||
}
|
||||
_mfLogUtilsBeanFile = new File(_mfLogDataDir, TAG + ".json");
|
||||
} else {
|
||||
// 初始化日志缓存文件路径
|
||||
_mfLogCacheDir = new File(context.getApplicationContext().getCacheDir(), TAG);
|
||||
if (!_mfLogCacheDir.exists()) {
|
||||
_mfLogCacheDir.mkdirs();
|
||||
}
|
||||
_mfLogCatchFile = new File(_mfLogCacheDir, "log.txt");
|
||||
|
||||
// 初始化日志配置文件路径
|
||||
_mfLogDataDir = new File(context.getApplicationContext().getFilesDir(), TAG);
|
||||
if (!_mfLogDataDir.exists()) {
|
||||
_mfLogDataDir.mkdirs();
|
||||
}
|
||||
_mfLogUtilsBeanFile = new File(_mfLogDataDir, TAG + ".json");
|
||||
}
|
||||
|
||||
// Toast.makeText(context,
|
||||
// "_mfLogUtilsBeanFile : " + _mfLogUtilsBeanFile
|
||||
// + "\n_mfLogCatchFile : " + _mfLogCatchFile,
|
||||
// Toast.LENGTH_SHORT).show();
|
||||
//
|
||||
_mLogUtilsBean = LogUtilsBean.loadBeanFromFile(_mfLogUtilsBeanFile.getPath(), LogUtilsBean.class);
|
||||
if (_mLogUtilsBean == null) {
|
||||
_mLogUtilsBean = new LogUtilsBean();
|
||||
_mLogUtilsBean.saveBeanToFile(_mfLogUtilsBeanFile.getPath(), _mLogUtilsBean);
|
||||
}
|
||||
|
||||
// 加载当前应用下的所有类的 TAG
|
||||
addClassTAGList();
|
||||
loadTAGBeanSettings();
|
||||
_IsInited = true;
|
||||
LogUtils.d(TAG, String.format("mapTAGList : %s", mapTAGList.toString()));
|
||||
}
|
||||
|
||||
public static Map<String, Boolean> getMapTAGList() {
|
||||
return mapTAGList;
|
||||
}
|
||||
|
||||
static void loadTAGBeanSettings() {
|
||||
ArrayList<LogUtilsClassTAGBean> list = new ArrayList<LogUtilsClassTAGBean>();
|
||||
LogUtilsClassTAGBean.loadBeanList(_mContext, list, LogUtilsClassTAGBean.class);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
LogUtilsClassTAGBean beanSetting = list.get(i);
|
||||
for (Map.Entry<String, Boolean> entry : mapTAGList.entrySet()) {
|
||||
if (entry.getKey().equals(beanSetting.getTag())) {
|
||||
entry.setValue(beanSetting.getEnable());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void saveTAGBeanSettings() {
|
||||
ArrayList<LogUtilsClassTAGBean> list = new ArrayList<LogUtilsClassTAGBean>();
|
||||
for (Map.Entry<String, Boolean> entry : mapTAGList.entrySet()) {
|
||||
list.add(new LogUtilsClassTAGBean(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
LogUtilsClassTAGBean.saveBeanList(_mContext, list, LogUtilsClassTAGBean.class);
|
||||
}
|
||||
|
||||
static void addClassTAGList() {
|
||||
//ClassLoader classLoader = getClass().getClassLoader();
|
||||
try {
|
||||
//String packageName = context.getPackageName();
|
||||
String packageNamePrefix = "cc.winboll.studio";
|
||||
List<String> classNames = new ArrayList<>();
|
||||
String apkPath = _mContext.getPackageCodePath();
|
||||
//Log.d("APK_PATH", "The APK path is: " + apkPath);
|
||||
LogUtils.d(TAG, String.format("apkPath : %s", apkPath));
|
||||
//String apkPath = "/data/app/" + packageName + "-";
|
||||
|
||||
//DexFile dexfile = new DexFile(apkPath + "1/base.apk");
|
||||
DexFile dexfile = new DexFile(apkPath);
|
||||
|
||||
int countTemp = 0;
|
||||
Enumeration<String> entries = dexfile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
countTemp++;
|
||||
String className = entries.nextElement();
|
||||
if (className.startsWith(packageNamePrefix)) {
|
||||
classNames.add(className);
|
||||
}
|
||||
}
|
||||
|
||||
LogUtils.d(TAG, String.format("countTemp : %d\nClassNames size : %d", countTemp, classNames.size()));
|
||||
|
||||
for (String className : classNames) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName(className);
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
if (Modifier.isStatic(field.getModifiers()) && Modifier.isPublic(field.getModifiers()) && field.getType() == String.class && "TAG".equals(field.getName())) {
|
||||
String tagValue = (String) field.get(null);
|
||||
//Log.d("TAG_INFO", "Class: " + className + ", TAG value: " + tagValue);
|
||||
//LogUtils.d(TAG, String.format("Tag Value : %s", tagValue));
|
||||
//mapTAGList.put(tagValue, true);
|
||||
mapTAGList.put(tagValue, false);
|
||||
}
|
||||
}
|
||||
} catch (NoClassDefFoundError | ClassNotFoundException | IllegalAccessException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
//LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
//Toast.makeText(context, TAG + " : " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
//Toast.makeText(context, TAG + " : " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setTAGListEnable(String tag, boolean isEnable) {
|
||||
Iterator<Map.Entry<String, Boolean>> iterator = mapTAGList.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, Boolean> entry = iterator.next();
|
||||
if (tag.equals(entry.getKey())) {
|
||||
entry.setValue(isEnable);
|
||||
//System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
saveTAGBeanSettings();
|
||||
LogUtils.d(TAG, String.format("mapTAGList : %s", mapTAGList.toString()));
|
||||
}
|
||||
|
||||
public static void setALlTAGListEnable(boolean isEnable) {
|
||||
Iterator<Map.Entry<String, Boolean>> iterator = mapTAGList.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, Boolean> entry = iterator.next();
|
||||
entry.setValue(isEnable);
|
||||
//System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
|
||||
}
|
||||
saveTAGBeanSettings();
|
||||
LogUtils.d(TAG, String.format("mapTAGList : %s", mapTAGList.toString()));
|
||||
}
|
||||
|
||||
public static void setLogLevel(LOG_LEVEL logLevel) {
|
||||
LogUtils._mLogUtilsBean.setLogLevel(logLevel);
|
||||
_mLogUtilsBean.saveBeanToFile(_mfLogUtilsBeanFile.getPath(), _mLogUtilsBean);
|
||||
}
|
||||
|
||||
public static LOG_LEVEL getLogLevel() {
|
||||
return LogUtils._mLogUtilsBean.getLogLevel();
|
||||
}
|
||||
|
||||
static boolean isLoggable(String tag, LOG_LEVEL logLevel) {
|
||||
return _IsInited && mapTAGList.get(tag) && isInTheLevel(logLevel);
|
||||
}
|
||||
|
||||
static boolean isInTheLevel(LOG_LEVEL logLevel) {
|
||||
return (LogUtils._mLogUtilsBean.getLogLevel().ordinal() == logLevel.ordinal()
|
||||
|| LogUtils._mLogUtilsBean.getLogLevel().ordinal() > logLevel.ordinal());
|
||||
}
|
||||
|
||||
//
|
||||
// 获取应用日志文件夹
|
||||
//
|
||||
public static File getLogCacheDir() {
|
||||
return _mfLogCacheDir;
|
||||
}
|
||||
|
||||
//
|
||||
// 调试日志写入函数
|
||||
//
|
||||
public static void e(String szTAG, String szMessage) {
|
||||
if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Error)) {
|
||||
saveLog(szTAG, LogUtils.LOG_LEVEL.Error, szMessage);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 调试日志写入函数
|
||||
//
|
||||
public static void w(String szTAG, String szMessage) {
|
||||
if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Warn)) {
|
||||
saveLog(szTAG, LogUtils.LOG_LEVEL.Warn, szMessage);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 调试日志写入函数
|
||||
//
|
||||
public static void i(String szTAG, String szMessage) {
|
||||
if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Info)) {
|
||||
saveLog(szTAG, LogUtils.LOG_LEVEL.Info, szMessage);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 调试日志写入函数
|
||||
//
|
||||
public static void d(String szTAG, String szMessage) {
|
||||
if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Debug)) {
|
||||
saveLog(szTAG, LogUtils.LOG_LEVEL.Debug, szMessage);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 调试日志写入函数
|
||||
// 包含线程调试堆栈信息
|
||||
//
|
||||
public static void d(String szTAG, String szMessage, StackTraceElement[] listStackTrace) {
|
||||
if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Debug)) {
|
||||
StringBuilder sbMessage = new StringBuilder(szMessage);
|
||||
sbMessage.append(" \nAt ");
|
||||
sbMessage.append(listStackTrace[2].getMethodName());
|
||||
sbMessage.append(" (");
|
||||
sbMessage.append(listStackTrace[2].getFileName());
|
||||
sbMessage.append(":");
|
||||
sbMessage.append(listStackTrace[2].getLineNumber());
|
||||
sbMessage.append(")");
|
||||
saveLog(szTAG, LogUtils.LOG_LEVEL.Debug, sbMessage.toString());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 调试日志写入函数
|
||||
// 包含异常信息和线程调试堆栈信息
|
||||
//
|
||||
public static void d(String szTAG, Exception e, StackTraceElement[] listStackTrace) {
|
||||
if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Debug)) {
|
||||
StringBuilder sbMessage = new StringBuilder(e.getClass().toGenericString());
|
||||
sbMessage.append(" : ");
|
||||
sbMessage.append(e.getMessage());
|
||||
sbMessage.append(" \nAt ");
|
||||
sbMessage.append(listStackTrace[2].getMethodName());
|
||||
sbMessage.append(" (");
|
||||
sbMessage.append(listStackTrace[2].getFileName());
|
||||
sbMessage.append(":");
|
||||
sbMessage.append(listStackTrace[2].getLineNumber());
|
||||
sbMessage.append(")");
|
||||
saveLog(szTAG, LogUtils.LOG_LEVEL.Debug, sbMessage.toString());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 调试日志写入函数
|
||||
//
|
||||
public static void v(String szTAG, String szMessage) {
|
||||
if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Verbose)) {
|
||||
saveLog(szTAG, LogUtils.LOG_LEVEL.Verbose, szMessage);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 日志文件保存函数
|
||||
//
|
||||
static void saveLog(String szTAG, LogUtils.LOG_LEVEL logLevel, String szMessage) {
|
||||
try {
|
||||
BufferedWriter out = null;
|
||||
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(_mfLogCatchFile, true), "UTF-8"));
|
||||
out.write("[" + logLevel + "] " + mSimpleDateFormat.format(System.currentTimeMillis()) + " [" + szTAG + "]\n" + szMessage + "\n");
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, "IOException : " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 历史日志加载函数
|
||||
//
|
||||
public static String loadLog() {
|
||||
if (_mfLogCatchFile.exists()) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
try {
|
||||
BufferedReader in = null;
|
||||
in = new BufferedReader(new InputStreamReader(new FileInputStream(_mfLogCatchFile), "UTF-8"));
|
||||
String line = "";
|
||||
while ((line = in.readLine()) != null) {
|
||||
sb.append(line);
|
||||
sb.append("\n");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, "IOException : " + e.getMessage());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//
|
||||
// 清理日志函数
|
||||
//
|
||||
public static void cleanLog() {
|
||||
if (_mfLogCatchFile.exists()) {
|
||||
try {
|
||||
UTF8FileUtils.writeStringToFile(_mfLogCatchFile.getPath(), "");
|
||||
//LogUtils.d(TAG, "cleanLog");
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
package cc.winboll.studio.libappbase;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@QQ.COM
|
||||
* @Date 2024/08/23 15:39:07
|
||||
* @Describe LogUtils 数据配置类。
|
||||
*/
|
||||
import android.util.JsonReader;
|
||||
import android.util.JsonWriter;
|
||||
import java.io.IOException;
|
||||
public class LogUtilsBean extends BaseBean {
|
||||
|
||||
public static final String TAG = "LogUtilsBean";
|
||||
|
||||
LogUtils.LOG_LEVEL logLevel;
|
||||
|
||||
public LogUtilsBean() {
|
||||
this.logLevel = LogUtils.LOG_LEVEL.Off;
|
||||
}
|
||||
|
||||
public LogUtilsBean(LogUtils.LOG_LEVEL logLevel) {
|
||||
this.logLevel = logLevel;
|
||||
}
|
||||
|
||||
public void setLogLevel(LogUtils.LOG_LEVEL logLevel) {
|
||||
this.logLevel = logLevel;
|
||||
}
|
||||
|
||||
public LogUtils.LOG_LEVEL getLogLevel() {
|
||||
return logLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return LogUtilsBean.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
|
||||
super.writeThisToJsonWriter(jsonWriter);
|
||||
LogUtilsBean bean = this;
|
||||
jsonWriter.name("logLevel").value(bean.getLogLevel().ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
|
||||
if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
|
||||
if (name.equals("logLevel")) {
|
||||
setLogLevel(LogUtils.LOG_LEVEL.values()[jsonReader.nextInt()]);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException {
|
||||
jsonReader.beginObject();
|
||||
while (jsonReader.hasNext()) {
|
||||
String name = jsonReader.nextName();
|
||||
if (!initObjectsFromJsonReader(jsonReader, name)) {
|
||||
jsonReader.skipValue();
|
||||
}
|
||||
}
|
||||
// 结束 JSON 对象
|
||||
jsonReader.endObject();
|
||||
return this;
|
||||
}
|
||||
}
|
@@ -0,0 +1,87 @@
|
||||
package cc.winboll.studio.libappbase;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@QQ.COM
|
||||
* @Date 2025/01/04 14:17:02
|
||||
* @Describe 日志类class TAG 标签数据类
|
||||
*/
|
||||
import android.util.JsonReader;
|
||||
import android.util.JsonWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LogUtilsClassTAGBean extends BaseBean {
|
||||
|
||||
public static final String TAG = "LogUtilsClassTAGBean";
|
||||
|
||||
// 标签名
|
||||
String tag;
|
||||
// 是否启用
|
||||
Boolean enable;
|
||||
|
||||
public LogUtilsClassTAGBean() {
|
||||
this.tag = TAG;
|
||||
this.enable = true;
|
||||
}
|
||||
|
||||
public LogUtilsClassTAGBean(String tag, Boolean enable) {
|
||||
this.tag = tag;
|
||||
this.enable = enable;
|
||||
}
|
||||
|
||||
public void setTag(String tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void setEnable(Boolean enable) {
|
||||
this.enable = enable;
|
||||
}
|
||||
|
||||
public Boolean getEnable() {
|
||||
return enable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return LogUtilsClassTAGBean.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
|
||||
super.writeThisToJsonWriter(jsonWriter);
|
||||
LogUtilsClassTAGBean bean = this;
|
||||
jsonWriter.name("tag").value(bean.getTag());
|
||||
jsonWriter.name("enable").value(bean.getEnable());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
|
||||
if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
|
||||
if (name.equals("tag")) {
|
||||
setTag(jsonReader.nextString());
|
||||
} else if (name.equals("enable")) {
|
||||
setEnable(jsonReader.nextBoolean());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException {
|
||||
jsonReader.beginObject();
|
||||
while (jsonReader.hasNext()) {
|
||||
String name = jsonReader.nextName();
|
||||
if (!initObjectsFromJsonReader(jsonReader, name)) {
|
||||
jsonReader.skipValue();
|
||||
}
|
||||
}
|
||||
// 结束 JSON 对象
|
||||
jsonReader.endObject();
|
||||
return this;
|
||||
}
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package cc.winboll.studio.libappbase;
|
||||
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/12 11:12:25
|
||||
* @Describe 简单信号服务中心
|
||||
*/
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
|
||||
public class SimpleOperateSignalCenterService extends Service {
|
||||
|
||||
public static final String TAG = "SimpleOperateSignalCenterService";
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
package cc.winboll.studio.libappbase;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@QQ.COM
|
||||
* @Date 2024/07/19 14:30:57
|
||||
* @Describe UTF-8编码文件工具类
|
||||
*/
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class UTF8FileUtils {
|
||||
|
||||
public static final String TAG = "FileUtils";
|
||||
|
||||
//
|
||||
// 把字符串写入文件,指定 UTF-8 编码
|
||||
//
|
||||
public static void writeStringToFile(String szFilePath, String szContent) throws IOException {
|
||||
File file = new File(szFilePath);
|
||||
if (!file.getParentFile().exists()) {
|
||||
file.getParentFile().mkdirs();
|
||||
}
|
||||
FileOutputStream outputStream = new FileOutputStream(file);
|
||||
OutputStreamWriter writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
|
||||
writer.write(szContent);
|
||||
writer.close();
|
||||
}
|
||||
|
||||
//
|
||||
// 读取文件到字符串,指定 UTF-8 编码
|
||||
//
|
||||
public static String readStringFromFile(String szFilePath) throws IOException {
|
||||
File file = new File(szFilePath);
|
||||
FileInputStream inputStream = new FileInputStream(file);
|
||||
InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
|
||||
StringBuilder content = new StringBuilder();
|
||||
int character;
|
||||
while ((character = reader.read()) != -1) {
|
||||
content.append((char) character);
|
||||
}
|
||||
reader.close();
|
||||
return content.toString();
|
||||
}
|
||||
}
|
15
libappbase/src/main/res/layout/activity_globalcrash.xml
Normal file
15
libappbase/src/main/res/layout/activity_globalcrash.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?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">
|
||||
|
||||
<cc.winboll.studio.libappbase.GlobalCrashReportView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/activityglobalcrashGlobalCrashReportView1"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
@@ -1,11 +0,0 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:text="@string/hello_world"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
35
libappbase/src/main/res/layout/view_globalcrashreport.xml
Normal file
35
libappbase/src/main/res/layout/view_globalcrashreport.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?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"
|
||||
android:id="@+id/viewglobalcrashreportLinearLayout1">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/viewglobalcrashreportToolbar1"/>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1.0">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#FFFFFFFF"
|
||||
android:id="@+id/viewglobalcrashreportTextView1"/>
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
|
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="AppTheme" parent="@android:style/Theme.Material.Light">
|
||||
</style>
|
||||
</resources>
|
13
libappbase/src/main/res/values/attrs.xml
Normal file
13
libappbase/src/main/res/values/attrs.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<attr name="themeGlobalCrashActivity" format="reference"/>
|
||||
|
||||
<declare-styleable name="GlobalCrashActivity">
|
||||
<attr name="colorTittle" format="color" />
|
||||
<attr name="colorTittleBackgound" format="color" />
|
||||
<attr name="colorText" format="color" />
|
||||
<attr name="colorTextBackgound" format="color" />
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
7
libappbase/src/main/res/values/colors.xml
Normal file
7
libappbase/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#FFFFE200</color>
|
||||
<color name="colorPrimaryDark">#FFFFE200</color>
|
||||
<color name="colorAccent">#FFFFE200</color>
|
||||
<color name="colorText">#FFFFE200</color>
|
||||
</resources>
|
@@ -1,5 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="AppTheme" parent="@android:style/Theme.Holo.Light">
|
||||
|
||||
<style name="APPBaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="themeGlobalCrashActivity">@style/GlobalCrashActivityTheme</item>
|
||||
</style>
|
||||
|
||||
<style name="GlobalCrashActivityTheme" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar">
|
||||
<item name="colorTittle">#FFFFF600</item>
|
||||
<item name="colorTittleBackgound">#FF00B322</item>
|
||||
<item name="colorText">#FF00B322</item>
|
||||
<item name="colorTextBackgound">#FF000000</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
</resources>
|
||||
|
@@ -38,7 +38,7 @@ dependencies {
|
||||
api 'androidx.fragment:fragment:1.0.0'
|
||||
api 'com.google.android.material:material:1.0.0'
|
||||
|
||||
api 'cc.winboll.studio:libappbase:1.1.3'
|
||||
api 'cc.winboll.studio:libappbase:1.0.3'
|
||||
|
||||
api fileTree(dir: 'libs', include: ['*.jar'])
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Tue Feb 04 08:54:03 HKT 2025
|
||||
stageCount=1
|
||||
#Sat Jan 18 13:02:39 HKT 2025
|
||||
stageCount=2
|
||||
libraryProject=libapputils
|
||||
baseVersion=9.3
|
||||
publishVersion=9.3.0
|
||||
baseVersion=9.2
|
||||
publishVersion=9.2.1
|
||||
buildCount=0
|
||||
baseBetaVersion=9.3.1
|
||||
baseBetaVersion=9.2.2
|
||||
|
@@ -18,9 +18,6 @@
|
||||
<!-- 拍摄照片和视频 -->
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
|
||||
<!-- 拥有完全的网络访问权限 -->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<application android:networkSecurityConfig="@xml/network_security_config">
|
||||
|
||||
<activity
|
||||
@@ -48,4 +45,4 @@
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
</manifest>
|
@@ -1,31 +1,25 @@
|
||||
package cc.winboll.studio.libapputils.activities;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@QQ.COM
|
||||
* @Date 2024/07/14 13:20:33
|
||||
* @Describe 应用介绍页
|
||||
*/
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.LinearLayout;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import cc.winboll.studio.libapputils.app.WinBollActivity;
|
||||
import cc.winboll.studio.libapputils.app.WinBollActivityManager;
|
||||
import cc.winboll.studio.libapputils.bean.APPInfo;
|
||||
import cc.winboll.studio.libapputils.view.AboutView;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import cc.winboll.studio.libapputils.log.LogUtils;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@QQ.COM
|
||||
* @Date 2024/07/14 13:20:33
|
||||
* @Describe AboutFragment Test
|
||||
*/
|
||||
final public class AboutActivity extends WinBollActivity {
|
||||
|
||||
public static final String TAG = "AboutActivity";
|
||||
public static final String EXTRA_APPINFO = "EXTRA_APPINFO";
|
||||
|
||||
|
||||
APPInfo mAPPInfo;
|
||||
|
||||
@Override
|
||||
public String getTag() {
|
||||
return TAG;
|
||||
@@ -40,19 +34,21 @@ final public class AboutActivity extends WinBollActivity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_about);
|
||||
Intent intent = getIntent();
|
||||
if (intent != null) {
|
||||
mAPPInfo = (APPInfo)intent.getSerializableExtra(EXTRA_APPINFO);
|
||||
}
|
||||
if (mAPPInfo == null) {
|
||||
mAPPInfo = new APPInfo();
|
||||
}
|
||||
|
||||
AboutView aboutView = new AboutView(this, mAPPInfo);
|
||||
LinearLayout llMain = findViewById(R.id.activityaboutLinearLayout1);
|
||||
llMain.addView(aboutView);
|
||||
|
||||
ToastUtils.show(TAG);
|
||||
|
||||
/*AboutView aboutView = findViewById(R.id.activityaboutAboutView1);
|
||||
aboutView.setOnRequestDevUserInfoAutofillListener(new AboutView.OnRequestDevUserInfoAutofillListener(){
|
||||
|
||||
@Override
|
||||
public void requestAutofill(EditText etDevUserName, EditText etDevUserPassword) {
|
||||
AutofillManager autofillManager = (AutofillManager) getSystemService(AutofillManager.class);
|
||||
if (autofillManager!= null) {
|
||||
//ToastUtils.show("0");
|
||||
autofillManager.requestAutofill(findViewById(R.id.usernameEditText));
|
||||
autofillManager.requestAutofill(findViewById(R.id.passwordEditText));
|
||||
}
|
||||
}
|
||||
});*/
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -83,8 +79,9 @@ final public class AboutActivity extends WinBollActivity {
|
||||
if (item.getItemId() == R.id.item_help) {
|
||||
WinBollActivityManager.getInstance(this).startWinBollActivity(this, AssetsHtmlActivity.class);
|
||||
}
|
||||
// else if (item.getItemId() == android.R.id.home) {
|
||||
// WinBollActivityManager.getInstance(this).finish(this);
|
||||
// }
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -81,7 +81,7 @@ public class AssetsHtmlActivity extends WinBollActivity {
|
||||
if (szTemp != null && !szTemp.trim().equals("")) {
|
||||
mszHtmlFileName = szTemp.trim();
|
||||
}
|
||||
//ToastUtils.show(mszHtmlFileName);
|
||||
ToastUtils.show(mszHtmlFileName);
|
||||
}
|
||||
|
||||
// 与其他应用分享 html 帮助
|
||||
|
@@ -5,7 +5,7 @@ package cc.winboll.studio.libapputils.app;
|
||||
* @Date 2024/08/12 14:45:35
|
||||
* @Describe 应用版本工具集
|
||||
*/
|
||||
import cc.winboll.studio.libapputils.log.LogUtils;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -23,7 +23,6 @@ public class AppVersionUtils {
|
||||
// true 新版本 == 当前版本
|
||||
//
|
||||
public static boolean isHasNewVersion2(String szCurrentName, String szNextName) {
|
||||
LogUtils.d(TAG, String.format("isHasNewVersion2\nszCurrentName : %s\nszNextName : %s", szCurrentName, szNextName));
|
||||
//szCurrentName = "AES_6.2.0-beta0_3234.apk";
|
||||
//szNextName = "AES_6.1.12.apk";
|
||||
//szCurrentName = "AES_6.2.0-beta0_3234.apk";
|
||||
@@ -78,9 +77,8 @@ public class AppVersionUtils {
|
||||
//LogUtils.d(TAG, "App version is the newest. ");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isHasNewStageReleaseVersion(String szCurrentName, String szNextName) {
|
||||
LogUtils.d(TAG, String.format("isHasNewStageReleaseVersion\nszCurrentName : %s\nszNextName : %s", szCurrentName, szNextName));
|
||||
//szCurrentName = "AES_6.2.12.apk";
|
||||
//szNextName = "AES_6.3.12.apk";
|
||||
if (checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName))) {
|
||||
@@ -98,10 +96,6 @@ public class AppVersionUtils {
|
||||
// 返回 :true 新版本 > 当前版本
|
||||
//
|
||||
public static Boolean checkNewVersion(String szCurrentCode, String szNextCode) {
|
||||
if (szCurrentCode == null || szCurrentCode.equals("") || szNextCode == null || szNextCode.equals("")) {
|
||||
LogUtils.d(TAG, String.format("checkNewVersion unexpected parameters:\nszCurrentCode : %s\nszNextCode : %s", szCurrentCode, szNextCode));
|
||||
return false;
|
||||
}
|
||||
boolean isNew = false;
|
||||
String[] appVersionCurrent = szCurrentCode.split("\\.");
|
||||
String[] appVersionNext = szNextCode.split("\\.");
|
||||
@@ -112,7 +106,7 @@ public class AppVersionUtils {
|
||||
if (Integer.parseInt(appVersionNext[i]) > Integer.parseInt(appVersionCurrent[i])) {
|
||||
isNew = true;
|
||||
return isNew;
|
||||
} else if (Integer.parseInt(appVersionNext[i]) == Integer.parseInt(appVersionCurrent[i])) {
|
||||
} else if(Integer.parseInt(appVersionNext[i]) == Integer.parseInt(appVersionCurrent[i])) {
|
||||
continue ;
|
||||
} else {
|
||||
isNew = false;
|
||||
@@ -128,17 +122,14 @@ public class AppVersionUtils {
|
||||
// 如 :AppUtils_7.0.4.apk 版本号为 7.0.4
|
||||
//
|
||||
public static String getCodeInPackageName(String apkName) {
|
||||
LogUtils.d(TAG, String.format("getCodeInPackageName apkName : %s", apkName));
|
||||
//String apkName = "AppUtils_7.0.0.apk";
|
||||
Pattern pattern = Pattern.compile("\\d+\\.\\d+\\.\\d+");
|
||||
Matcher matcher = pattern.matcher(apkName);
|
||||
if (matcher.find()) {
|
||||
String version = matcher.group();
|
||||
LogUtils.d(TAG, String.format("version is %s", version));
|
||||
return version;
|
||||
//System.out.println("Version number: " + version); // 输出:7.0.0
|
||||
}
|
||||
LogUtils.d(TAG, String.format("No result."));
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -158,4 +149,5 @@ public class AppVersionUtils {
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -6,20 +6,22 @@ package cc.winboll.studio.libapputils.app;
|
||||
*/
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import cc.winboll.studio.libapputils.log.LogUtils;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import android.content.Context;
|
||||
import java.util.Set;
|
||||
|
||||
public class MyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
|
||||
|
||||
public static final String TAG = "MyActivityLifecycleCallbacks";
|
||||
|
||||
|
||||
public String mInfo = "";
|
||||
|
||||
public MyActivityLifecycleCallbacks() {
|
||||
public MyActivityLifecycleCallbacks(WinBollApplication application) {
|
||||
|
||||
}
|
||||
|
||||
void createActivityeInfo(Activity activity) {
|
||||
|
@@ -64,7 +64,7 @@ abstract public class WinBollActivity extends AppCompatActivity {
|
||||
// 传入的Intent action在Activity清单的intent-filter的action节点里有定义
|
||||
if (intent.getAction() != null) {
|
||||
if (intent.getAction().equals(cc.winboll.studio.libapputils.intent.action.DEBUGVIEW)) {
|
||||
WinBollGlobalApplication.setIsDebug(true);
|
||||
WinBollApplication.setIsDebug(true);
|
||||
//ToastUtils.show!("WinBollApplication.setIsDebug(true) by action : " + intent.getAction());
|
||||
|
||||
}
|
||||
@@ -356,7 +356,7 @@ abstract public class WinBollActivity extends AppCompatActivity {
|
||||
if (isAddWinBollToolBar()) {
|
||||
getMenuInflater().inflate(R.menu.toolbar_winboll_shared_main, menu);
|
||||
}
|
||||
if (WinBollGlobalApplication.isDebug()) {
|
||||
if (WinBollApplication.isDebug()) {
|
||||
getMenuInflater().inflate(R.menu.toolbar_studio_debug, menu);
|
||||
}
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
@@ -365,26 +365,15 @@ abstract public class WinBollActivity extends AppCompatActivity {
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
LogUtils.d(TAG, "onOptionsItemSelected");
|
||||
if (item.getItemId() == R.id.item_testcrashreport) {
|
||||
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
|
||||
getString(i);
|
||||
}
|
||||
} else if (item.getItemId() == R.id.item_log) {
|
||||
// LogUtils.d(TAG, "item_log not yet.");
|
||||
// Intent intent = new Intent(this, LogActivity.class);
|
||||
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
|
||||
// intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
|
||||
// startActivity(intent);
|
||||
|
||||
if (item.getItemId() == R.id.item_log) {
|
||||
LogUtils.d(TAG, "item_log not yet.");
|
||||
//WinBollActivityManager.getInstance().printAvtivityListInfo();
|
||||
WinBollActivityManager.getInstance(this).startWinBollActivity(this, LogActivity.class);
|
||||
//WinBollActivityManager.getInstance(this).startWinBollActivity(this, LogActivity.class);
|
||||
} else if (item.getItemId() == R.id.item_exit) {
|
||||
//ToastUtils.show("item_exit");
|
||||
WinBollActivityManager.getInstance(this).finishAll();
|
||||
} else if (item.getItemId() == R.id.item_info) {
|
||||
LogUtils.d(TAG, "item_info not yet.");
|
||||
//WinBollApplication application = (WinBollApplication) getApplication();
|
||||
//application.getMyActivityLifecycleCallbacks().showActivityeInfo();
|
||||
WinBollApplication application = (WinBollApplication) getApplication();
|
||||
application.getMyActivityLifecycleCallbacks().showActivityeInfo();
|
||||
} else if (item.getItemId() == R.id.item_exitdebug) {
|
||||
AboutView.setApp2NormalMode(getApplicationContext());
|
||||
} else if (item.getItemId() == R.id.item_about) {
|
||||
|
@@ -20,16 +20,17 @@ import java.util.Map;
|
||||
public class WinBollActivityManager {
|
||||
|
||||
public static final String TAG = "WinBollActivityManager";
|
||||
public static final String EXTRA_TAG = "EXTRA_TAG";
|
||||
|
||||
Context mContext;
|
||||
static WinBollActivityManager _mWinBollActivityManager;
|
||||
static Map<String, WinBollActivity> _mapActivityList;
|
||||
//static ArrayList<WinBollActivity> _mWinBollActivityList;
|
||||
|
||||
public WinBollActivityManager(Context context) {
|
||||
mContext = context;
|
||||
LogUtils.d(TAG, "WinBollActivityManager()");
|
||||
_mapActivityList = new HashMap<String, WinBollActivity>();
|
||||
//_mWinBollActivityList = new ArrayList<WinBollActivity>();
|
||||
}
|
||||
|
||||
public static synchronized WinBollActivityManager getInstance(Context context) {
|
||||
@@ -41,10 +42,19 @@ public class WinBollActivityManager {
|
||||
return _mWinBollActivityManager;
|
||||
}
|
||||
|
||||
//
|
||||
// 把Activity添加到管理中
|
||||
//
|
||||
/**
|
||||
* 把Activity添加到管理中
|
||||
*/
|
||||
public <T extends WinBollActivity> void add(T activity) {
|
||||
/*for (int i = 0; i < _mWinBollActivityList.size(); i++) {
|
||||
LogUtils.d(TAG, String.format("add for i %d\nget(i).getTag() %s", i, _mWinBollActivityList.get(i).getTag()));
|
||||
if (_mWinBollActivityList.get(i).getTag().equals(activity.getTag())) {
|
||||
_mWinBollActivityList.add(i, activity);
|
||||
_mWinBollActivityList.remove(i);
|
||||
LogUtils.d(TAG, String.format("Replace activity : %s\nSize %d", activity.getTag(), _mWinBollActivityList.size()));
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
if (isActive(activity.getTag())) {
|
||||
LogUtils.d(TAG, String.format("add(...) %s is active.", activity.getTag()));
|
||||
} else {
|
||||
@@ -56,7 +66,7 @@ public class WinBollActivityManager {
|
||||
|
||||
//
|
||||
// activity: 为 null 时,
|
||||
// intent.putExtra 函数 EXTRA_TAG 参数为 tag
|
||||
// intent.putExtra 函数 "tag" 参数为 tag
|
||||
// activity: 不为 null 时,
|
||||
// intent.putExtra 函数 "tag" 参数为 activity.getTag()
|
||||
//
|
||||
@@ -74,7 +84,7 @@ public class WinBollActivityManager {
|
||||
//打开多任务窗口 flags
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
|
||||
intent.putExtra(EXTRA_TAG, tag);
|
||||
intent.putExtra("tag", tag);
|
||||
mContext.startActivity(intent);
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
@@ -95,18 +105,18 @@ public class WinBollActivityManager {
|
||||
//打开多任务窗口 flags
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
|
||||
intent.putExtra(EXTRA_TAG, tag);
|
||||
intent.putExtra("tag", tag);
|
||||
mContext.startActivity(intent);
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 判断 tag绑定的 MyActivity是否存在
|
||||
//
|
||||
/**
|
||||
* 判断 tag绑定的 MyActivity是否存在
|
||||
*/
|
||||
public boolean isActive(String tag) {
|
||||
//printAvtivityListInfo();
|
||||
printAvtivityListInfo();
|
||||
WinBollActivity activity = getWinBollActivity(tag);
|
||||
if (activity != null) {
|
||||
LogUtils.d(TAG, "isActive(...) activity != null tag " + tag);
|
||||
@@ -131,21 +141,21 @@ public class WinBollActivityManager {
|
||||
return _mapActivityList.get(tag);
|
||||
}
|
||||
|
||||
//
|
||||
// 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台
|
||||
//
|
||||
/**
|
||||
* 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台
|
||||
*/
|
||||
public <T extends WinBollActivity> void resumeActivity(Context context, String tag) {
|
||||
LogUtils.d(TAG, "resumeActivty");
|
||||
T activity = (T)getWinBollActivity(tag);
|
||||
//LogUtils.d(TAG, "activity " + activity.getTag());
|
||||
LogUtils.d(TAG, "activity " + activity.getTag());
|
||||
if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) {
|
||||
resumeActivity(context, activity);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台
|
||||
//
|
||||
/**
|
||||
* 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台
|
||||
*/
|
||||
public <T extends WinBollActivity> void resumeActivity(Context context, T activity) {
|
||||
ActivityManager am = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
//返回启动它的根任务(home 或者 MainActivity)
|
||||
@@ -160,39 +170,39 @@ public class WinBollActivityManager {
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 结束所有 Activity
|
||||
//
|
||||
/**
|
||||
* 结束所有 Activity
|
||||
*/
|
||||
public void finishAll() {
|
||||
try {
|
||||
for (String key : _mapActivityList.keySet()) {
|
||||
//System.out.println("Key: " + key + ", Value: " + _mapActivityList.get(key));
|
||||
WinBollActivity activity = _mapActivityList.get(key);
|
||||
//ToastUtils.show("finishAll() activity");
|
||||
if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) {
|
||||
//ToastUtils.show("activity != null ...");
|
||||
if (WinBollGlobalApplication.getWinBollUI_TYPE() == WinBollGlobalApplication.WinBollUI_TYPE.Service) {
|
||||
// 结束窗口和最近任务栏, 建议前台服务类应用使用,可以方便用户再次调用 UI 操作。
|
||||
activity.finishAndRemoveTask();
|
||||
//ToastUtils.show("finishAll() activity.finishAndRemoveTask();");
|
||||
} else if (WinBollGlobalApplication.getWinBollUI_TYPE() == WinBollGlobalApplication.WinBollUI_TYPE.Aplication) {
|
||||
// 结束窗口保留最近任务栏,建议前台服务类应用使用,可以保持应用的系统自觉性。
|
||||
activity.finish();
|
||||
//ToastUtils.show("finishAll() activity.finish();");
|
||||
} else {
|
||||
LogUtils.d(TAG, "WinBollApplication.WinBollUI_TYPE error.");
|
||||
//ToastUtils.show("WinBollApplication.WinBollUI_TYPE error.");
|
||||
}
|
||||
}
|
||||
}
|
||||
LogUtils.d(TAG, "finishAll no yet.");
|
||||
//ToastUtils.show(String.format("finishAll() size : %d", _mWinBollActivityList.size()));
|
||||
// for (int i = _mWinBollActivityList.size() - 1; i > -1; i--) {
|
||||
// WinBollActivity activity = _mWinBollActivityList.get(i);
|
||||
// ToastUtils.show("finishAll() activity");
|
||||
// if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) {
|
||||
// //ToastUtils.show("activity != null ...");
|
||||
// if (WinBollApplication.getWinBollUI_TYPE() == WinBollApplication.WinBollUI_TYPE.Service) {
|
||||
// // 结束窗口和最近任务栏, 建议前台服务类应用使用,可以方便用户再次调用 UI 操作。
|
||||
// activity.finishAndRemoveTask();
|
||||
// //ToastUtils.show("finishAll() activity.finishAndRemoveTask();");
|
||||
// } else if (WinBollApplication.getWinBollUI_TYPE() == WinBollApplication.WinBollUI_TYPE.Aplication) {
|
||||
// // 结束窗口保留最近任务栏,建议前台服务类应用使用,可以保持应用的系统自觉性。
|
||||
// activity.finish();
|
||||
// //ToastUtils.show("finishAll() activity.finish();");
|
||||
// } else {
|
||||
// ToastUtils.show("WinBollApplication.WinBollUI_TYPE error.");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
} catch (Exception e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 结束指定Activity
|
||||
//
|
||||
/**
|
||||
* 结束指定Activity
|
||||
*/
|
||||
public <T extends WinBollActivity> void finish(T activity) {
|
||||
try {
|
||||
if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) {
|
||||
@@ -215,6 +225,22 @@ public class WinBollActivityManager {
|
||||
if (preActivity != null) {
|
||||
resumeActivity(mContext, preActivity);
|
||||
}
|
||||
|
||||
// for (int i = 0; i < _mWinBollActivityList.size(); i++) {
|
||||
// if (_mWinBollActivityList.get(i).getTag().equals(activity.getTag())) {
|
||||
// //ToastUtils.show(String.format("equals i : %d\nTag : %s\nSize : %d", i, activity.getTag(), _mWinBollActivityList.size()));
|
||||
// if (i == 0) {
|
||||
// finishAll();
|
||||
// //ToastUtils.show("finish finishAll");
|
||||
// return;
|
||||
// }
|
||||
// if (i > 0) {
|
||||
// activity.finish();
|
||||
// resumeActivity(mContext, _mWinBollActivityList.get(i - 1));
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
@@ -222,9 +248,6 @@ public class WinBollActivityManager {
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 获取窗口队列中的前一个窗口
|
||||
//
|
||||
WinBollActivity getPreActivity(WinBollActivity activity) {
|
||||
try {
|
||||
boolean bingo = false;
|
||||
@@ -248,10 +271,12 @@ public class WinBollActivityManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
// 从管理列表中移除管理项
|
||||
//
|
||||
public <T extends WinBollActivity> boolean registeRemove(T activity) {
|
||||
// for (int i = 0; i < _mWinBollActivityList.size(); i++) {
|
||||
// if (registeRemove(activity, i)) {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
WinBollActivity activityTest = _mapActivityList.get(activity.getTag());
|
||||
if (activityTest != null) {
|
||||
_mapActivityList.remove(activity.getTag());
|
||||
@@ -260,9 +285,15 @@ public class WinBollActivityManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// 打印管理列表项列表里的信息
|
||||
//
|
||||
// public <T extends WinBollActivity> boolean registeRemove(T activity, int position) {
|
||||
// if (_mWinBollActivityList.get(position) == activity) {
|
||||
// _mWinBollActivityList.remove(position);
|
||||
// //ToastUtils.show(String.format("registeRemove remove.\nTag %s\nposition %d", activity.getTag(), position));
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
public static void printAvtivityListInfo() {
|
||||
//LogUtils.d(TAG, "printAvtivityListInfo");
|
||||
if (!_mapActivityList.isEmpty()) {
|
||||
@@ -279,4 +310,6 @@ public class WinBollActivityManager {
|
||||
LogUtils.d(TAG, "The map is empty.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,76 @@
|
||||
package cc.winboll.studio.libapputils.app;
|
||||
|
||||
import cc.winboll.studio.libapputils.bean.DebugBean;
|
||||
import cc.winboll.studio.libapputils.log.LogUtils;
|
||||
|
||||
public class WinBollApplication extends cc.winboll.studio.libappbase.GlobalApplication {
|
||||
|
||||
public static final String TAG = "WinBollApplication";
|
||||
|
||||
public static enum WinBollUI_TYPE {
|
||||
Aplication, // 退出应用后,保持最近任务栏任务记录主窗口
|
||||
Service // 退出应用后,清理所有最近任务栏任务记录窗口
|
||||
};
|
||||
|
||||
// 应用类型标志
|
||||
volatile static WinBollUI_TYPE _mWinBollUI_TYPE = WinBollUI_TYPE.Service;
|
||||
|
||||
static volatile WinBollApplication _WinBollApplication = null;
|
||||
MyActivityLifecycleCallbacks mMyActivityLifecycleCallbacks;
|
||||
|
||||
// 标记当前应用是否处于调试状态
|
||||
static volatile boolean isDebug = false;
|
||||
|
||||
public static void setIsDebug(boolean isDebug) {
|
||||
WinBollApplication.isDebug = isDebug;
|
||||
}
|
||||
|
||||
public static boolean isDebug() {
|
||||
return isDebug;
|
||||
}
|
||||
|
||||
//
|
||||
// 设置 WinBoll 应用 UI 类型
|
||||
//
|
||||
public static void setWinBollUI_TYPE(WinBollUI_TYPE mWinBollUI_TYPE) {
|
||||
_mWinBollUI_TYPE = mWinBollUI_TYPE;
|
||||
}
|
||||
|
||||
//
|
||||
// 获取 WinBoll 应用 UI 类型
|
||||
//
|
||||
public static WinBollUI_TYPE getWinBollUI_TYPE() {
|
||||
return _mWinBollUI_TYPE;
|
||||
}
|
||||
|
||||
MyActivityLifecycleCallbacks getMyActivityLifecycleCallbacks() {
|
||||
return mMyActivityLifecycleCallbacks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
_WinBollApplication = this;
|
||||
// 应用环境初始化, 基本调试环境
|
||||
//
|
||||
CrashHandler.init(this);
|
||||
LogUtils.init(this);
|
||||
|
||||
DebugBean debugBean = DebugBean.loadBean(this, DebugBean.class);
|
||||
if (debugBean == null) {
|
||||
//ToastUtils.show("debugBean == null");
|
||||
setIsDebug(false);
|
||||
} else {
|
||||
//ToastUtils.show("saveDebugStatus(" + String.valueOf(debugBean.isDebuging()) + ")");
|
||||
setIsDebug(debugBean.isDebuging());
|
||||
}
|
||||
|
||||
// 应用运行状态环境设置
|
||||
//
|
||||
mMyActivityLifecycleCallbacks = new MyActivityLifecycleCallbacks(this);
|
||||
registerActivityLifecycleCallbacks(mMyActivityLifecycleCallbacks);
|
||||
// 设置默认 WinBoll 应用 UI 类型
|
||||
setWinBollUI_TYPE(WinBollUI_TYPE.Service);
|
||||
//ToastUtils.show("WinBollUI_TYPE " + getWinBollUI_TYPE());
|
||||
}
|
||||
}
|
@@ -1,103 +0,0 @@
|
||||
package cc.winboll.studio.libapputils.app;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.view.Gravity;
|
||||
import android.widget.Toast;
|
||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
||||
import cc.winboll.studio.libapputils.bean.DebugBean;
|
||||
import cc.winboll.studio.libapputils.log.LogUtils;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import com.hjq.toast.style.WhiteToastStyle;
|
||||
|
||||
public class WinBollGlobalApplication extends GlobalApplication {
|
||||
|
||||
public static final String TAG = "WinBollGlobalApplication";
|
||||
|
||||
public static enum WinBollUI_TYPE {
|
||||
Aplication, // 退出应用后,保持最近任务栏任务记录主窗口
|
||||
Service // 退出应用后,清理所有最近任务栏任务记录窗口
|
||||
};
|
||||
|
||||
// 应用类型标志
|
||||
volatile static WinBollUI_TYPE _mWinBollUI_TYPE = WinBollUI_TYPE.Service;
|
||||
|
||||
//static volatile WinBollApplication _WinBollApplication = null;
|
||||
MyActivityLifecycleCallbacks mMyActivityLifecycleCallbacks;
|
||||
|
||||
// 标记当前应用是否处于调试状态
|
||||
static volatile boolean isDebug = false;
|
||||
|
||||
public synchronized static void setIsDebug(boolean isDebug) {
|
||||
WinBollGlobalApplication.isDebug = isDebug;
|
||||
}
|
||||
|
||||
public static boolean isDebug() {
|
||||
return isDebug;
|
||||
}
|
||||
|
||||
//
|
||||
// 设置 WinBoll 应用 UI 类型
|
||||
//
|
||||
public synchronized static void setWinBollUI_TYPE(WinBollUI_TYPE mWinBollUI_TYPE) {
|
||||
_mWinBollUI_TYPE = mWinBollUI_TYPE;
|
||||
}
|
||||
|
||||
//
|
||||
// 获取 WinBoll 应用 UI 类型
|
||||
//
|
||||
public synchronized static WinBollUI_TYPE getWinBollUI_TYPE() {
|
||||
return _mWinBollUI_TYPE;
|
||||
}
|
||||
|
||||
MyActivityLifecycleCallbacks getMyActivityLifecycleCallbacks() {
|
||||
return mMyActivityLifecycleCallbacks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getApplicationContext() {
|
||||
return super.getApplicationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Application getApplication() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
// 应用环境初始化, 基本调试环境
|
||||
//
|
||||
// 初始化日志模块
|
||||
LogUtils.init(this);
|
||||
|
||||
try {
|
||||
// 初始化 Toast 框架
|
||||
ToastUtils.init(this);
|
||||
// 设置 Toast 布局样式
|
||||
//ToastUtils.setView(R.layout.view_toast);
|
||||
ToastUtils.setStyle(new WhiteToastStyle());
|
||||
ToastUtils.setGravity(Gravity.BOTTOM, 0, 200);
|
||||
// 设置应用调试标志
|
||||
DebugBean debugBean = DebugBean.loadBean(this, DebugBean.class);
|
||||
if (debugBean == null) {
|
||||
//ToastUtils.show("debugBean == null");
|
||||
setIsDebug(false);
|
||||
} else {
|
||||
//ToastUtils.show("saveDebugStatus(" + String.valueOf(debugBean.isDebuging()) + ")");
|
||||
setIsDebug(debugBean.isDebuging());
|
||||
}
|
||||
// 应用窗口管理模块参数设置
|
||||
//
|
||||
mMyActivityLifecycleCallbacks = new MyActivityLifecycleCallbacks();
|
||||
registerActivityLifecycleCallbacks(mMyActivityLifecycleCallbacks);
|
||||
// 设置默认 WinBoll 应用 UI 类型
|
||||
setWinBollUI_TYPE(WinBollUI_TYPE.Service);
|
||||
//ToastUtils.show("WinBollUI_TYPE " + getWinBollUI_TYPE());
|
||||
} catch (Exception e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,142 +0,0 @@
|
||||
package cc.winboll.studio.libapputils.bean;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@QQ.COM
|
||||
* @Date 2025/01/20 14:19:02
|
||||
* @Describe 应用信息类
|
||||
*/
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class APPInfo implements Serializable {
|
||||
|
||||
public static final String TAG = "APPInfo";
|
||||
|
||||
// 应用名称
|
||||
String appName;
|
||||
// 应用图标
|
||||
int appIcon;
|
||||
// 应用描述
|
||||
String appDescription;
|
||||
// 应用Git仓库地址
|
||||
String appGitName;
|
||||
// 应用Git仓库拥有者
|
||||
String appGitOwner;
|
||||
// 应用Git仓库分支
|
||||
String appGitAPPBranch;
|
||||
// 应用Git仓库子项目文件夹
|
||||
String appGitAPPSubProjectFolder;
|
||||
// 应用主页
|
||||
String appHomePage;
|
||||
// 应用包名称
|
||||
String appAPKName;
|
||||
// 应用包存储文件夹名称
|
||||
String appAPKFolderName;
|
||||
|
||||
public APPInfo(String appName, int appIcon, String appDescription, String appGitName, String appGitOwner, String appGitAPPBranch, String appGitAPPSubProjectFolder, String appHomePage, String appAPKName, String appAPKFolderName) {
|
||||
this.appName = appName;
|
||||
this.appIcon = appIcon;
|
||||
this.appDescription = appDescription;
|
||||
this.appGitName = appGitName;
|
||||
this.appGitOwner = appGitOwner;
|
||||
this.appGitAPPBranch = appGitAPPBranch;
|
||||
this.appGitAPPSubProjectFolder = appGitAPPSubProjectFolder;
|
||||
this.appHomePage = appHomePage;
|
||||
this.appAPKName = appAPKName;
|
||||
this.appAPKFolderName = appAPKFolderName;
|
||||
}
|
||||
|
||||
public APPInfo() {
|
||||
this.appName = "WinBoll-APP";
|
||||
this.appIcon = R.drawable.ic_launcher;
|
||||
this.appDescription = "WinBoll APP";
|
||||
this.appGitName = "APP";
|
||||
this.appGitOwner = "Studio";
|
||||
this.appGitAPPBranch = "app";
|
||||
this.appGitAPPSubProjectFolder = "app";
|
||||
this.appHomePage = "https://www.winboll.cc/studio/details.php?app=APP";
|
||||
this.appAPKName = "APP";
|
||||
this.appAPKFolderName = "APP";
|
||||
}
|
||||
|
||||
public void setAppGitOwner(String appGitOwner) {
|
||||
this.appGitOwner = appGitOwner;
|
||||
}
|
||||
|
||||
public String getAppGitOwner() {
|
||||
return appGitOwner;
|
||||
}
|
||||
|
||||
public void setAppGitAPPBranch(String appGitAPPBranch) {
|
||||
this.appGitAPPBranch = appGitAPPBranch;
|
||||
}
|
||||
|
||||
public String getAppGitAPPBranch() {
|
||||
return appGitAPPBranch;
|
||||
}
|
||||
|
||||
public void setAppGitAPPSubProjectFolder(String appGitAPPSubProjectFolder) {
|
||||
this.appGitAPPSubProjectFolder = appGitAPPSubProjectFolder;
|
||||
}
|
||||
|
||||
public String getAppGitAPPSubProjectFolder() {
|
||||
return appGitAPPSubProjectFolder;
|
||||
}
|
||||
|
||||
public void setAppIcon(int appIcon) {
|
||||
this.appIcon = appIcon;
|
||||
}
|
||||
|
||||
public int getAppIcon() {
|
||||
return appIcon;
|
||||
}
|
||||
|
||||
public void setAppDescription(String appDescription) {
|
||||
this.appDescription = appDescription;
|
||||
}
|
||||
|
||||
public String getAppDescription() {
|
||||
return appDescription;
|
||||
}
|
||||
|
||||
public void setAppAPKFolderName(String appAPKFolderName) {
|
||||
this.appAPKFolderName = appAPKFolderName;
|
||||
}
|
||||
|
||||
public String getAppAPKFolderName() {
|
||||
return appAPKFolderName;
|
||||
}
|
||||
|
||||
public void setAppName(String appName) {
|
||||
this.appName = appName;
|
||||
}
|
||||
|
||||
public String getAppName() {
|
||||
return appName;
|
||||
}
|
||||
|
||||
public void setAppGitName(String appGitName) {
|
||||
this.appGitName = appGitName;
|
||||
}
|
||||
|
||||
public String getAppGitName() {
|
||||
return appGitName;
|
||||
}
|
||||
|
||||
public void setAppHomePage(String appHomePage) {
|
||||
this.appHomePage = appHomePage;
|
||||
}
|
||||
|
||||
public String getAppHomePage() {
|
||||
return appHomePage;
|
||||
}
|
||||
|
||||
public void setAppAPKName(String appAPKName) {
|
||||
this.appAPKName = appAPKName;
|
||||
}
|
||||
|
||||
public String getAppAPKName() {
|
||||
return appAPKName;
|
||||
}
|
||||
}
|
||||
|
@@ -1,41 +1,30 @@
|
||||
package cc.winboll.studio.libapputils.log;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import cc.winboll.studio.libapputils.app.WinBollActivity;
|
||||
import cc.winboll.studio.libapputils.ads.ADsView;
|
||||
import cc.winboll.studio.libapputils.app.WinBollApplication;
|
||||
import android.view.View;
|
||||
import android.app.Activity;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@QQ.COM
|
||||
* @Date 2024/08/12 15:07:58
|
||||
* @Describe WinBoll 应用日志窗口
|
||||
*/
|
||||
import android.os.Bundle;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import cc.winboll.studio.libapputils.app.WinBollActivity;
|
||||
import cc.winboll.studio.libapputils.app.WinBollGlobalApplication;
|
||||
|
||||
public class LogActivity extends WinBollActivity {
|
||||
public class LogActivity extends Activity {
|
||||
|
||||
public static final String TAG = "LogActivity";
|
||||
|
||||
LogView mLogView;
|
||||
//ADsView mADsView;
|
||||
|
||||
@Override
|
||||
public String getTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Toolbar initToolBar() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnableDisplayHomeAsUp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAddWinBollToolBar() {
|
||||
return false;
|
||||
}
|
||||
// @Override
|
||||
// protected boolean isEnableDisplayHomeAsUp() {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -43,8 +32,12 @@ public class LogActivity extends WinBollActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_log);
|
||||
mLogView = findViewById(R.id.logview);
|
||||
|
||||
if (WinBollGlobalApplication.isDebug()) { mLogView.start(); }
|
||||
//mADsView = findViewById(R.id.adsview);
|
||||
//mADsView.loadUrl("https://www.winboll.cc");
|
||||
//mLogView.setVisibility(WinBollApplication.isDebug()?View.GONE:View.VISIBLE);
|
||||
//mADsView.setVisibility(WinBollApplication.isDebug()?View.GONE:View.VISIBLE);
|
||||
|
||||
if(WinBollApplication.isDebug()) { mLogView.start(); }
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,4 +46,21 @@ public class LogActivity extends WinBollActivity {
|
||||
super.onResume();
|
||||
mLogView.start();
|
||||
}
|
||||
|
||||
// @Override
|
||||
// protected boolean isAddWinBollToolBar() {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected Toolbar initToolBar() {
|
||||
// LogUtils.d(TAG, "initToolBar");
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String getTag() {
|
||||
// LogUtils.d(TAG, "getTag");
|
||||
// return TAG;
|
||||
// }
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ package cc.winboll.studio.libapputils.log;
|
||||
* @Describe 应用日志类
|
||||
*/
|
||||
import android.content.Context;
|
||||
import cc.winboll.studio.libapputils.app.WinBollGlobalApplication;
|
||||
import cc.winboll.studio.libapputils.app.WinBollApplication;
|
||||
import cc.winboll.studio.libapputils.util.FileUtils;
|
||||
import dalvik.system.DexFile;
|
||||
import java.io.BufferedReader;
|
||||
@@ -61,7 +61,7 @@ public class LogUtils {
|
||||
// 初始化函数
|
||||
//
|
||||
public static void init(Context context, LOG_LEVEL logLevel) {
|
||||
if (WinBollGlobalApplication.isDebug()) {
|
||||
if (WinBollApplication.isDebug()) {
|
||||
// 初始化日志缓存文件路径
|
||||
_mfLogCacheDir = new File(context.getApplicationContext().getExternalCacheDir(), TAG);
|
||||
if (!_mfLogCacheDir.exists()) {
|
||||
@@ -174,9 +174,8 @@ public class LogUtils {
|
||||
mapTAGList.put(tagValue, false);
|
||||
}
|
||||
}
|
||||
} catch (NoClassDefFoundError | ClassNotFoundException | IllegalAccessException e) {
|
||||
LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
|
||||
//LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
} catch (ClassNotFoundException | IllegalAccessException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
//Toast.makeText(context, TAG + " : " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
@@ -19,8 +19,7 @@ import android.widget.LinearLayout;
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import cc.winboll.studio.libapputils.app.AppVersionUtils;
|
||||
import cc.winboll.studio.libapputils.app.WinBollActivityManager;
|
||||
import cc.winboll.studio.libapputils.app.WinBollGlobalApplication;
|
||||
import cc.winboll.studio.libapputils.bean.APPInfo;
|
||||
import cc.winboll.studio.libapputils.app.WinBollApplication;
|
||||
import cc.winboll.studio.libapputils.bean.DebugBean;
|
||||
import cc.winboll.studio.libapputils.log.LogUtils;
|
||||
import cc.winboll.studio.libapputils.util.PrefUtils;
|
||||
@@ -42,8 +41,6 @@ public class AboutView extends LinearLayout {
|
||||
public static final int MSG_APPUPDATE_CHECKED = 0;
|
||||
|
||||
Context mContext;
|
||||
APPInfo mAPPInfo;
|
||||
|
||||
WinBollServiceStatusView mWinBollServiceStatusView;
|
||||
OnRequestDevUserInfoAutofillListener mOnRequestDevUserInfoAutofillListener;
|
||||
String mszAppName = "";
|
||||
@@ -58,66 +55,38 @@ public class AboutView extends LinearLayout {
|
||||
String mszGitea = "";
|
||||
int mnAppIcon = 0;
|
||||
String mszWinBollServerHost;
|
||||
//String mszReleaseAPKName;
|
||||
String mszReleaseAPKName;
|
||||
EditText metDevUserName;
|
||||
EditText metDevUserPassword;
|
||||
|
||||
public AboutView(Context context, APPInfo appInfo) {
|
||||
super(context);
|
||||
mContext = context;
|
||||
|
||||
setAPPInfo(appInfo);
|
||||
initView(context);
|
||||
}
|
||||
|
||||
public AboutView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mContext = context;
|
||||
|
||||
initView(context, attrs);
|
||||
}
|
||||
|
||||
public void setAPPInfo(APPInfo appInfo) {
|
||||
mAPPInfo = appInfo;
|
||||
}
|
||||
|
||||
APPInfo createAppInfo(Context context, AttributeSet attrs) {
|
||||
APPInfo appInfo = new APPInfo();
|
||||
void initView(Context context, AttributeSet attrs) {
|
||||
mContext = context;
|
||||
mszWinBollServerHost = WinBollApplication.isDebug() ? "http://10.8.0.13": "https://www.winboll.cc";
|
||||
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AboutView);
|
||||
appInfo.setAppName(typedArray.getString(R.styleable.AboutView_app_name));
|
||||
appInfo.setAppAPKFolderName(typedArray.getString(R.styleable.AboutView_app_apkfoldername));
|
||||
appInfo.setAppAPKName(typedArray.getString(R.styleable.AboutView_app_apkname));
|
||||
appInfo.setAppGitName(typedArray.getString(R.styleable.AboutView_app_gitname));
|
||||
appInfo.setAppGitOwner(typedArray.getString(R.styleable.AboutView_app_gitowner));
|
||||
appInfo.setAppGitAPPBranch(typedArray.getString(R.styleable.AboutView_app_gitappbranch));
|
||||
appInfo.setAppGitAPPSubProjectFolder(typedArray.getString(R.styleable.AboutView_app_gitappsubprojectfolder));
|
||||
appInfo.setAppDescription(typedArray.getString(R.styleable.AboutView_appdescription));
|
||||
appInfo.setAppIcon(typedArray.getResourceId(R.styleable.AboutView_appicon, R.drawable.ic_winboll));
|
||||
mszAppName = typedArray.getString(R.styleable.AboutView_app_name);
|
||||
mszAppAPKFolderName = typedArray.getString(R.styleable.AboutView_app_apkfoldername);
|
||||
mszAppAPKName = typedArray.getString(R.styleable.AboutView_app_apkname);
|
||||
mszAppGitName = typedArray.getString(R.styleable.AboutView_app_gitname);
|
||||
mszAppDescription = typedArray.getString(R.styleable.AboutView_appdescription);
|
||||
mnAppIcon = typedArray.getResourceId(R.styleable.AboutView_appicon, R.drawable.ic_winboll);
|
||||
// 返回一个绑定资源结束的信号给资源
|
||||
typedArray.recycle();
|
||||
return appInfo;
|
||||
}
|
||||
|
||||
void initView(Context context) {
|
||||
mszAppName = mAPPInfo.getAppName();
|
||||
mszAppAPKFolderName = mAPPInfo.getAppAPKFolderName();
|
||||
mszAppAPKName = mAPPInfo.getAppAPKName();
|
||||
mszAppGitName = mAPPInfo.getAppGitName();
|
||||
mszAppDescription = mAPPInfo.getAppDescription();
|
||||
mnAppIcon = mAPPInfo.getAppIcon();
|
||||
|
||||
mszWinBollServerHost = WinBollGlobalApplication.isDebug() ? "https://dev.winboll.cc": "https://www.winboll.cc";
|
||||
|
||||
try {
|
||||
mszAppVersionName = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
mszCurrentAppPackageName = mszAppAPKName + "_" + mszAppVersionName + ".apk";
|
||||
mszCurrentAppPackageName = mszAppName + "_" + mszAppVersionName + ".apk";
|
||||
mszHomePage = mszWinBollServerHost + "/studio/details.php?app=" + mszAppAPKFolderName;
|
||||
mszGitea = "https://gitea.winboll.cc/" + mAPPInfo.getAppGitOwner() + "/" + mszAppGitName + "/src/branch/" + mAPPInfo.getAppGitAPPBranch() + "/" + mAPPInfo.getAppGitAPPSubProjectFolder();
|
||||
mszGitea = "https://gitea.winboll.cc/Studio/" + mszAppGitName + ".git";
|
||||
|
||||
if (WinBollGlobalApplication.isDebug()) {
|
||||
if (WinBollApplication.isDebug()) {
|
||||
LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
View addedView = inflater.inflate(R.layout.view_about_dev, this, false);
|
||||
LinearLayout llMain = addedView.findViewById(R.id.viewaboutdevLinearLayout1);
|
||||
@@ -151,21 +120,15 @@ public class AboutView extends LinearLayout {
|
||||
//llMain.addView(createAboutPage());
|
||||
|
||||
// 就读取正式版应用包版本号,设置 Release 应用包文件名
|
||||
// String szReleaseAppVersionName = "";
|
||||
// try {
|
||||
// //LogUtils.d(TAG, String.format("mContext.getPackageName() %s", mContext.getPackageName()));
|
||||
// String szSubBetaSuffix = subBetaSuffix(mContext.getPackageName());
|
||||
// //LogUtils.d(TAG, String.format("szSubBetaSuffix : %s", szSubBetaSuffix));
|
||||
// szReleaseAppVersionName = mContext.getPackageManager().getPackageInfo(szSubBetaSuffix, 0).versionName;
|
||||
// } catch (PackageManager.NameNotFoundException e) {
|
||||
// LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
// }
|
||||
// mszReleaseAPKName = mszAppAPKName + "_" + szReleaseAppVersionName + ".apk";
|
||||
}
|
||||
String szReleaseAppVersionName = "";
|
||||
try {
|
||||
szReleaseAppVersionName = mContext.getPackageManager().getPackageInfo(subBetaSuffix(mContext.getPackageName()), 0).versionName;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
mszReleaseAPKName = mszAppAPKName + "_" + szReleaseAppVersionName + ".apk";
|
||||
|
||||
|
||||
void initView(Context context, AttributeSet attrs) {
|
||||
mAPPInfo = createAppInfo(context, attrs);
|
||||
initView(context);
|
||||
}
|
||||
|
||||
public static String subBetaSuffix(String input) {
|
||||
@@ -187,13 +150,10 @@ public class AboutView extends LinearLayout {
|
||||
return;
|
||||
}*/
|
||||
|
||||
// if (!AppVersionUtils.isHasNewStageReleaseVersion(mszReleaseAPKName, mszNewestAppPackageName)) {
|
||||
// ToastUtils.delayedShow("Current app is the newest.", 5000);
|
||||
// }
|
||||
if (!AppVersionUtils.isHasNewVersion2(mszCurrentAppPackageName, mszNewestAppPackageName)) {
|
||||
if (!AppVersionUtils.isHasNewStageReleaseVersion(mszReleaseAPKName, mszNewestAppPackageName)) {
|
||||
ToastUtils.delayedShow("Current app is the newest.", 5000);
|
||||
} else {
|
||||
String szMsg = "Current app is :\n[ " + mszCurrentAppPackageName
|
||||
String szMsg = "Current app is :\n[ " + mszReleaseAPKName
|
||||
+ " ]\nThe last app is :\n[ " + mszNewestAppPackageName
|
||||
+ " ]\nIs download the last app?";
|
||||
YesNoAlertDialog.show(mContext, "Application Update Prompt", szMsg, mIsDownlaodUpdateListener);
|
||||
@@ -208,7 +168,7 @@ public class AboutView extends LinearLayout {
|
||||
// 定义应用调试按钮
|
||||
//
|
||||
Element elementAppMode;
|
||||
if (WinBollGlobalApplication.isDebug()) {
|
||||
if (WinBollApplication.isDebug()) {
|
||||
elementAppMode = new Element(mContext.getString(R.string.app_normal), R.drawable.ic_winboll);
|
||||
elementAppMode.setOnClickListener(mAppNormalOnClickListener);
|
||||
} else {
|
||||
@@ -240,7 +200,7 @@ public class AboutView extends LinearLayout {
|
||||
//.addItem(versionElement)
|
||||
//.addItem(adsElement)
|
||||
//.addGroup("Connect with us")
|
||||
.addEmail("ZhanGSKen@AliYun.Com")
|
||||
.addEmail("ZhanGSKen@QQ.COM")
|
||||
.addWebsite(mszHomePage)
|
||||
.addItem(elementAppMode)
|
||||
.addItem(elementGitWeb)
|
||||
@@ -274,7 +234,7 @@ public class AboutView extends LinearLayout {
|
||||
if (intent != null) {
|
||||
intent.setAction(cc.winboll.studio.libapputils.intent.action.DEBUGVIEW);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
WinBollGlobalApplication.setIsDebug(true);
|
||||
WinBollApplication.setIsDebug(true);
|
||||
DebugBean.saveBean(context, new DebugBean(true));
|
||||
|
||||
WinBollActivityManager.getInstance(context).finishAll();
|
||||
@@ -286,7 +246,7 @@ public class AboutView extends LinearLayout {
|
||||
Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
|
||||
if (intent != null) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
WinBollGlobalApplication.setIsDebug(false);
|
||||
WinBollApplication.setIsDebug(false);
|
||||
DebugBean.saveBean(context, new DebugBean(false));
|
||||
|
||||
WinBollActivityManager.getInstance(context).finishAll();
|
||||
@@ -312,7 +272,7 @@ public class AboutView extends LinearLayout {
|
||||
String szUrl = mszWinBollServerHost + "/studio/details.php?app=" + mszAppAPKFolderName;
|
||||
// 构建包含认证信息的请求
|
||||
String credential = "";
|
||||
if (WinBollGlobalApplication.isDebug()) {
|
||||
if (WinBollApplication.isDebug()) {
|
||||
credential = Credentials.basic(metDevUserName.getText().toString(), metDevUserPassword.getText().toString());
|
||||
PrefUtils.saveString(mContext, "metDevUserName", metDevUserName.getText().toString());
|
||||
PrefUtils.saveString(mContext, "metDevUserPassword", metDevUserPassword.getText().toString());
|
||||
|
@@ -1,22 +1,25 @@
|
||||
<?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">
|
||||
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"/>
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/activityaboutToolbar1"/>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1.0"
|
||||
android:id="@+id/activityaboutLinearLayout1"/>
|
||||
<cc.winboll.studio.libapputils.view.AboutView
|
||||
app:app_name= "APP"
|
||||
app:app_apkfoldername="APP"
|
||||
app:app_apkname="APP"
|
||||
app:app_gitname="APP"
|
||||
app:appdescription="WinBoll.CC 网站客户端。"
|
||||
app:appicon="@drawable/ic_winboll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/activityaboutAboutView1"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@@ -8,8 +8,8 @@
|
||||
app:cardElevation="4dp"
|
||||
app:cardCornerRadius="4dp"
|
||||
android:id="@+id/listviewauthinfoCardView1"
|
||||
android:layout_marginLeft="0dp"
|
||||
android:layout_marginRight="5dp">
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
@@ -19,7 +19,6 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:id="@+id/viewlogtagTextView1"/>
|
||||
|
||||
<CheckBox
|
||||
|
@@ -15,9 +15,6 @@
|
||||
|
||||
<item android:title="DebugTools">
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/item_testcrashreport"
|
||||
android:title="Test Application Crash Report"/>
|
||||
<item
|
||||
android:id="@+id/item_unittest"
|
||||
android:title="UnitTest"/>
|
||||
|
@@ -5,9 +5,6 @@
|
||||
<attr name="app_apkfoldername" format="string" />
|
||||
<attr name="app_apkname" format="string" />
|
||||
<attr name="app_gitname" format="string" />
|
||||
<attr name="app_gitowner" format="string" />
|
||||
<attr name="app_gitappbranch" format="string" />
|
||||
<attr name="app_gitappsubprojectfolder" format="string" />
|
||||
<attr name="appdescription" format="string" />
|
||||
<attr name="appicon" format="reference" />
|
||||
</declare-styleable>
|
||||
|
@@ -1,10 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- WinBoll 默认方案 -->
|
||||
<color name="colorPrimary">#FF196ABC</color>
|
||||
<color name="colorPrimaryDark">#FF002B57</color>
|
||||
<color name="colorAccent">#FF80BFFF</color>
|
||||
<color name="colorToastFrame">#FFA9A9A9</color>
|
||||
<color name="colorToastShadow">#FF000000</color>
|
||||
<color name="colorToastBackgroung">#FFFFFFFF</color>
|
||||
</resources>
|
||||
|
Reference in New Issue
Block a user