Compare commits
20 Commits
apputils-v
...
apputils-v
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0031100219 | ||
|
|
f9e7d362b7 | ||
|
|
8d9d308c68 | ||
|
|
d3b12207e0 | ||
|
|
befea40f61 | ||
|
|
cc1ca5b092 | ||
|
|
af77c09415 | ||
|
|
2968d1dbfa | ||
|
|
db96ece15f | ||
|
|
c0347ed706 | ||
|
|
ad408dfb53 | ||
|
|
a2e963b53e | ||
|
|
953da400be | ||
|
|
165765e0eb | ||
|
|
f5f88a61b0 | ||
|
|
2f33574d5c | ||
|
|
afd93d6871 | ||
|
|
b7affa477f | ||
|
|
4f317322fc | ||
|
|
41c0394c4a |
1
.gitignore
vendored
@@ -96,6 +96,7 @@ local.properties
|
||||
|
||||
## 忽略模块应用编译配置
|
||||
/settings.gradle
|
||||
/gradle.properties
|
||||
|
||||
## 忽略 srv 纠结问题
|
||||
/srv/
|
||||
|
||||
1
androiddemo/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
0
androiddemo/app_update_description.txt
Normal file
74
androiddemo/build.gradle
Normal file
@@ -0,0 +1,74 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply from: '../.winboll/winboll_app_build.gradle'
|
||||
apply from: '../.winboll/winboll_lint_build.gradle'
|
||||
|
||||
def genVersionName(def versionName){
|
||||
// 检查编译标志位配置
|
||||
assert (winbollBuildProps['stageCount'] != null)
|
||||
assert (winbollBuildProps['baseVersion'] != null)
|
||||
// 保存基础版本号
|
||||
winbollBuildProps.setProperty("baseVersion", "${versionName}");
|
||||
//保存编译标志配置
|
||||
FileOutputStream fos = new FileOutputStream(winbollBuildPropsFile)
|
||||
winbollBuildProps.store(fos, "${winbollBuildPropsDesc}");
|
||||
fos.close();
|
||||
|
||||
// 返回编译版本号
|
||||
return "${versionName}." + winbollBuildProps['stageCount']
|
||||
}
|
||||
|
||||
android {
|
||||
productFlavors {
|
||||
beta {
|
||||
}
|
||||
stage {
|
||||
}
|
||||
}
|
||||
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion "30.0.3"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "cc.winboll.studio.androiddemo"
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
// versionName 更新后需要手动设置
|
||||
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
|
||||
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
|
||||
versionName "1.0"
|
||||
if(true) {
|
||||
versionName = genVersionName("${versionName}")
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
// 吐司类库
|
||||
implementation 'com.github.getActivity:ToastUtils:10.5'
|
||||
|
||||
// Android 类库
|
||||
// https://mvnrepository.com/artifact/com.android.support/support-v4
|
||||
implementation 'com.android.support:support-v4:28.0.0'
|
||||
// https://mvnrepository.com/artifact/com.android.support/support-compat
|
||||
implementation 'com.android.support:support-compat:28.0.0'
|
||||
// https://mvnrepository.com/artifact/com.android.support/support-media-compat
|
||||
implementation 'com.android.support:support-media-compat:28.0.0'
|
||||
// https://mvnrepository.com/artifact/com.android.support/support-core-utils
|
||||
implementation 'com.android.support:support-core-utils:28.0.0'
|
||||
// https://mvnrepository.com/artifact/com.android.support/support-core-ui
|
||||
implementation 'com.android.support:support-core-ui:28.0.0'
|
||||
// https://mvnrepository.com/artifact/com.android.support/support-fragment
|
||||
implementation 'com.android.support:support-fragment:28.0.0'
|
||||
// https://mvnrepository.com/artifact/com.android.support/recyclerview-v7
|
||||
implementation 'com.android.support:recyclerview-v7:28.0.0'
|
||||
}
|
||||
8
androiddemo/build.properties
Normal file
@@ -0,0 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Tue Mar 11 18:02:14 GMT 2025
|
||||
stageCount=0
|
||||
libraryProject=
|
||||
baseVersion=1.0
|
||||
publishVersion=1.0.0
|
||||
buildCount=1
|
||||
baseBetaVersion=1.0.1
|
||||
21
androiddemo/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
12
androiddemo/src/beta/AndroidManifest.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools" >
|
||||
|
||||
<application>
|
||||
|
||||
<!-- Put flavor specific code here -->
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
7
androiddemo/src/beta/res/values/strings.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
|
||||
<string name="app_name">Android Demo +</string>
|
||||
|
||||
</resources>
|
||||
39
androiddemo/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,39 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="cc.winboll.studio.androiddemo">
|
||||
|
||||
<application
|
||||
tools:replace="android:appComponentFactory"
|
||||
android:appComponentFactory="android.support.v4.app.CoreComponentFactory"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme"
|
||||
android:resizeableActivity="true"
|
||||
android:name=".GlobalApplication">
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
<meta-data
|
||||
android:name="android.max_aspect"
|
||||
android:value="4.0"/>
|
||||
|
||||
<activity android:name=".GlobalApplication$CrashActivity"/>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,334 @@
|
||||
package cc.winboll.studio.androiddemo;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.HorizontalScrollView;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class GlobalApplication extends Application {
|
||||
|
||||
private static Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
CrashHandler.getInstance().registerGlobal(this);
|
||||
CrashHandler.getInstance().registerPart(this);
|
||||
}
|
||||
|
||||
public static void write(InputStream input, OutputStream output) throws IOException {
|
||||
byte[] buf = new byte[1024 * 8];
|
||||
int len;
|
||||
while ((len = input.read(buf)) != -1) {
|
||||
output.write(buf, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(File file, byte[] data) throws IOException {
|
||||
File parent = file.getParentFile();
|
||||
if (parent != null && !parent.exists()) parent.mkdirs();
|
||||
|
||||
ByteArrayInputStream input = new ByteArrayInputStream(data);
|
||||
FileOutputStream output = new FileOutputStream(file);
|
||||
try {
|
||||
write(input, output);
|
||||
} finally {
|
||||
closeIO(input, output);
|
||||
}
|
||||
}
|
||||
|
||||
public static String toString(InputStream input) throws IOException {
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
write(input, output);
|
||||
try {
|
||||
return output.toString("UTF-8");
|
||||
} finally {
|
||||
closeIO(input, output);
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeIO(Closeable... closeables) {
|
||||
for (Closeable closeable : closeables) {
|
||||
try {
|
||||
if (closeable != null) closeable.close();
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
public static class CrashHandler {
|
||||
|
||||
public static final UncaughtExceptionHandler DEFAULT_UNCAUGHT_EXCEPTION_HANDLER = Thread.getDefaultUncaughtExceptionHandler();
|
||||
|
||||
private static CrashHandler sInstance;
|
||||
|
||||
private PartCrashHandler mPartCrashHandler;
|
||||
|
||||
public static CrashHandler getInstance() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new CrashHandler();
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public void registerGlobal(Context context) {
|
||||
registerGlobal(context, null);
|
||||
}
|
||||
|
||||
public void registerGlobal(Context context, String crashDir) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandlerImpl(context.getApplicationContext(), crashDir));
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
Thread.setDefaultUncaughtExceptionHandler(DEFAULT_UNCAUGHT_EXCEPTION_HANDLER);
|
||||
}
|
||||
|
||||
public void registerPart(Context context) {
|
||||
unregisterPart(context);
|
||||
mPartCrashHandler = new PartCrashHandler(context.getApplicationContext());
|
||||
MAIN_HANDLER.postAtFrontOfQueue(mPartCrashHandler);
|
||||
}
|
||||
|
||||
public void unregisterPart(Context context) {
|
||||
if (mPartCrashHandler != null) {
|
||||
mPartCrashHandler.isRunning.set(false);
|
||||
mPartCrashHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class PartCrashHandler implements Runnable {
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
public AtomicBoolean isRunning = new AtomicBoolean(true);
|
||||
|
||||
public PartCrashHandler(Context context) {
|
||||
this.mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (isRunning.get()) {
|
||||
try {
|
||||
Looper.loop();
|
||||
} catch (final Throwable e) {
|
||||
e.printStackTrace();
|
||||
if (isRunning.get()) {
|
||||
MAIN_HANDLER.post(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(mContext, e.toString(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (e instanceof RuntimeException) {
|
||||
throw (RuntimeException)e;
|
||||
} else {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class UncaughtExceptionHandlerImpl implements UncaughtExceptionHandler {
|
||||
|
||||
private static DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss");
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
private final File mCrashDir;
|
||||
|
||||
public UncaughtExceptionHandlerImpl(Context context, String crashDir) {
|
||||
this.mContext = context;
|
||||
this.mCrashDir = TextUtils.isEmpty(crashDir) ? new File(mContext.getExternalCacheDir(), "crash") : new File(crashDir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncaughtException(Thread thread, Throwable throwable) {
|
||||
try {
|
||||
|
||||
String log = buildLog(throwable);
|
||||
writeLog(log);
|
||||
|
||||
try {
|
||||
Intent intent = new Intent(mContext, CrashActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(Intent.EXTRA_TEXT, log);
|
||||
mContext.startActivity(intent);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
writeLog(e.toString());
|
||||
}
|
||||
|
||||
throwable.printStackTrace();
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
System.exit(0);
|
||||
|
||||
} catch (Throwable e) {
|
||||
if (DEFAULT_UNCAUGHT_EXCEPTION_HANDLER != null) DEFAULT_UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(thread, throwable);
|
||||
}
|
||||
}
|
||||
|
||||
private String buildLog(Throwable throwable) {
|
||||
String time = DATE_FORMAT.format(new Date());
|
||||
|
||||
String versionName = "unknown";
|
||||
long versionCode = 0;
|
||||
try {
|
||||
PackageInfo packageInfo = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0);
|
||||
versionName = packageInfo.versionName;
|
||||
versionCode = Build.VERSION.SDK_INT >= 28 ? packageInfo.getLongVersionCode() : packageInfo.versionCode;
|
||||
} catch (Throwable ignored) {}
|
||||
|
||||
LinkedHashMap<String, String> head = new LinkedHashMap<String, String>();
|
||||
head.put("Time Of Crash", time);
|
||||
head.put("Device", String.format("%s, %s", Build.MANUFACTURER, Build.MODEL));
|
||||
head.put("Android Version", String.format("%s (%d)", Build.VERSION.RELEASE, Build.VERSION.SDK_INT));
|
||||
head.put("App Version", String.format("%s (%d)", versionName, versionCode));
|
||||
head.put("Kernel", getKernel());
|
||||
head.put("Support Abis", Build.VERSION.SDK_INT >= 21 && Build.SUPPORTED_ABIS != null ? Arrays.toString(Build.SUPPORTED_ABIS): "unknown");
|
||||
head.put("Fingerprint", Build.FINGERPRINT);
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
for (String key : head.keySet()) {
|
||||
if (builder.length() != 0) builder.append("\n");
|
||||
builder.append(key);
|
||||
builder.append(" : ");
|
||||
builder.append(head.get(key));
|
||||
}
|
||||
|
||||
builder.append("\n\n");
|
||||
builder.append(Log.getStackTraceString(throwable));
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private void writeLog(String log) {
|
||||
String time = DATE_FORMAT.format(new Date());
|
||||
File file = new File(mCrashDir, "crash_" + time + ".txt");
|
||||
try {
|
||||
write(file, log.getBytes("UTF-8"));
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getKernel() {
|
||||
try {
|
||||
return GlobalApplication.toString(new FileInputStream("/proc/version")).trim();
|
||||
} catch (Throwable e) {
|
||||
return e.getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class CrashActivity extends Activity {
|
||||
|
||||
private String mLog;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setTheme(android.R.style.Theme_DeviceDefault);
|
||||
setTitle("App Crash");
|
||||
|
||||
mLog = getIntent().getStringExtra(Intent.EXTRA_TEXT);
|
||||
|
||||
ScrollView contentView = new ScrollView(this);
|
||||
contentView.setFillViewport(true);
|
||||
|
||||
HorizontalScrollView horizontalScrollView = new HorizontalScrollView(this);
|
||||
|
||||
TextView textView = new TextView(this);
|
||||
int padding = dp2px(16);
|
||||
textView.setPadding(padding, padding, padding, padding);
|
||||
textView.setText(mLog);
|
||||
textView.setTextIsSelectable(true);
|
||||
textView.setTypeface(Typeface.DEFAULT);
|
||||
textView.setLinksClickable(true);
|
||||
|
||||
horizontalScrollView.addView(textView);
|
||||
contentView.addView(horizontalScrollView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
|
||||
setContentView(contentView);
|
||||
}
|
||||
|
||||
private void restart() {
|
||||
Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
|
||||
if (intent != null) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
}
|
||||
finish();
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private static int dp2px(float dpValue) {
|
||||
final float scale = Resources.getSystem().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
menu.add(0, android.R.id.copy, 0, android.R.string.copy)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.copy:
|
||||
ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cm.setPrimaryClip(ClipData.newPlainText(getPackageName(), mLog));
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package cc.winboll.studio.androiddemo;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class MainActivity extends Activity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
BIN
androiddemo/src/main/res/drawable/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
16
androiddemo/src/main/res/layout/activity_main.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical|center_horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Android Demo"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
9
androiddemo/src/main/res/values-v21/styles.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?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>
|
||||
6
androiddemo/src/main/res/values/colors.xml
Normal file
@@ -0,0 +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>
|
||||
4
androiddemo/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Android Demo</string>
|
||||
</resources>
|
||||
5
androiddemo/src/main/res/values/styles.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="AppTheme" parent="@android:style/Theme.Holo.Light.DarkActionBar">
|
||||
</style>
|
||||
</resources>
|
||||
12
androiddemo/src/stage/AndroidManifest.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools" >
|
||||
|
||||
<application>
|
||||
|
||||
<!-- Put flavor specific code here -->
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
6
androiddemo/src/stage/res/values/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<!-- Put flavor specific strings here -->
|
||||
|
||||
</resources>
|
||||
1
androidxdemo/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
0
androidxdemo/app_update_description.txt
Normal file
76
androidxdemo/build.gradle
Normal file
@@ -0,0 +1,76 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply from: '../.winboll/winboll_app_build.gradle'
|
||||
apply from: '../.winboll/winboll_lint_build.gradle'
|
||||
|
||||
def genVersionName(def versionName){
|
||||
// 检查编译标志位配置
|
||||
assert (winbollBuildProps['stageCount'] != null)
|
||||
assert (winbollBuildProps['baseVersion'] != null)
|
||||
// 保存基础版本号
|
||||
winbollBuildProps.setProperty("baseVersion", "${versionName}");
|
||||
//保存编译标志配置
|
||||
FileOutputStream fos = new FileOutputStream(winbollBuildPropsFile)
|
||||
winbollBuildProps.store(fos, "${winbollBuildPropsDesc}");
|
||||
fos.close();
|
||||
|
||||
// 返回编译版本号
|
||||
return "${versionName}." + winbollBuildProps['stageCount']
|
||||
}
|
||||
|
||||
android {
|
||||
productFlavors {
|
||||
beta {
|
||||
}
|
||||
stage {
|
||||
}
|
||||
}
|
||||
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion "30.0.3"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "cc.winboll.studio.androidxdemo"
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
// versionName 更新后需要手动设置
|
||||
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
|
||||
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
|
||||
versionName "1.0"
|
||||
if(true) {
|
||||
versionName = genVersionName("${versionName}")
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
// SSH
|
||||
implementation 'com.jcraft:jsch:0.1.55'
|
||||
// Html 解析
|
||||
implementation 'org.jsoup:jsoup:1.13.1'
|
||||
// 二维码类库
|
||||
implementation 'com.google.zxing:core:3.4.1'
|
||||
implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
|
||||
// 应用介绍页类库
|
||||
implementation 'io.github.medyo:android-about-page:2.0.0'
|
||||
// 吐司类库
|
||||
implementation 'com.github.getActivity:ToastUtils:10.5'
|
||||
// 网络连接类库
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.4.1'
|
||||
// Android 类库
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.viewpager:viewpager:1.0.0'
|
||||
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
|
||||
implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
|
||||
implementation 'androidx.fragment:fragment:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
}
|
||||
8
androidxdemo/build.properties
Normal file
@@ -0,0 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Tue Mar 11 18:25:43 GMT 2025
|
||||
stageCount=0
|
||||
libraryProject=
|
||||
baseVersion=1.0
|
||||
publishVersion=1.0.0
|
||||
buildCount=4
|
||||
baseBetaVersion=1.0.1
|
||||
21
androidxdemo/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
12
androidxdemo/src/beta/AndroidManifest.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools" >
|
||||
|
||||
<application>
|
||||
|
||||
<!-- Put flavor specific code here -->
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
6
androidxdemo/src/beta/res/values/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_name">AndroidX Demo +</string>
|
||||
|
||||
</resources>
|
||||
37
androidxdemo/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="cc.winboll.studio.androidxdemo">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme"
|
||||
android:resizeableActivity="true"
|
||||
android:name=".GlobalApplication">
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name">
|
||||
|
||||
<intent-filter>
|
||||
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
<meta-data
|
||||
android:name="android.max_aspect"
|
||||
android:value="4.0"/>
|
||||
|
||||
<activity android:name=".GlobalApplication$CrashActivity"/>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,334 @@
|
||||
package cc.winboll.studio.androidxdemo;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.HorizontalScrollView;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class GlobalApplication extends Application {
|
||||
|
||||
private static Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
CrashHandler.getInstance().registerGlobal(this);
|
||||
CrashHandler.getInstance().registerPart(this);
|
||||
}
|
||||
|
||||
public static void write(InputStream input, OutputStream output) throws IOException {
|
||||
byte[] buf = new byte[1024 * 8];
|
||||
int len;
|
||||
while ((len = input.read(buf)) != -1) {
|
||||
output.write(buf, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(File file, byte[] data) throws IOException {
|
||||
File parent = file.getParentFile();
|
||||
if (parent != null && !parent.exists()) parent.mkdirs();
|
||||
|
||||
ByteArrayInputStream input = new ByteArrayInputStream(data);
|
||||
FileOutputStream output = new FileOutputStream(file);
|
||||
try {
|
||||
write(input, output);
|
||||
} finally {
|
||||
closeIO(input, output);
|
||||
}
|
||||
}
|
||||
|
||||
public static String toString(InputStream input) throws IOException {
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
write(input, output);
|
||||
try {
|
||||
return output.toString("UTF-8");
|
||||
} finally {
|
||||
closeIO(input, output);
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeIO(Closeable... closeables) {
|
||||
for (Closeable closeable : closeables) {
|
||||
try {
|
||||
if (closeable != null) closeable.close();
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
public static class CrashHandler {
|
||||
|
||||
public static final UncaughtExceptionHandler DEFAULT_UNCAUGHT_EXCEPTION_HANDLER = Thread.getDefaultUncaughtExceptionHandler();
|
||||
|
||||
private static CrashHandler sInstance;
|
||||
|
||||
private PartCrashHandler mPartCrashHandler;
|
||||
|
||||
public static CrashHandler getInstance() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new CrashHandler();
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public void registerGlobal(Context context) {
|
||||
registerGlobal(context, null);
|
||||
}
|
||||
|
||||
public void registerGlobal(Context context, String crashDir) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandlerImpl(context.getApplicationContext(), crashDir));
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
Thread.setDefaultUncaughtExceptionHandler(DEFAULT_UNCAUGHT_EXCEPTION_HANDLER);
|
||||
}
|
||||
|
||||
public void registerPart(Context context) {
|
||||
unregisterPart(context);
|
||||
mPartCrashHandler = new PartCrashHandler(context.getApplicationContext());
|
||||
MAIN_HANDLER.postAtFrontOfQueue(mPartCrashHandler);
|
||||
}
|
||||
|
||||
public void unregisterPart(Context context) {
|
||||
if (mPartCrashHandler != null) {
|
||||
mPartCrashHandler.isRunning.set(false);
|
||||
mPartCrashHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class PartCrashHandler implements Runnable {
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
public AtomicBoolean isRunning = new AtomicBoolean(true);
|
||||
|
||||
public PartCrashHandler(Context context) {
|
||||
this.mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (isRunning.get()) {
|
||||
try {
|
||||
Looper.loop();
|
||||
} catch (final Throwable e) {
|
||||
e.printStackTrace();
|
||||
if (isRunning.get()) {
|
||||
MAIN_HANDLER.post(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(mContext, e.toString(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (e instanceof RuntimeException) {
|
||||
throw (RuntimeException)e;
|
||||
} else {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class UncaughtExceptionHandlerImpl implements UncaughtExceptionHandler {
|
||||
|
||||
private static DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss");
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
private final File mCrashDir;
|
||||
|
||||
public UncaughtExceptionHandlerImpl(Context context, String crashDir) {
|
||||
this.mContext = context;
|
||||
this.mCrashDir = TextUtils.isEmpty(crashDir) ? new File(mContext.getExternalCacheDir(), "crash") : new File(crashDir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncaughtException(Thread thread, Throwable throwable) {
|
||||
try {
|
||||
|
||||
String log = buildLog(throwable);
|
||||
writeLog(log);
|
||||
|
||||
try {
|
||||
Intent intent = new Intent(mContext, CrashActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(Intent.EXTRA_TEXT, log);
|
||||
mContext.startActivity(intent);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
writeLog(e.toString());
|
||||
}
|
||||
|
||||
throwable.printStackTrace();
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
System.exit(0);
|
||||
|
||||
} catch (Throwable e) {
|
||||
if (DEFAULT_UNCAUGHT_EXCEPTION_HANDLER != null) DEFAULT_UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(thread, throwable);
|
||||
}
|
||||
}
|
||||
|
||||
private String buildLog(Throwable throwable) {
|
||||
String time = DATE_FORMAT.format(new Date());
|
||||
|
||||
String versionName = "unknown";
|
||||
long versionCode = 0;
|
||||
try {
|
||||
PackageInfo packageInfo = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0);
|
||||
versionName = packageInfo.versionName;
|
||||
versionCode = Build.VERSION.SDK_INT >= 28 ? packageInfo.getLongVersionCode() : packageInfo.versionCode;
|
||||
} catch (Throwable ignored) {}
|
||||
|
||||
LinkedHashMap<String, String> head = new LinkedHashMap<String, String>();
|
||||
head.put("Time Of Crash", time);
|
||||
head.put("Device", String.format("%s, %s", Build.MANUFACTURER, Build.MODEL));
|
||||
head.put("Android Version", String.format("%s (%d)", Build.VERSION.RELEASE, Build.VERSION.SDK_INT));
|
||||
head.put("App Version", String.format("%s (%d)", versionName, versionCode));
|
||||
head.put("Kernel", getKernel());
|
||||
head.put("Support Abis", Build.VERSION.SDK_INT >= 21 && Build.SUPPORTED_ABIS != null ? Arrays.toString(Build.SUPPORTED_ABIS): "unknown");
|
||||
head.put("Fingerprint", Build.FINGERPRINT);
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
for (String key : head.keySet()) {
|
||||
if (builder.length() != 0) builder.append("\n");
|
||||
builder.append(key);
|
||||
builder.append(" : ");
|
||||
builder.append(head.get(key));
|
||||
}
|
||||
|
||||
builder.append("\n\n");
|
||||
builder.append(Log.getStackTraceString(throwable));
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private void writeLog(String log) {
|
||||
String time = DATE_FORMAT.format(new Date());
|
||||
File file = new File(mCrashDir, "crash_" + time + ".txt");
|
||||
try {
|
||||
write(file, log.getBytes("UTF-8"));
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getKernel() {
|
||||
try {
|
||||
return GlobalApplication.toString(new FileInputStream("/proc/version")).trim();
|
||||
} catch (Throwable e) {
|
||||
return e.getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class CrashActivity extends Activity {
|
||||
|
||||
private String mLog;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setTheme(android.R.style.Theme_DeviceDefault);
|
||||
setTitle("App Crash");
|
||||
|
||||
mLog = getIntent().getStringExtra(Intent.EXTRA_TEXT);
|
||||
|
||||
ScrollView contentView = new ScrollView(this);
|
||||
contentView.setFillViewport(true);
|
||||
|
||||
HorizontalScrollView horizontalScrollView = new HorizontalScrollView(this);
|
||||
|
||||
TextView textView = new TextView(this);
|
||||
int padding = dp2px(16);
|
||||
textView.setPadding(padding, padding, padding, padding);
|
||||
textView.setText(mLog);
|
||||
textView.setTextIsSelectable(true);
|
||||
textView.setTypeface(Typeface.DEFAULT);
|
||||
textView.setLinksClickable(true);
|
||||
|
||||
horizontalScrollView.addView(textView);
|
||||
contentView.addView(horizontalScrollView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
|
||||
setContentView(contentView);
|
||||
}
|
||||
|
||||
private void restart() {
|
||||
Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
|
||||
if (intent != null) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
}
|
||||
finish();
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private static int dp2px(float dpValue) {
|
||||
final float scale = Resources.getSystem().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
menu.add(0, android.R.id.copy, 0, android.R.string.copy)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.copy:
|
||||
ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cm.setPrimaryClip(ClipData.newPlainText(getPackageName(), mLog));
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package cc.winboll.studio.androidxdemo;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
Toolbar toolbar=(Toolbar)findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1" />
|
||||
</vector>
|
||||
170
androidxdemo/src/main/res/drawable/ic_launcher_background.xml
Normal file
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillColor="#26A69A"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
</vector>
|
||||
38
androidxdemo/src/main/res/layout/activity_main.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1.0"
|
||||
android:gravity="center_vertical|center_horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="AndroidX Demo"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
BIN
androidxdemo/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
androidxdemo/src/main/res/mipmap-hdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
androidxdemo/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
androidxdemo/src/main/res/mipmap-mdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
androidxdemo/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
androidxdemo/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
androidxdemo/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
androidxdemo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
androidxdemo/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
BIN
androidxdemo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
6
androidxdemo/src/main/res/values/colors.xml
Normal file
@@ -0,0 +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>
|
||||
4
androidxdemo/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<resources>
|
||||
<string name="app_name">AndroidX Demo</string>
|
||||
|
||||
</resources>
|
||||
11
androidxdemo/src/main/res/values/styles.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
12
androidxdemo/src/stage/AndroidManifest.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools" >
|
||||
|
||||
<application>
|
||||
|
||||
<!-- Put flavor specific code here -->
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
6
androidxdemo/src/stage/res/values/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<!-- Put flavor specific strings here -->
|
||||
|
||||
</resources>
|
||||
@@ -29,7 +29,7 @@ android {
|
||||
// versionName 更新后需要手动设置
|
||||
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
|
||||
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
|
||||
versionName "2.1"
|
||||
versionName "15.0"
|
||||
if(true) {
|
||||
versionName = genVersionName("${versionName}")
|
||||
}
|
||||
@@ -46,25 +46,4 @@ android {
|
||||
dependencies {
|
||||
api project(':libappbase')
|
||||
api fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
// SSH
|
||||
implementation 'com.jcraft:jsch:0.1.55'
|
||||
// Html 解析
|
||||
implementation 'org.jsoup:jsoup:1.13.1'
|
||||
// 二维码类库
|
||||
implementation 'com.google.zxing:core:3.4.1'
|
||||
implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
|
||||
// 应用介绍页类库
|
||||
implementation 'io.github.medyo:android-about-page:2.0.0'
|
||||
// 吐司类库
|
||||
implementation 'com.github.getActivity:ToastUtils:10.5'
|
||||
// 网络连接类库
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.4.1'
|
||||
// Android 类库
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.viewpager:viewpager:1.0.0'
|
||||
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
|
||||
implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
|
||||
implementation 'androidx.fragment:fragment:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Sun Mar 09 09:15:39 HKT 2025
|
||||
stageCount=6
|
||||
#Sat Mar 15 15:30:02 HKT 2025
|
||||
stageCount=3
|
||||
libraryProject=libappbase
|
||||
baseVersion=2.1
|
||||
publishVersion=2.1.5
|
||||
baseVersion=15.0
|
||||
publishVersion=15.0.2
|
||||
buildCount=0
|
||||
baseBetaVersion=2.1.6
|
||||
baseBetaVersion=15.0.3
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
android:name=".App"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme"
|
||||
android:theme="@style/MyAppTheme"
|
||||
android:resizeableActivity="true">
|
||||
|
||||
<activity
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package cc.winboll.studio.appbase;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.widget.Toolbar;
|
||||
import cc.winboll.studio.appbase.R;
|
||||
import cc.winboll.studio.appbase.services.MainService;
|
||||
import cc.winboll.studio.appbase.services.TestDemoBindService;
|
||||
@@ -13,13 +14,11 @@ import cc.winboll.studio.appbase.services.TestDemoService;
|
||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.LogView;
|
||||
import cc.winboll.studio.libappbase.widgets.StatusWidget;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import android.content.ComponentName;
|
||||
import cc.winboll.studio.libappbase.sos.SOS;
|
||||
import cc.winboll.studio.libappbase.sos.SOSObject;
|
||||
import cc.winboll.studio.libappbase.utils.ToastUtils;
|
||||
import cc.winboll.studio.libappbase.widgets.StatusWidget;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
public class MainActivity extends Activity {
|
||||
|
||||
public static final String TAG = "MainActivity";
|
||||
|
||||
@@ -32,13 +31,16 @@ public class MainActivity extends AppCompatActivity {
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
Toolbar toolbar = findViewById(R.id.activitymainToolbar1);
|
||||
setSupportActionBar(toolbar);
|
||||
setActionBar(toolbar);
|
||||
|
||||
CheckBox cbIsDebugMode = findViewById(R.id.activitymainCheckBox1);
|
||||
cbIsDebugMode.setChecked(GlobalApplication.isDebuging());
|
||||
mLogView = findViewById(R.id.activitymainLogView1);
|
||||
|
||||
if (GlobalApplication.isDebuging()) { mLogView.start(); }
|
||||
if (GlobalApplication.isDebuging()) {
|
||||
mLogView.start();
|
||||
ToastUtils.show("LogView start.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -90,7 +92,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
public void onTestSOS(View view) {
|
||||
Intent intent = new Intent(this, TestDemoService.class);
|
||||
stopService(intent);
|
||||
if(App.isDebuging()) {
|
||||
if (App.isDebuging()) {
|
||||
SOS.sosToAppBaseBeta(this, TestDemoService.class.getName());
|
||||
} else {
|
||||
SOS.sosToAppBase(this, TestDemoService.class.getName());
|
||||
|
||||
@@ -5,7 +5,6 @@ package cc.winboll.studio.appbase.receivers;
|
||||
* @Date 2025/02/13 06:58:04
|
||||
* @Describe 主要广播接收器
|
||||
*/
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -16,15 +15,15 @@ import cc.winboll.studio.appbase.services.MainService;
|
||||
import cc.winboll.studio.appbase.widgets.APPNewsWidget;
|
||||
import cc.winboll.studio.libappbase.AppUtils;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import cc.winboll.studio.libappbase.sos.APPModel;
|
||||
import cc.winboll.studio.libappbase.sos.SOS;
|
||||
import cc.winboll.studio.libappbase.sos.SOSObject;
|
||||
import cc.winboll.studio.libappbase.sos.WinBoll;
|
||||
import cc.winboll.studio.libappbase.utils.ToastUtils;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import cc.winboll.studio.libappbase.sos.WinBoll;
|
||||
import cc.winboll.studio.libappbase.sos.APPModel;
|
||||
import cc.winboll.studio.libappbase.sos.SOS;
|
||||
import cc.winboll.studio.libappbase.sos.SOSObject;
|
||||
|
||||
public class MainReceiver extends BroadcastReceiver {
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
<android.widget.Toolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/activitymainToolbar1"/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="AppTheme" parent="APPBaseTheme">
|
||||
<style name="MyAppTheme" parent="APPBaseTheme">
|
||||
<item name="attrColorPrimary">@color/colorPrimary</item>
|
||||
<item name="themeGlobalCrashActivity">@style/MyGlobalCrashActivityTheme</item>
|
||||
</style>
|
||||
|
||||
@@ -29,7 +29,7 @@ android {
|
||||
// versionName 更新后需要手动设置
|
||||
// 项目模块目录的 build.gradle 文件的 stageCount=0
|
||||
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
|
||||
versionName "9.4"
|
||||
versionName "15.0"
|
||||
if(true) {
|
||||
versionName = genVersionName("${versionName}")
|
||||
}
|
||||
@@ -41,38 +41,26 @@ android {
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_17
|
||||
targetCompatibility JavaVersion.VERSION_17
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':libapputils')
|
||||
api fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'cc.winboll.studio:libappbase:15.0.3'
|
||||
|
||||
// SSH
|
||||
implementation 'com.jcraft:jsch:0.1.55'
|
||||
// Html 解析
|
||||
implementation 'org.jsoup:jsoup:1.13.1'
|
||||
// 二维码类库
|
||||
implementation 'com.google.zxing:core:3.4.1'
|
||||
implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
|
||||
// 应用介绍页类库
|
||||
implementation 'io.github.medyo:android-about-page:2.0.0'
|
||||
// 吐司类库
|
||||
implementation 'com.github.getActivity:ToastUtils:10.5'
|
||||
|
||||
// 网络连接类库
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.4.1'
|
||||
//implementation 'com.squareup.okhttp3:okhttp:4.4.1'
|
||||
|
||||
// Android 类库
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.viewpager:viewpager:1.0.0'
|
||||
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
|
||||
implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
|
||||
implementation 'androidx.fragment:fragment:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
// Html 解析
|
||||
//implementation 'org.jsoup:jsoup:1.13.1'
|
||||
|
||||
implementation 'cc.winboll.studio:libappbase:2.1.5'
|
||||
// SSH
|
||||
//implementation 'com.jcraft:jsch:0.1.55'
|
||||
|
||||
// 应用介绍页类库
|
||||
//implementation 'io.github.medyo:android-about-page:2.0.0'
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Sun Mar 09 09:34:16 HKT 2025
|
||||
stageCount=5
|
||||
#Tue Mar 18 08:44:48 HKT 2025
|
||||
stageCount=1
|
||||
libraryProject=libapputils
|
||||
baseVersion=9.4
|
||||
publishVersion=9.4.4
|
||||
baseVersion=15.0
|
||||
publishVersion=15.0.0
|
||||
buildCount=0
|
||||
baseBetaVersion=9.4.5
|
||||
baseBetaVersion=15.0.1
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package cc.winboll.studio.apputils;
|
||||
|
||||
import cc.winboll.studio.apputils.R;
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -10,11 +12,10 @@ import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import cc.winboll.studio.apputils.R;
|
||||
import android.widget.Toolbar;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.LogView;
|
||||
import cc.winboll.studio.libappbase.utils.ToastUtils;
|
||||
import cc.winboll.studio.libapputils.activities.AssetsHtmlActivity;
|
||||
import cc.winboll.studio.libapputils.activities.LogActivity;
|
||||
import cc.winboll.studio.libapputils.activities.QRCodeDecodeActivity;
|
||||
@@ -24,11 +25,10 @@ import cc.winboll.studio.libapputils.app.WinBollActivityManager;
|
||||
import cc.winboll.studio.libapputils.bean.APPInfo;
|
||||
import cc.winboll.studio.libapputils.view.AboutView;
|
||||
import cc.winboll.studio.libapputils.view.YesNoAlertDialog;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
final public class MainActivity extends AppCompatActivity implements IWinBollActivity {
|
||||
final public class MainActivity extends Activity implements IWinBollActivity {
|
||||
|
||||
public static final String TAG = "MainActivity";
|
||||
|
||||
@@ -38,7 +38,7 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct
|
||||
LogView mLogView;
|
||||
|
||||
@Override
|
||||
public AppCompatActivity getActivity() {
|
||||
public Activity getActivity() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -91,12 +91,12 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct
|
||||
|
||||
// 初始化工具栏
|
||||
mToolbar = findViewById(R.id.activitymainToolbar1);
|
||||
setSupportActionBar(mToolbar);
|
||||
setActionBar(mToolbar);
|
||||
if (isEnableDisplayHomeAsUp()) {
|
||||
// 显示后退按钮
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
getSupportActionBar().setSubtitle(getTag());
|
||||
getActionBar().setSubtitle(getTag());
|
||||
|
||||
checkResolveActivity();
|
||||
archiveInstance();
|
||||
@@ -281,7 +281,7 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct
|
||||
WinBollActivityManager.getInstance(this).startWinBollActivity(this, LogActivity.class);
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.item_exitdebug) {
|
||||
AboutView.setApp2NormalMode(this);
|
||||
//AboutView.setApp2NormalMode(this);
|
||||
return true;
|
||||
} else if (item.getItemId() == android.R.id.home) {
|
||||
WinBollActivityManager.getInstance(this).finish(this);
|
||||
@@ -332,6 +332,12 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct
|
||||
WinBollActivityManager.getInstance(this).startWinBollActivity(this, intent, AssetsHtmlActivity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mLogView.start();
|
||||
}
|
||||
|
||||
/*@Override
|
||||
protected void onActivithyResult(int requestCode, int resultCode, Intent data) {
|
||||
switch (requestCode) {
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
package cc.winboll.studio.apputils;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import cc.winboll.studio.libapputils.app.IWinBollActivity;
|
||||
import cc.winboll.studio.libapputils.bean.APPInfo;
|
||||
import cc.winboll.studio.libapputils.view.StringToQrCodeView;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@QQ.COM
|
||||
* @Date 2025/01/17 19:50:46
|
||||
*/
|
||||
public class TestStringToQrCodeViewActivity extends AppCompatActivity implements IWinBollActivity {
|
||||
import cc.winboll.studio.apputils.R;
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toolbar;
|
||||
import cc.winboll.studio.libapputils.app.IWinBollActivity;
|
||||
import cc.winboll.studio.libapputils.bean.APPInfo;
|
||||
import cc.winboll.studio.libapputils.view.StringToQrCodeView;
|
||||
|
||||
public class TestStringToQrCodeViewActivity extends Activity implements IWinBollActivity {
|
||||
|
||||
public static final String TAG = "TestStringToQrCodeViewActivity";
|
||||
|
||||
StringToQrCodeView mStringToQrCodeView;
|
||||
|
||||
@Override
|
||||
public AppCompatActivity getActivity() {
|
||||
public Activity getActivity() {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
<android.widget.Toolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/activitymainToolbar1"/>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
<android.widget.Toolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/activityteststringtoqrcodeviewToolbar1"/>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:background="#FF36B5B3">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
<android.widget.Toolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/activitytestwinbollToolbar1"/>
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/shape_gradient"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="10dp">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:src="@drawable/ic_launcher"/>
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10dp"
|
||||
android:textColor="#FF000000"
|
||||
android:textSize="16sp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -3,14 +3,11 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/item_testwinboll"
|
||||
android:title="TestWinBollActivity"
|
||||
app:showAsAction="ifRoom"/>
|
||||
android:title="TestWinBollActivity"/>
|
||||
<item
|
||||
android:id="@+id/item_teststringtoqrcodeview"
|
||||
android:title="TestStringToQrCodeViewActivity"
|
||||
app:showAsAction="ifRoom"/>
|
||||
android:title="TestStringToQrCodeViewActivity"/>
|
||||
<item
|
||||
android:id="@+id/item_testqrcodedecodeactivity"
|
||||
android:title="TestQRCodeDecodeActivity"
|
||||
app:showAsAction="ifRoom"/>
|
||||
android:title="TestQRCodeDecodeActivity"/>
|
||||
</menu>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="MyAppTheme" parent="APPBaseTheme">
|
||||
<item name="attrColorPrimary">@color/colorPrimary</item>
|
||||
<item name="themeGlobalCrashActivity">@style/MyGlobalCrashActivityTheme</item>
|
||||
</style>
|
||||
|
||||
<style name="GlobalCrashActivityTheme" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar">
|
||||
<item name="colorTittle">@color/colorAccent</item>
|
||||
<item name="colorTittleBackgound">@color/colorPrimary</item>
|
||||
<item name="colorText">@color/colorAccent</item>
|
||||
<item name="colorTextBackgound">@color/colorPrimaryDark</item>
|
||||
<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>
|
||||
|
||||
19
gradle.properties-android-demo
Normal file
@@ -0,0 +1,19 @@
|
||||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2048m
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app"s APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=false
|
||||
# Automatically convert third-party libraries to use AndroidX
|
||||
android.enableJetifier=false
|
||||
@@ -6,7 +6,7 @@
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx4096m
|
||||
org.gradle.jvmargs=-Xmx2048m
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
@@ -17,10 +17,3 @@ org.gradle.jvmargs=-Xmx4096m
|
||||
android.useAndroidX=true
|
||||
# Automatically convert third-party libraries to use AndroidX
|
||||
android.enableJetifier=true
|
||||
|
||||
org.gradle.caching=true
|
||||
|
||||
android.disableAutomaticComponentCreation=true
|
||||
|
||||
android.injected.testOnly=false
|
||||
|
||||
@@ -21,26 +21,4 @@ android {
|
||||
|
||||
dependencies {
|
||||
api fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
// SSH
|
||||
implementation 'com.jcraft:jsch:0.1.55'
|
||||
// Html 解析
|
||||
implementation 'org.jsoup:jsoup:1.13.1'
|
||||
// 二维码类库
|
||||
implementation 'com.google.zxing:core:3.4.1'
|
||||
implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
|
||||
// 应用介绍页类库
|
||||
implementation 'io.github.medyo:android-about-page:2.0.0'
|
||||
// 吐司类库
|
||||
implementation 'com.github.getActivity:ToastUtils:10.5'
|
||||
// 网络连接类库
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.4.1'
|
||||
|
||||
// Android 类库
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.viewpager:viewpager:1.0.0'
|
||||
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
|
||||
implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
|
||||
implementation 'androidx.fragment:fragment:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Sun Mar 09 09:15:24 HKT 2025
|
||||
stageCount=6
|
||||
#Sat Mar 15 15:29:07 HKT 2025
|
||||
stageCount=3
|
||||
libraryProject=libappbase
|
||||
baseVersion=2.1
|
||||
publishVersion=2.1.5
|
||||
baseVersion=15.0
|
||||
publishVersion=15.0.2
|
||||
buildCount=0
|
||||
baseBetaVersion=2.1.6
|
||||
baseBetaVersion=15.0.3
|
||||
|
||||
@@ -6,17 +6,13 @@ package cc.winboll.studio.libappbase;
|
||||
* @Describe 全局应用类
|
||||
*/
|
||||
import android.app.Application;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
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;
|
||||
import cc.winboll.studio.libappbase.utils.ToastUtils;
|
||||
|
||||
public class GlobalApplication extends Application {
|
||||
|
||||
@@ -78,8 +74,8 @@ public class GlobalApplication extends Application {
|
||||
ToastUtils.init(this);
|
||||
// 设置 Toast 布局样式
|
||||
//ToastUtils.setView(R.layout.toast_custom_view);
|
||||
ToastUtils.setStyle(new WhiteToastStyle());
|
||||
ToastUtils.setGravity(Gravity.BOTTOM, 0, 200);
|
||||
//ToastUtils.setStyle(new WhiteToastStyle());
|
||||
//ToastUtils.setGravity(Gravity.BOTTOM, 0, 200);
|
||||
}
|
||||
|
||||
public static String getAppName(Context context) {
|
||||
|
||||
@@ -21,11 +21,9 @@ 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 {
|
||||
public final class GlobalCrashActivity extends Activity implements MenuItem.OnMenuItemClickListener {
|
||||
|
||||
private static final int MENUITEM_COPY = 0;
|
||||
private static final int MENUITEM_RESTART = 1;
|
||||
@@ -47,10 +45,10 @@ public final class GlobalCrashActivity extends AppCompatActivity implements Menu
|
||||
setContentView(R.layout.activity_globalcrash);
|
||||
mGlobalCrashReportView = findViewById(R.id.activityglobalcrashGlobalCrashReportView1);
|
||||
mGlobalCrashReportView.setReport(mLog);
|
||||
setSupportActionBar(mGlobalCrashReportView.getToolbar());
|
||||
setActionBar(mGlobalCrashReportView.getToolbar());
|
||||
|
||||
getSupportActionBar().setTitle(CrashHandler.TITTLE);
|
||||
getSupportActionBar().setSubtitle(GlobalApplication.getAppName(getApplicationContext()));
|
||||
getActionBar().setTitle(CrashHandler.TITTLE);
|
||||
getActionBar().setSubtitle(GlobalApplication.getAppName(getApplicationContext()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,8 +15,8 @@ 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;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
public class GlobalCrashReportView extends LinearLayout {
|
||||
|
||||
|
||||
@@ -16,16 +16,15 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.R;
|
||||
import cc.winboll.studio.libappbase.views.HorizontalListView;
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -51,7 +50,7 @@ public class LogView extends RelativeLayout {
|
||||
Spinner mLogLevelSpinner;
|
||||
ArrayAdapter<CharSequence> mLogLevelSpinnerAdapter;
|
||||
// 标签列表
|
||||
RecyclerView recyclerView;
|
||||
HorizontalListView mListViewTags;
|
||||
|
||||
public LogView(Context context) {
|
||||
super(context);
|
||||
@@ -190,11 +189,9 @@ public class LogView extends RelativeLayout {
|
||||
cbALLTAG.setChecked(isAllSelect);
|
||||
|
||||
// 加载标签表
|
||||
recyclerView = findViewById(cc.winboll.studio.libappbase.R.id.viewlogRecyclerView1);
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
mTAGListAdapter = new TAGListAdapter(mapTAGList);
|
||||
recyclerView.setAdapter(mTAGListAdapter);
|
||||
mListViewTags = findViewById(cc.winboll.studio.libappbase.R.id.tags_listview);
|
||||
mTAGListAdapter = new TAGListAdapter(mContext, mapTAGList);
|
||||
mListViewTags.setAdapter(mTAGListAdapter);
|
||||
|
||||
// 可以添加点击监听器来处理勾选框状态变化后的逻辑,比如获取当前勾选情况等
|
||||
mTAGListAdapter.notifyDataSetChanged();
|
||||
@@ -305,16 +302,33 @@ public class LogView extends RelativeLayout {
|
||||
}
|
||||
|
||||
|
||||
public class TAGListAdapter extends RecyclerView.Adapter<TAGListAdapter.ViewHolder> {
|
||||
public class TAGListAdapter extends BaseAdapter {
|
||||
|
||||
private Context context;
|
||||
private Map<String, Boolean> mapOrigin;
|
||||
private List<TAGItemModel> itemList;
|
||||
|
||||
public TAGListAdapter(Map<String, Boolean> map) {
|
||||
public TAGListAdapter(Context context, Map<String, Boolean> map) {
|
||||
this.context = context;
|
||||
mapOrigin = map;
|
||||
loadMap(mapOrigin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return itemList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int p) {
|
||||
return itemList.get(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int p) {
|
||||
return p;
|
||||
}
|
||||
|
||||
void loadMap(Map<String, Boolean> map) {
|
||||
itemList = new ArrayList<TAGItemModel>();
|
||||
for (Map.Entry<String, Boolean> entry : map.entrySet()) {
|
||||
@@ -330,15 +344,19 @@ public class LogView extends RelativeLayout {
|
||||
super.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_logtag, parent, false);
|
||||
return new ViewHolder(view);
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
ViewHolder holder;
|
||||
if (convertView == null) {
|
||||
convertView = LayoutInflater.from(context).inflate(R.layout.item_logtag, parent, false);
|
||||
holder = new ViewHolder();
|
||||
holder.tvText = convertView.findViewById(R.id.viewlogtagTextView1);
|
||||
holder.cbChecked = convertView.findViewById(R.id.viewlogtagCheckBox1);
|
||||
convertView.setTag(holder);
|
||||
} else {
|
||||
holder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
final TAGItemModel item = itemList.get(position);
|
||||
holder.tvText.setText(item.getTag());
|
||||
holder.cbChecked.setChecked(item.isChecked());
|
||||
@@ -349,22 +367,13 @@ public class LogView extends RelativeLayout {
|
||||
LogUtils.setTAGListEnable(item.getTag(), ((CheckBox)v).isChecked());
|
||||
}
|
||||
});
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return itemList.size();
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||
public class ViewHolder {
|
||||
TextView tvText;
|
||||
CheckBox cbChecked;
|
||||
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
tvText = itemView.findViewById(R.id.viewlogtagTextView1);
|
||||
cbChecked = itemView.findViewById(R.id.viewlogtagCheckBox1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package cc.winboll.studio.libappbase.utils;
|
||||
import android.content.Context;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/03/12 12:02:31
|
||||
*/
|
||||
public class ToastUtils {
|
||||
|
||||
public static final String TAG = "ToastUtils";
|
||||
|
||||
volatile static ToastUtils _ToastUtils;
|
||||
Context mContext;
|
||||
|
||||
ToastUtils() {
|
||||
}
|
||||
|
||||
synchronized static ToastUtils getInstance() {
|
||||
if (_ToastUtils == null) {
|
||||
_ToastUtils = new ToastUtils();
|
||||
}
|
||||
return _ToastUtils;
|
||||
}
|
||||
|
||||
public static void init(Context context) {
|
||||
getInstance().mContext = context;
|
||||
}
|
||||
|
||||
public static void show(String message) {
|
||||
Toast.makeText(getInstance().mContext, message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package cc.winboll.studio.libappbase.views;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/03/12 12:29:01
|
||||
* @Describe 水平布局的 ListView
|
||||
*/
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ListView;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
|
||||
public class HorizontalListView extends ListView {
|
||||
public static final String TAG = "HorizontalListView";
|
||||
|
||||
public HorizontalListView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public HorizontalListView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public HorizontalListView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
// @Override
|
||||
// protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
// super.onLayout(changed, l, t, r, b);
|
||||
// int childCount = getChildCount();
|
||||
// int left = getPaddingLeft();
|
||||
// // 获取HorizontalListView的高度
|
||||
// int viewHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
|
||||
// for (int i = 0; i < childCount; i++) {
|
||||
// View child = getChildAt(i);
|
||||
// int width = child.getMeasuredWidth();
|
||||
// int height = child.getMeasuredHeight();
|
||||
// // 计算子项在垂直方向上的居中偏移量
|
||||
// int verticalOffset = (viewHeight - height) / 2;
|
||||
// // 设置子视图的位置,实现水平布局并垂直居中
|
||||
// child.layout(left, getPaddingTop() + verticalOffset, left + width, getPaddingTop() + verticalOffset + height);
|
||||
// left += width;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
super.onLayout(changed, l, t, r, b);
|
||||
int childCount = getChildCount();
|
||||
int left = getPaddingLeft();
|
||||
int viewHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
|
||||
LogUtils.d(TAG, String.format("HorizontalListView的高度 %d", viewHeight));
|
||||
int verticalOffset = 20;
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View child = getChildAt(i);
|
||||
// 计算每个子视图的宽度和高度
|
||||
int width = child.getMeasuredWidth();
|
||||
int height = child.getMeasuredHeight();
|
||||
//LogUtils.d(TAG, String.format("child : width %d , height %d", width, height));
|
||||
// 设置子视图的位置,实现水平布局
|
||||
|
||||
child.layout(left, verticalOffset, left + width, verticalOffset + height);
|
||||
left += width;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
|
||||
int newHeightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
|
||||
//super.onMeasure(widthMeasureSpec, newHeightMeasureSpec);
|
||||
int newWidthMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
|
||||
//LogUtils.d(TAG, String.format("newWidthMeasureSpec %d, newHeightMeasureSpec %d", newWidthMeasureSpec, newHeightMeasureSpec));
|
||||
super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec);
|
||||
|
||||
// ViewGroup.LayoutParams params = getLayoutParams();
|
||||
// params.width = getMeasuredWidth();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ import android.widget.RemoteViews;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.R;
|
||||
import cc.winboll.studio.libappbase.utils.ServiceUtils;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
import cc.winboll.studio.libappbase.utils.ToastUtils;
|
||||
|
||||
public class StatusWidget extends AppWidgetProvider {
|
||||
|
||||
@@ -35,6 +35,7 @@ public class StatusWidget extends AppWidgetProvider {
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
super.onReceive(context, intent);
|
||||
if (intent.getAction().equals(ACTION_STATUS_UPDATE)) {
|
||||
ToastUtils.show("Test");
|
||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
|
||||
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, StatusWidget.class));
|
||||
for (int appWidgetId : appWidgetIds) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import cc.winboll.studio.libappbase.utils.ToastUtils;
|
||||
|
||||
public class StatusWidgetClickListener extends BroadcastReceiver {
|
||||
|
||||
|
||||
22
libappbase/src/main/res/layout/item_logtag.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?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="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#FFEEEEEE">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:id="@+id/viewlogtagTextView1"/>
|
||||
|
||||
<CheckBox
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:id="@+id/viewlogtagCheckBox1"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/viewglobalcrashreportLinearLayout1">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
<android.widget.Toolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/viewglobalcrashreportToolbar1"/>
|
||||
|
||||
@@ -69,10 +69,10 @@
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:background="@drawable/bg_shadow"
|
||||
android:layout_below="@+id/viewlogRelativeLayoutToolbar"
|
||||
android:id="@+id/viewlogLinearLayout1"
|
||||
android:gravity="center_vertical">
|
||||
android:gravity="center_vertical"
|
||||
android:background="#FFC0F4C2">
|
||||
|
||||
<CheckBox
|
||||
android:layout_width="wrap_content"
|
||||
@@ -80,14 +80,21 @@
|
||||
android:text="ALL"
|
||||
android:id="@+id/viewlogCheckBox1"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
<HorizontalScrollView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/view_border"
|
||||
android:id="@+id/viewlogRecyclerView1"
|
||||
android:layout_height="match_parent"
|
||||
android:scrollbars="none"
|
||||
android:layout_weight="1.0"
|
||||
android:layout_marginRight="5dp"
|
||||
android:padding="2dp"/>
|
||||
android:background="#FF97F2E3">
|
||||
|
||||
<cc.winboll.studio.libappbase.views.HorizontalListView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/view_border"
|
||||
android:id="@+id/tags_listview"
|
||||
android:paddingLeft="10dp"/>
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardBackgroundColor="#F5F5F5"
|
||||
app:cardElevation="4dp"
|
||||
app:cardCornerRadius="4dp"
|
||||
android:id="@+id/listviewauthinfoCardView1"
|
||||
android:layout_marginLeft="0dp"
|
||||
android:layout_marginRight="5dp">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:id="@+id/viewlogtagTextView1"/>
|
||||
|
||||
<CheckBox
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:id="@+id/viewlogtagCheckBox1"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="APPBaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<style name="APPBaseTheme" parent="@android:style/Theme.Holo.Light.NoActionBar">
|
||||
<item name="themeGlobalCrashActivity">@style/GlobalCrashActivityTheme</item>
|
||||
</style>
|
||||
|
||||
|
||||
@@ -21,28 +21,18 @@ android {
|
||||
|
||||
dependencies {
|
||||
api fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'cc.winboll.studio:libappbase:15.0.3'
|
||||
|
||||
// SSH
|
||||
implementation 'com.jcraft:jsch:0.1.55'
|
||||
// Html 解析
|
||||
implementation 'org.jsoup:jsoup:1.13.1'
|
||||
// 二维码类库
|
||||
implementation 'com.google.zxing:core:3.4.1'
|
||||
implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
|
||||
// 应用介绍页类库
|
||||
implementation 'io.github.medyo:android-about-page:2.0.0'
|
||||
// 吐司类库
|
||||
implementation 'com.github.getActivity:ToastUtils:10.5'
|
||||
|
||||
// 网络连接类库
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.4.1'
|
||||
//implementation 'com.squareup.okhttp3:okhttp:4.4.1'
|
||||
|
||||
// Android 类库
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.viewpager:viewpager:1.0.0'
|
||||
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
|
||||
implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
|
||||
implementation 'androidx.fragment:fragment:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
// Html 解析
|
||||
//implementation 'org.jsoup:jsoup:1.13.1'
|
||||
|
||||
implementation 'cc.winboll.studio:libappbase:2.1.5'
|
||||
// SSH
|
||||
//implementation 'com.jcraft:jsch:0.1.55'
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Sun Mar 09 09:34:16 HKT 2025
|
||||
stageCount=5
|
||||
#Tue Mar 18 08:44:48 HKT 2025
|
||||
stageCount=1
|
||||
libraryProject=libapputils
|
||||
baseVersion=9.4
|
||||
publishVersion=9.4.4
|
||||
baseVersion=15.0
|
||||
publishVersion=15.0.0
|
||||
buildCount=0
|
||||
baseBetaVersion=9.4.5
|
||||
baseBetaVersion=15.0.1
|
||||
|
||||
@@ -5,20 +5,20 @@ package cc.winboll.studio.libapputils.activities;
|
||||
* @Date 2024/07/14 13:20:33
|
||||
* @Describe 应用介绍页
|
||||
*/
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.LinearLayout;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import android.widget.Toolbar;
|
||||
import cc.winboll.studio.libapputils.app.IWinBollActivity;
|
||||
import cc.winboll.studio.libapputils.app.WinBollActivityManager;
|
||||
import cc.winboll.studio.libapputils.bean.APPInfo;
|
||||
import cc.winboll.studio.libapputils.view.AboutView;
|
||||
|
||||
final public class AboutActivity extends AppCompatActivity implements IWinBollActivity {
|
||||
final public class AboutActivity extends Activity implements IWinBollActivity {
|
||||
|
||||
public static final String TAG = "AboutActivity";
|
||||
|
||||
@@ -28,7 +28,7 @@ final public class AboutActivity extends AppCompatActivity implements IWinBollAc
|
||||
APPInfo mAPPInfo;
|
||||
|
||||
@Override
|
||||
public AppCompatActivity getActivity() {
|
||||
public Activity getActivity() {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,23 +5,23 @@ package cc.winboll.studio.libapputils.activities;
|
||||
* @Date 2025/01/03 11:02:49
|
||||
* @Describe 一个可以浏览随 APP 附带的 Html 文档的窗口
|
||||
*/
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.widget.Toolbar;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import cc.winboll.studio.libapputils.app.IWinBollActivity;
|
||||
import cc.winboll.studio.libapputils.bean.APPInfo;
|
||||
import cc.winboll.studio.libapputils.view.SimpleWebView;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class AssetsHtmlActivity extends AppCompatActivity implements IWinBollActivity {
|
||||
public class AssetsHtmlActivity extends Activity implements IWinBollActivity {
|
||||
|
||||
public static final String TAG = "AssetsHtmlActivity";
|
||||
|
||||
@@ -35,7 +35,7 @@ public class AssetsHtmlActivity extends AppCompatActivity implements IWinBollAct
|
||||
String mszHtmlFileName;
|
||||
|
||||
@Override
|
||||
public AppCompatActivity getActivity() {
|
||||
public Activity getActivity() {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,24 +5,23 @@ package cc.winboll.studio.libapputils.activities;
|
||||
* @Date 2025/03/08 00:19:39
|
||||
* @Describe LogActivity
|
||||
*/
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
||||
import android.widget.Toolbar;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.LogView;
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import cc.winboll.studio.libapputils.app.IWinBollActivity;
|
||||
import cc.winboll.studio.libapputils.bean.APPInfo;
|
||||
|
||||
public class LogActivity extends AppCompatActivity implements IWinBollActivity {
|
||||
public class LogActivity extends Activity implements IWinBollActivity {
|
||||
|
||||
public static final String TAG = "LogActivity";
|
||||
|
||||
LogView mLogView;
|
||||
|
||||
@Override
|
||||
public AppCompatActivity getActivity() {
|
||||
public Activity getActivity() {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,15 +5,13 @@ package cc.winboll.studio.libapputils.activities;
|
||||
* @Date 2025/01/18 10:32:21
|
||||
* @Describe 二维码扫码解码窗口
|
||||
*/
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.widget.TextView;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import android.widget.Toolbar;
|
||||
import cc.winboll.studio.libapputils.app.IWinBollActivity;
|
||||
import cc.winboll.studio.libapputils.bean.APPInfo;
|
||||
import com.google.zxing.ResultPoint;
|
||||
@@ -22,7 +20,7 @@ import com.journeyapps.barcodescanner.BarcodeResult;
|
||||
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
|
||||
import java.util.List;
|
||||
|
||||
public class QRCodeDecodeActivity extends AppCompatActivity implements IWinBollActivity {
|
||||
public class QRCodeDecodeActivity extends Activity implements IWinBollActivity {
|
||||
|
||||
public static final String TAG = "QRCodeDecodeActivity";
|
||||
|
||||
@@ -33,7 +31,7 @@ public class QRCodeDecodeActivity extends AppCompatActivity implements IWinBollA
|
||||
DecoratedBarcodeView barcodeView;
|
||||
|
||||
@Override
|
||||
public AppCompatActivity getActivity() {
|
||||
public Activity getActivity() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -70,14 +68,15 @@ public class QRCodeDecodeActivity extends AppCompatActivity implements IWinBollA
|
||||
resultTextView = findViewById(R.id.activityqrcodedecodeTextView1);
|
||||
barcodeView = findViewById(R.id.activityqrcodedecodeDecoratedBarcodeView1);
|
||||
// 请求相机权限
|
||||
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(this,
|
||||
new String[]{android.Manifest.permission.CAMERA},
|
||||
REQUEST_CAMERA_PERMISSION);
|
||||
} else {
|
||||
// if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)
|
||||
// != PackageManager.PERMISSION_GRANTED) {
|
||||
// ActivityCompat.requestPermissions(this,
|
||||
// new String[]{android.Manifest.permission.CAMERA},
|
||||
// REQUEST_CAMERA_PERMISSION);
|
||||
// } else {
|
||||
// startScanning();
|
||||
// }
|
||||
startScanning();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ package cc.winboll.studio.libapputils.app;
|
||||
* @Date 2025/03/08 00:15:36
|
||||
* @Describe WinBoll 活动窗口通用接口
|
||||
*/
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.app.Activity;
|
||||
import android.widget.Toolbar;
|
||||
import cc.winboll.studio.libapputils.bean.APPInfo;
|
||||
|
||||
public interface IWinBollActivity {
|
||||
@@ -14,7 +14,7 @@ public interface IWinBollActivity {
|
||||
public static final String TAG = "IWinBollActivity";
|
||||
|
||||
// 获取当前具有 IWinBoll 特征的 AppCompatActivity 活动窗口
|
||||
abstract public AppCompatActivity getActivity();
|
||||
abstract public Activity getActivity();
|
||||
abstract public APPInfo getAppInfo();
|
||||
abstract public String getTag();
|
||||
abstract public Toolbar initToolBar();
|
||||
|
||||
@@ -9,7 +9,7 @@ import android.app.Application;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import cc.winboll.studio.libappbase.utils.ToastUtils;
|
||||
|
||||
public class MyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ package cc.winboll.studio.libapputils.app;
|
||||
* https://blog.csdn.net/qq_29364417/article/details/109379915?app_version=6.4.2&code=app_1562916241&csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22109379915%22%2C%22source%22%3A%22weixin_38986226%22%7D&uLinkId=usr1mkqgl919blen&utm_source=app
|
||||
*/
|
||||
import android.app.ActivityManager;
|
||||
import android.app.TaskStackBuilder;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import androidx.core.app.TaskStackBuilder;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
@@ -8,8 +8,8 @@ import android.content.ServiceConnection;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.IBinder;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.utils.ToastUtils;
|
||||
import cc.winboll.studio.libapputils.util.ServiceUtils;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@QQ.COM
|
||||
|
||||
@@ -9,7 +9,6 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.AssetManager;
|
||||
import android.net.Uri;
|
||||
import androidx.core.content.FileProvider;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@@ -23,6 +22,7 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import android.support.v4.content.FileProvider;
|
||||
|
||||
public class FileUtils {
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ package cc.winboll.studio.libapputils.view;
|
||||
* @Date 2024/08/12 14:38:03
|
||||
* @Describe AboutView
|
||||
*/
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -18,22 +19,19 @@ import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import cc.winboll.studio.libappbase.utils.ToastUtils;
|
||||
import cc.winboll.studio.libapputils.app.AppVersionUtils;
|
||||
import cc.winboll.studio.libapputils.app.WinBollActivityManager;
|
||||
import cc.winboll.studio.libapputils.bean.APPInfo;
|
||||
import cc.winboll.studio.libapputils.bean.DebugBean;
|
||||
import cc.winboll.studio.libapputils.util.PrefUtils;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import java.io.IOException;
|
||||
import mehdi.sakout.aboutpage.AboutPage;
|
||||
import mehdi.sakout.aboutpage.Element;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.Credentials;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
//import okhttp3.Call;
|
||||
//import okhttp3.Callback;
|
||||
//import okhttp3.Credentials;
|
||||
//import okhttp3.OkHttpClient;
|
||||
//import okhttp3.Request;
|
||||
//import okhttp3.Response;
|
||||
|
||||
public class AboutView extends LinearLayout {
|
||||
|
||||
@@ -45,7 +43,7 @@ public class AboutView extends LinearLayout {
|
||||
APPInfo mAPPInfo;
|
||||
|
||||
WinBollServiceStatusView mWinBollServiceStatusView;
|
||||
OnRequestDevUserInfoAutofillListener mOnRequestDevUserInfoAutofillListener;
|
||||
//OnRequestDevUserInfoAutofillListener mOnRequestDevUserInfoAutofillListener;
|
||||
String mszAppName = "";
|
||||
String mszAppAPKFolderName = "";
|
||||
String mszAppAPKName = "";
|
||||
@@ -97,57 +95,58 @@ public class AboutView extends LinearLayout {
|
||||
typedArray.recycle();
|
||||
return appInfo;
|
||||
}
|
||||
void initView(Context context) {}
|
||||
|
||||
void initView(Context context) {
|
||||
mszAppName = mAPPInfo.getAppName();
|
||||
mszAppAPKFolderName = mAPPInfo.getAppAPKFolderName();
|
||||
mszAppAPKName = mAPPInfo.getAppAPKName();
|
||||
mszAppGitName = mAPPInfo.getAppGitName();
|
||||
mszAppDescription = mAPPInfo.getAppDescription();
|
||||
mnAppIcon = mAPPInfo.getAppIcon();
|
||||
|
||||
mszWinBollServerHost = GlobalApplication.isDebuging() ? "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";
|
||||
mszHomePage = mszWinBollServerHost + "/studio/details.php?app=" + mszAppAPKFolderName;
|
||||
if(mAPPInfo.getAppGitAPPBranch().equals("")) {
|
||||
mszGitea = "https://gitea.winboll.cc/" + mAPPInfo.getAppGitOwner() + "/" + mszAppGitName;
|
||||
} else {
|
||||
mszGitea = "https://gitea.winboll.cc/" + mAPPInfo.getAppGitOwner() + "/" + mszAppGitName + "/src/branch/" + mAPPInfo.getAppGitAPPBranch() + "/" + mAPPInfo.getAppGitAPPSubProjectFolder();
|
||||
}
|
||||
|
||||
if (GlobalApplication.isDebuging()) {
|
||||
LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
View addedView = inflater.inflate(R.layout.view_about_dev, this, false);
|
||||
LinearLayout llMain = addedView.findViewById(R.id.viewaboutdevLinearLayout1);
|
||||
metDevUserName = addedView.findViewById(R.id.viewaboutdevEditText1);
|
||||
metDevUserPassword = addedView.findViewById(R.id.viewaboutdevEditText2);
|
||||
metDevUserName.setText(PrefUtils.getString(mContext, "metDevUserName", ""));
|
||||
metDevUserPassword.setText(PrefUtils.getString(mContext, "metDevUserPassword", ""));
|
||||
//mDevelopHostConnectionStatusView = new DevelopHostConnectionStatusView(context);
|
||||
mWinBollServiceStatusView = addedView.findViewById(R.id.viewaboutdevWinBollServiceStatusView1);
|
||||
mWinBollServiceStatusView.setServerHost(mszWinBollServerHost);
|
||||
mWinBollServiceStatusView.setAuthInfo(metDevUserName.getText().toString(), metDevUserPassword.getText().toString());
|
||||
//llMain.addView(mDevelopHostConnectionStatusView);
|
||||
llMain.addView(createAboutPage());
|
||||
addView(addedView);
|
||||
} else {
|
||||
LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
View addedView = inflater.inflate(R.layout.view_about_www, this, false);
|
||||
LinearLayout llMain = addedView.findViewById(R.id.viewaboutwwwLinearLayout1);
|
||||
//mDevelopHostConnectionStatusView = new DevelopHostConnectionStatusView(context);
|
||||
mWinBollServiceStatusView = addedView.findViewById(R.id.viewaboutwwwWinBollServiceStatusView1);
|
||||
mWinBollServiceStatusView.setServerHost(mszWinBollServerHost);
|
||||
mWinBollServiceStatusView.setAuthInfo("", "");
|
||||
//llMain.addView(mDevelopHostConnectionStatusView);
|
||||
llMain.addView(createAboutPage());
|
||||
addView(addedView);
|
||||
}
|
||||
// void initView(Context context) {
|
||||
// mszAppName = mAPPInfo.getAppName();
|
||||
// mszAppAPKFolderName = mAPPInfo.getAppAPKFolderName();
|
||||
// mszAppAPKName = mAPPInfo.getAppAPKName();
|
||||
// mszAppGitName = mAPPInfo.getAppGitName();
|
||||
// mszAppDescription = mAPPInfo.getAppDescription();
|
||||
// mnAppIcon = mAPPInfo.getAppIcon();
|
||||
//
|
||||
// mszWinBollServerHost = GlobalApplication.isDebuging() ? "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";
|
||||
// mszHomePage = mszWinBollServerHost + "/studio/details.php?app=" + mszAppAPKFolderName;
|
||||
// if(mAPPInfo.getAppGitAPPBranch().equals("")) {
|
||||
// mszGitea = "https://gitea.winboll.cc/" + mAPPInfo.getAppGitOwner() + "/" + mszAppGitName;
|
||||
// } else {
|
||||
// mszGitea = "https://gitea.winboll.cc/" + mAPPInfo.getAppGitOwner() + "/" + mszAppGitName + "/src/branch/" + mAPPInfo.getAppGitAPPBranch() + "/" + mAPPInfo.getAppGitAPPSubProjectFolder();
|
||||
//}
|
||||
//
|
||||
// if (GlobalApplication.isDebuging()) {
|
||||
// LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
// View addedView = inflater.inflate(R.layout.view_about_dev, this, false);
|
||||
// LinearLayout llMain = addedView.findViewById(R.id.viewaboutdevLinearLayout1);
|
||||
// metDevUserName = addedView.findViewById(R.id.viewaboutdevEditText1);
|
||||
// metDevUserPassword = addedView.findViewById(R.id.viewaboutdevEditText2);
|
||||
// metDevUserName.setText(PrefUtils.getString(mContext, "metDevUserName", ""));
|
||||
// metDevUserPassword.setText(PrefUtils.getString(mContext, "metDevUserPassword", ""));
|
||||
// //mDevelopHostConnectionStatusView = new DevelopHostConnectionStatusView(context);
|
||||
// mWinBollServiceStatusView = addedView.findViewById(R.id.viewaboutdevWinBollServiceStatusView1);
|
||||
// mWinBollServiceStatusView.setServerHost(mszWinBollServerHost);
|
||||
// mWinBollServiceStatusView.setAuthInfo(metDevUserName.getText().toString(), metDevUserPassword.getText().toString());
|
||||
// //llMain.addView(mDevelopHostConnectionStatusView);
|
||||
// llMain.addView(createAboutPage());
|
||||
// addView(addedView);
|
||||
// } else {
|
||||
// LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
// View addedView = inflater.inflate(R.layout.view_about_www, this, false);
|
||||
// LinearLayout llMain = addedView.findViewById(R.id.viewaboutwwwLinearLayout1);
|
||||
// //mDevelopHostConnectionStatusView = new DevelopHostConnectionStatusView(context);
|
||||
// mWinBollServiceStatusView = addedView.findViewById(R.id.viewaboutwwwWinBollServiceStatusView1);
|
||||
// mWinBollServiceStatusView.setServerHost(mszWinBollServerHost);
|
||||
// mWinBollServiceStatusView.setAuthInfo("", "");
|
||||
// //llMain.addView(mDevelopHostConnectionStatusView);
|
||||
// llMain.addView(createAboutPage());
|
||||
// addView(addedView);
|
||||
// }
|
||||
|
||||
// 初始化标题栏
|
||||
//setSubtitle(getContext().getString(R.string.text_about));
|
||||
@@ -165,225 +164,226 @@ public class AboutView extends LinearLayout {
|
||||
// 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) {
|
||||
if (input.endsWith(".beta")) {
|
||||
return input.substring(0, input.length() - ".beta".length());
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
android.os.Handler mHandler = new android.os.Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
super.handleMessage(msg);
|
||||
switch (msg.what) {
|
||||
case MSG_APPUPDATE_CHECKED : {
|
||||
/*//检查当前应用包文件名是否是测试版,如果是就忽略检查
|
||||
if(mszCurrentAppPackageName.matches(".*_\\d+\\.\\d+\\.\\d+-beta.*\\.apk")) {
|
||||
ToastUtils.show("APP is the beta Version. Version check ignore.");
|
||||
return;
|
||||
}*/
|
||||
|
||||
// if (!AppVersionUtils.isHasNewStageReleaseVersion(mszReleaseAPKName, mszNewestAppPackageName)) {
|
||||
// ToastUtils.delayedShow("Current app is the newest.", 5000);
|
||||
// public static String subBetaSuffix(String input) {
|
||||
// if (input.endsWith(".beta")) {
|
||||
// return input.substring(0, input.length() - ".beta".length());
|
||||
// }
|
||||
if (!AppVersionUtils.isHasNewVersion2(mszCurrentAppPackageName, mszNewestAppPackageName)) {
|
||||
ToastUtils.delayedShow("Current app is the newest.", 5000);
|
||||
} else {
|
||||
String szMsg = "Current app is :\n[ " + mszCurrentAppPackageName
|
||||
+ " ]\nThe last app is :\n[ " + mszNewestAppPackageName
|
||||
+ " ]\nIs download the last app?";
|
||||
YesNoAlertDialog.show(mContext, "Application Update Prompt", szMsg, mIsDownlaodUpdateListener);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
// return input;
|
||||
// }
|
||||
//
|
||||
// android.os.Handler mHandler = new android.os.Handler() {
|
||||
// @Override
|
||||
// public void handleMessage(Message msg) {
|
||||
// super.handleMessage(msg);
|
||||
// switch (msg.what) {
|
||||
// case MSG_APPUPDATE_CHECKED : {
|
||||
// /*//检查当前应用包文件名是否是测试版,如果是就忽略检查
|
||||
// if(mszCurrentAppPackageName.matches(".*_\\d+\\.\\d+\\.\\d+-beta.*\\.apk")) {
|
||||
// ToastUtils.show("APP is the beta Version. Version check ignore.");
|
||||
// return;
|
||||
// }*/
|
||||
//
|
||||
//// if (!AppVersionUtils.isHasNewStageReleaseVersion(mszReleaseAPKName, mszNewestAppPackageName)) {
|
||||
//// ToastUtils.delayedShow("Current app is the newest.", 5000);
|
||||
//// }
|
||||
// if (!AppVersionUtils.isHasNewVersion2(mszCurrentAppPackageName, mszNewestAppPackageName)) {
|
||||
// ToastUtils.show("Current app is the newest.");
|
||||
// } else {
|
||||
// String szMsg = "Current app is :\n[ " + mszCurrentAppPackageName
|
||||
// + " ]\nThe last app is :\n[ " + mszNewestAppPackageName
|
||||
// + " ]\nIs download the last app?";
|
||||
// YesNoAlertDialog.show(mContext, "Application Update Prompt", szMsg, mIsDownlaodUpdateListener);
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
protected View createAboutPage() {
|
||||
// 定义应用调试按钮
|
||||
//
|
||||
Element elementAppMode;
|
||||
if (GlobalApplication.isDebuging()) {
|
||||
elementAppMode = new Element(mContext.getString(R.string.app_normal), R.drawable.ic_winboll);
|
||||
elementAppMode.setOnClickListener(mAppNormalOnClickListener);
|
||||
} else {
|
||||
elementAppMode = new Element(mContext.getString(R.string.app_debug), R.drawable.ic_winboll);
|
||||
elementAppMode.setOnClickListener(mAppDebugOnClickListener);
|
||||
}
|
||||
// 定义 GitWeb 按钮
|
||||
//
|
||||
Element elementGitWeb = new Element(mContext.getString(R.string.gitea_home), R.drawable.ic_winboll);
|
||||
elementGitWeb.setOnClickListener(mGitWebOnClickListener);
|
||||
// 定义检查更新按钮
|
||||
//
|
||||
Element elementAppUpdate = new Element(mContext.getString(R.string.app_update), R.drawable.ic_winboll);
|
||||
elementAppUpdate.setOnClickListener(mAppUpdateOnClickListener);
|
||||
// protected View createAboutPage() {
|
||||
// // 定义应用调试按钮
|
||||
// //
|
||||
// Element elementAppMode;
|
||||
// if (GlobalApplication.isDebuging()) {
|
||||
// elementAppMode = new Element(mContext.getString(R.string.app_normal), R.drawable.ic_winboll);
|
||||
// elementAppMode.setOnClickListener(mAppNormalOnClickListener);
|
||||
// } else {
|
||||
// elementAppMode = new Element(mContext.getString(R.string.app_debug), R.drawable.ic_winboll);
|
||||
// elementAppMode.setOnClickListener(mAppDebugOnClickListener);
|
||||
// }
|
||||
// // 定义 GitWeb 按钮
|
||||
// //
|
||||
// Element elementGitWeb = new Element(mContext.getString(R.string.gitea_home), R.drawable.ic_winboll);
|
||||
// elementGitWeb.setOnClickListener(mGitWebOnClickListener);
|
||||
// // 定义检查更新按钮
|
||||
// //
|
||||
// Element elementAppUpdate = new Element(mContext.getString(R.string.app_update), R.drawable.ic_winboll);
|
||||
// elementAppUpdate.setOnClickListener(mAppUpdateOnClickListener);
|
||||
//
|
||||
// String szAppInfo = "";
|
||||
// try {
|
||||
// szAppInfo = mszAppName + " "
|
||||
// + mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName
|
||||
// + "\n" + mszAppDescription;
|
||||
// } catch (PackageManager.NameNotFoundException e) {
|
||||
// LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
// }
|
||||
// View aboutPage = new AboutPage(mContext)
|
||||
// .setDescription(szAppInfo)
|
||||
// //.isRTL(false)
|
||||
// //.setCustomFont(String) // or Typeface
|
||||
// .setImage(mnAppIcon)
|
||||
// //.addItem(versionElement)
|
||||
// //.addItem(adsElement)
|
||||
// //.addGroup("Connect with us")
|
||||
// .addEmail("ZhanGSKen@AliYun.Com")
|
||||
// .addWebsite(mszHomePage)
|
||||
// .addItem(elementAppMode)
|
||||
// .addItem(elementGitWeb)
|
||||
// .addItem(elementAppUpdate)
|
||||
// //.addFacebook("the.medy")
|
||||
// //.addTwitter("medyo80")
|
||||
// //.addYoutube("UCdPQtdWIsg7_pi4mrRu46vA")
|
||||
// //.addPlayStore("com.ideashower.readitlater.pro")
|
||||
// //.addGitHub("medyo")
|
||||
// //.addInstagram("medyo80")
|
||||
// .create();
|
||||
// return aboutPage;
|
||||
// }
|
||||
|
||||
String szAppInfo = "";
|
||||
try {
|
||||
szAppInfo = mszAppName + " "
|
||||
+ mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName
|
||||
+ "\n" + mszAppDescription;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
View aboutPage = new AboutPage(mContext)
|
||||
.setDescription(szAppInfo)
|
||||
//.isRTL(false)
|
||||
//.setCustomFont(String) // or Typeface
|
||||
.setImage(mnAppIcon)
|
||||
//.addItem(versionElement)
|
||||
//.addItem(adsElement)
|
||||
//.addGroup("Connect with us")
|
||||
.addEmail("ZhanGSKen@AliYun.Com")
|
||||
.addWebsite(mszHomePage)
|
||||
.addItem(elementAppMode)
|
||||
.addItem(elementGitWeb)
|
||||
.addItem(elementAppUpdate)
|
||||
//.addFacebook("the.medy")
|
||||
//.addTwitter("medyo80")
|
||||
//.addYoutube("UCdPQtdWIsg7_pi4mrRu46vA")
|
||||
//.addPlayStore("com.ideashower.readitlater.pro")
|
||||
//.addGitHub("medyo")
|
||||
//.addInstagram("medyo80")
|
||||
.create();
|
||||
return aboutPage;
|
||||
}
|
||||
|
||||
View.OnClickListener mAppDebugOnClickListener = new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
setApp2DebugMode(mContext);
|
||||
}
|
||||
};
|
||||
|
||||
View.OnClickListener mAppNormalOnClickListener = new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
setApp2NormalMode(mContext);
|
||||
}
|
||||
};
|
||||
|
||||
public static void setApp2DebugMode(Context context) {
|
||||
Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
|
||||
if (intent != null) {
|
||||
intent.setAction(cc.winboll.studio.libapputils.intent.action.DEBUGVIEW);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
GlobalApplication.setIsDebuging(context, true);
|
||||
DebugBean.saveBean(context, new DebugBean(true));
|
||||
|
||||
WinBollActivityManager.getInstance(context).finishAll();
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setApp2NormalMode(Context context) {
|
||||
Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
|
||||
if (intent != null) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
GlobalApplication.setIsDebuging(context, false);
|
||||
DebugBean.saveBean(context, new DebugBean(false));
|
||||
|
||||
WinBollActivityManager.getInstance(context).finishAll();
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
View.OnClickListener mGitWebOnClickListener = new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(mszGitea));
|
||||
mContext.startActivity(browserIntent);
|
||||
}
|
||||
};
|
||||
|
||||
View.OnClickListener mAppUpdateOnClickListener = new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
ToastUtils.show("Start app update checking.");
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String szUrl = mszWinBollServerHost + "/studio/details.php?app=" + mszAppAPKFolderName;
|
||||
// 构建包含认证信息的请求
|
||||
String credential = "";
|
||||
if (GlobalApplication.isDebuging()) {
|
||||
credential = Credentials.basic(metDevUserName.getText().toString(), metDevUserPassword.getText().toString());
|
||||
PrefUtils.saveString(mContext, "metDevUserName", metDevUserName.getText().toString());
|
||||
PrefUtils.saveString(mContext, "metDevUserPassword", metDevUserPassword.getText().toString());
|
||||
}
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
Request request = new Request.Builder()
|
||||
.url(szUrl)
|
||||
.header("Accept", "text/plain") // 设置正确的Content-Type头
|
||||
.header("Authorization", credential)
|
||||
.build();
|
||||
Call call = client.newCall(request);
|
||||
call.enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
// 处理网络请求失败
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) throws IOException {
|
||||
if (!response.isSuccessful()) {
|
||||
LogUtils.d(TAG, "Unexpected code " + response, Thread.currentThread().getStackTrace());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 读取响应体作为字符串,注意这里可能需要解码
|
||||
String text = response.body().string();
|
||||
org.jsoup.nodes.Document doc = org.jsoup.Jsoup.parse(text);
|
||||
LogUtils.v(TAG, doc.text());
|
||||
|
||||
// 使用id选择器找到具有特定id的元素
|
||||
org.jsoup.nodes.Element elementWithId = doc.select("#LastRelease").first(); // 获取第一个匹配的元素
|
||||
|
||||
// 提取并打印元素的文本内容
|
||||
mszNewestAppPackageName = elementWithId.text();
|
||||
//ToastUtils.delayedShow(text + "\n" + mszNewestAppPackageName, 5000);
|
||||
|
||||
mHandler.sendMessage(mHandler.obtainMessage(MSG_APPUPDATE_CHECKED));
|
||||
} catch (Exception e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
};
|
||||
|
||||
YesNoAlertDialog.OnDialogResultListener mIsDownlaodUpdateListener = new YesNoAlertDialog.OnDialogResultListener() {
|
||||
@Override
|
||||
public void onYes() {
|
||||
String szUrl = mszWinBollServerHost + "/studio/download.php?appname=" + mszAppAPKFolderName + "&apkname=" + mszNewestAppPackageName;
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(szUrl));
|
||||
mContext.startActivity(browserIntent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNo() {
|
||||
}
|
||||
};
|
||||
|
||||
public interface OnRequestDevUserInfoAutofillListener {
|
||||
void requestAutofill(EditText etDevUserName, EditText etDevUserPassword);
|
||||
}
|
||||
|
||||
public void setOnRequestDevUserInfoAutofillListener(OnRequestDevUserInfoAutofillListener l) {
|
||||
mOnRequestDevUserInfoAutofillListener = l;
|
||||
}
|
||||
// View.OnClickListener mAppDebugOnClickListener = new View.OnClickListener(){
|
||||
// @Override
|
||||
// public void onClick(View view) {
|
||||
// setApp2DebugMode(mContext);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// View.OnClickListener mAppNormalOnClickListener = new View.OnClickListener(){
|
||||
// @Override
|
||||
// public void onClick(View view) {
|
||||
// setApp2NormalMode(mContext);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// public static void setApp2DebugMode(Context context) {
|
||||
// Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
|
||||
// if (intent != null) {
|
||||
// intent.setAction(cc.winboll.studio.libapputils.intent.action.DEBUGVIEW);
|
||||
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
// GlobalApplication.setIsDebuging(context, true);
|
||||
// DebugBean.saveBean(context, new DebugBean(true));
|
||||
//
|
||||
// WinBollActivityManager.getInstance(context).finishAll();
|
||||
// context.startActivity(intent);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public static void setApp2NormalMode(Context context) {
|
||||
// Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
|
||||
// if (intent != null) {
|
||||
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
// GlobalApplication.setIsDebuging(context, false);
|
||||
// DebugBean.saveBean(context, new DebugBean(false));
|
||||
//
|
||||
// WinBollActivityManager.getInstance(context).finishAll();
|
||||
// context.startActivity(intent);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// View.OnClickListener mGitWebOnClickListener = new View.OnClickListener(){
|
||||
// @Override
|
||||
// public void onClick(View view) {
|
||||
// Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(mszGitea));
|
||||
// mContext.startActivity(browserIntent);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// View.OnClickListener mAppUpdateOnClickListener = new View.OnClickListener(){
|
||||
// @Override
|
||||
// public void onClick(View view) {
|
||||
// ToastUtils.show("Start app update checking.");
|
||||
// new Thread(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// String szUrl = mszWinBollServerHost + "/studio/details.php?app=" + mszAppAPKFolderName;
|
||||
// // 构建包含认证信息的请求
|
||||
// String credential = "";
|
||||
// if (GlobalApplication.isDebuging()) {
|
||||
// credential = Credentials.basic(metDevUserName.getText().toString(), metDevUserPassword.getText().toString());
|
||||
// PrefUtils.saveString(mContext, "metDevUserName", metDevUserName.getText().toString());
|
||||
// PrefUtils.saveString(mContext, "metDevUserPassword", metDevUserPassword.getText().toString());
|
||||
// }
|
||||
// OkHttpClient client = new OkHttpClient();
|
||||
// Request request = new Request.Builder()
|
||||
// .url(szUrl)
|
||||
// .header("Accept", "text/plain") // 设置正确的Content-Type头
|
||||
// .header("Authorization", credential)
|
||||
// .build();
|
||||
// Call call = client.newCall(request);
|
||||
// call.enqueue(new Callback() {
|
||||
// @Override
|
||||
// public void onFailure(Call call, IOException e) {
|
||||
// // 处理网络请求失败
|
||||
// LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onResponse(Call call, Response response) throws IOException {
|
||||
// if (!response.isSuccessful()) {
|
||||
// LogUtils.d(TAG, "Unexpected code " + response, Thread.currentThread().getStackTrace());
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// try {
|
||||
// // 读取响应体作为字符串,注意这里可能需要解码
|
||||
// String text = response.body().string();
|
||||
// org.jsoup.nodes.Document doc = org.jsoup.Jsoup.parse(text);
|
||||
// LogUtils.v(TAG, doc.text());
|
||||
//
|
||||
// // 使用id选择器找到具有特定id的元素
|
||||
// org.jsoup.nodes.Element elementWithId = doc.select("#LastRelease").first(); // 获取第一个匹配的元素
|
||||
//
|
||||
// // 提取并打印元素的文本内容
|
||||
// mszNewestAppPackageName = elementWithId.text();
|
||||
// //ToastUtils.delayedShow(text + "\n" + mszNewestAppPackageName, 5000);
|
||||
//
|
||||
// mHandler.sendMessage(mHandler.obtainMessage(MSG_APPUPDATE_CHECKED));
|
||||
// } catch (Exception e) {
|
||||
// LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }).start();
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// YesNoAlertDialog.OnDialogResultListener mIsDownlaodUpdateListener = new YesNoAlertDialog.OnDialogResultListener() {
|
||||
// @Override
|
||||
// public void onYes() {
|
||||
// String szUrl = mszWinBollServerHost + "/studio/download.php?appname=" + mszAppAPKFolderName + "&apkname=" + mszNewestAppPackageName;
|
||||
// Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(szUrl));
|
||||
// mContext.startActivity(browserIntent);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onNo() {
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// public interface OnRequestDevUserInfoAutofillListener {
|
||||
// void requestAutofill(EditText etDevUserName, EditText etDevUserPassword);
|
||||
// }
|
||||
//
|
||||
// public void setOnRequestDevUserInfoAutofillListener(OnRequestDevUserInfoAutofillListener l) {
|
||||
// mOnRequestDevUserInfoAutofillListener = l;
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
|
||||
public class SimpleWebView extends WebView {
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ package cc.winboll.studio.libapputils.view;
|
||||
* @Date 2024/12/19 13:49:14
|
||||
* @Describe 把字符串转化为二维码的视图
|
||||
*/
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -13,12 +14,7 @@ import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import cc.winboll.studio.libapputils.util.QRCodeGenerator;
|
||||
import com.google.zxing.Result;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
|
||||
|
||||
public class StringToQrCodeView extends LinearLayout {
|
||||
|
||||
@@ -5,6 +5,7 @@ package cc.winboll.studio.libapputils.view;
|
||||
* @Date 2024/12/07 20:15:47
|
||||
* @Describe WinBoll 服务主机连接状态视图
|
||||
*/
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -18,22 +19,20 @@ import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libapputils.R;
|
||||
import cc.winboll.studio.libappbase.utils.ToastUtils;
|
||||
import cc.winboll.studio.libapputils.service.IWinBollClientServiceBinder;
|
||||
import cc.winboll.studio.libapputils.service.WinBollClientService;
|
||||
import cc.winboll.studio.libapputils.service.WinBollClientServiceBean;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import okhttp3.Authenticator;
|
||||
import okhttp3.Credentials;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.Route;
|
||||
//import okhttp3.Authenticator;
|
||||
//import okhttp3.Credentials;
|
||||
//import okhttp3.OkHttpClient;
|
||||
//import okhttp3.Request;
|
||||
//import okhttp3.Response;
|
||||
//import okhttp3.Route;
|
||||
|
||||
public class WinBollServiceStatusView extends LinearLayout {
|
||||
|
||||
@@ -211,7 +210,7 @@ public class WinBollServiceStatusView extends LinearLayout {
|
||||
void setImageViewByConnection(ImageView imageView, boolean isConnected) {
|
||||
//mIsConnected = isConnected;
|
||||
// 获取vector drawable
|
||||
Drawable drawable = ContextCompat.getDrawable(mContext, isConnected ? R.drawable.ic_dev_connected : R.drawable.ic_dev_disconnected);
|
||||
Drawable drawable = mContext.getDrawable(isConnected ? R.drawable.ic_dev_connected : R.drawable.ic_dev_disconnected);
|
||||
if (drawable != null) {
|
||||
imageView.setImageDrawable(drawable);
|
||||
}
|
||||
@@ -222,49 +221,49 @@ public class WinBollServiceStatusView extends LinearLayout {
|
||||
//String username = "your_username";
|
||||
//String password = "your_password";
|
||||
|
||||
OkHttpClient client = new OkHttpClient.Builder()
|
||||
.authenticator(new Authenticator() {
|
||||
@Override
|
||||
public Request authenticate(Route route, Response response) throws IOException {
|
||||
String credential = Credentials.basic(username, password);
|
||||
return response.request().newBuilder()
|
||||
.header("Authorization", credential)
|
||||
.build();
|
||||
}
|
||||
})
|
||||
.build();
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(targetUrl) // 替换为实际要请求的网页地址
|
||||
.build();
|
||||
|
||||
try {
|
||||
Response response = client.newCall(request).execute();
|
||||
if (response.isSuccessful()) {
|
||||
//System.out.println(response.body().string());
|
||||
//ToastUtils.show("Develop Host Connection IP is : " + response.body().string());
|
||||
// 获取当前时间
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
// 定义时间格式
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
|
||||
// 按照指定格式格式化时间并输出
|
||||
String formattedDateTime = now.format(formatter);
|
||||
//System.out.println(formattedDateTime);
|
||||
textViewHandler.postMessageText("ClientIP<" + formattedDateTime + ">: " + response.body().string());
|
||||
textViewHandler.postMessageConnectionStatus(true);
|
||||
} else {
|
||||
String sz = "请求失败,状态码: " + response.code();
|
||||
setImageViewByConnection(mImageView, false);
|
||||
textViewHandler.postMessageText(sz);
|
||||
textViewHandler.postMessageConnectionStatus(false);
|
||||
LogUtils.d(TAG, sz);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
textViewHandler.postMessageText(e.getMessage());
|
||||
textViewHandler.postMessageConnectionStatus(false);
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
// OkHttpClient client = new OkHttpClient.Builder()
|
||||
// .authenticator(new Authenticator() {
|
||||
// @Override
|
||||
// public Request authenticate(Route route, Response response) throws IOException {
|
||||
// String credential = Credentials.basic(username, password);
|
||||
// return response.request().newBuilder()
|
||||
// .header("Authorization", credential)
|
||||
// .build();
|
||||
// }
|
||||
// })
|
||||
// .build();
|
||||
//
|
||||
// Request request = new Request.Builder()
|
||||
// .url(targetUrl) // 替换为实际要请求的网页地址
|
||||
// .build();
|
||||
//
|
||||
// try {
|
||||
// Response response = client.newCall(request).execute();
|
||||
// if (response.isSuccessful()) {
|
||||
// //System.out.println(response.body().string());
|
||||
// //ToastUtils.show("Develop Host Connection IP is : " + response.body().string());
|
||||
// // 获取当前时间
|
||||
// LocalDateTime now = LocalDateTime.now();
|
||||
//
|
||||
// // 定义时间格式
|
||||
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
|
||||
// // 按照指定格式格式化时间并输出
|
||||
// String formattedDateTime = now.format(formatter);
|
||||
// //System.out.println(formattedDateTime);
|
||||
// textViewHandler.postMessageText("ClientIP<" + formattedDateTime + ">: " + response.body().string());
|
||||
// textViewHandler.postMessageConnectionStatus(true);
|
||||
// } else {
|
||||
// String sz = "请求失败,状态码: " + response.code();
|
||||
// setImageViewByConnection(mImageView, false);
|
||||
// textViewHandler.postMessageText(sz);
|
||||
// textViewHandler.postMessageConnectionStatus(false);
|
||||
// LogUtils.d(TAG, sz);
|
||||
// }
|
||||
// } catch (IOException e) {
|
||||
// textViewHandler.postMessageText(e.getMessage());
|
||||
// textViewHandler.postMessageConnectionStatus(false);
|
||||
// LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
// }
|
||||
}
|
||||
|
||||
class WinBollServiceViewHandler extends Handler {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
<android.widget.Toolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/activityaboutToolbar1"/>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
<android.widget.Toolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/activityassetshtmlToolbar1"/>
|
||||
|
||||