更新类库
This commit is contained in:
		| @@ -18,18 +18,18 @@ def genVersionName(def versionName){ | ||||
| } | ||||
|  | ||||
| android { | ||||
|     compileSdkVersion 32 | ||||
|     buildToolsVersion "33.0.3" | ||||
|     compileSdkVersion 30 | ||||
|     buildToolsVersion "30.0.3" | ||||
|  | ||||
|     defaultConfig { | ||||
|         applicationId "cc.winboll.studio.apputils" | ||||
|         minSdkVersion 21 | ||||
|         targetSdkVersion 30 | ||||
|         minSdkVersion 26 | ||||
|         targetSdkVersion 29 | ||||
|         versionCode 1 | ||||
|         // versionName 更新后需要手动设置  | ||||
|         // 项目模块目录的 build.gradle 文件的 stageCount=0 | ||||
|         // Gradle编译环境下合起来的 versionName 就是 "${versionName}.0" | ||||
|         versionName "9.3"  | ||||
|         versionName "9.4"  | ||||
|         if(true) { | ||||
|             versionName = genVersionName("${versionName}") | ||||
|         } | ||||
| @@ -49,7 +49,31 @@ android { | ||||
| } | ||||
|  | ||||
| dependencies { | ||||
| 	api project(':libapputils') | ||||
| 	implementation project(':libapputils') | ||||
|      | ||||
|     api fileTree(dir: 'libs', include: ['*.jar']) | ||||
|     implementation 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' | ||||
|      | ||||
|     implementation 'cc.winboll.studio:libappbase:2.1.1' | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| #Created by .winboll/winboll_app_build.gradle | ||||
| #Wed Feb 12 19:50:18 HKT 2025 | ||||
| stageCount=3 | ||||
| #Fri Mar 07 19:11:42 GMT 2025 | ||||
| stageCount=0 | ||||
| libraryProject=libapputils | ||||
| baseVersion=9.3 | ||||
| publishVersion=9.3.2 | ||||
| buildCount=0 | ||||
| baseBetaVersion=9.3.3 | ||||
| baseVersion=9.4 | ||||
| publishVersion=9.4.0 | ||||
| buildCount=1 | ||||
| baseBetaVersion=9.4.1 | ||||
|   | ||||
| @@ -14,13 +14,14 @@ import androidx.appcompat.app.AppCompatActivity; | ||||
| import androidx.appcompat.widget.Toolbar; | ||||
| import cc.winboll.studio.apputils.R; | ||||
| import cc.winboll.studio.libappbase.LogUtils; | ||||
| import cc.winboll.studio.libappbase.LogView; | ||||
| import cc.winboll.studio.libapputils.activities.AssetsHtmlActivity; | ||||
| import cc.winboll.studio.libapputils.activities.LogActivity; | ||||
| import cc.winboll.studio.libapputils.activities.QRCodeDecodeActivity; | ||||
| import cc.winboll.studio.libapputils.app.AboutActivityFactory; | ||||
| 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.log.LogActivity; | ||||
| import cc.winboll.studio.libapputils.view.AboutView; | ||||
| import cc.winboll.studio.libapputils.view.YesNoAlertDialog; | ||||
| import com.hjq.toast.ToastUtils; | ||||
| @@ -34,6 +35,7 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct | ||||
|     public static final int REQUEST_QRCODEDECODE_ACTIVITY = 0; | ||||
|  | ||||
|     Toolbar mToolbar; | ||||
|     LogView mLogView; | ||||
|  | ||||
|     @Override | ||||
|     public AppCompatActivity getActivity() { | ||||
| @@ -58,7 +60,7 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct | ||||
|         return appInfo; | ||||
|         //return null; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     @Override | ||||
|     public String getTag() { | ||||
|         return TAG; | ||||
| @@ -84,6 +86,9 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setContentView(R.layout.activity_main); | ||||
|  | ||||
|         mLogView = findViewById(R.id.logview); | ||||
|         mLogView.start(); | ||||
|  | ||||
|         // 初始化工具栏 | ||||
|         mToolbar = findViewById(R.id.activitymainToolbar1); | ||||
|         setSupportActionBar(mToolbar); | ||||
|   | ||||
| @@ -26,7 +26,7 @@ public class TestStringToQrCodeViewActivity extends AppCompatActivity implements | ||||
|     public APPInfo getAppInfo() { | ||||
|         return null; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     @Override | ||||
|     public String getTag() { | ||||
|         return TAG; | ||||
|   | ||||
| @@ -27,7 +27,7 @@ | ||||
| 				android:layout_width="wrap_content" | ||||
| 				android:layout_height="wrap_content" | ||||
| 				android:text="TestLog" | ||||
|                 android:textAllCaps="false" | ||||
| 				android:textAllCaps="false" | ||||
| 				android:onClick="onTestLogClick"/> | ||||
|  | ||||
| 			<Button | ||||
| @@ -39,35 +39,28 @@ | ||||
|  | ||||
| 		</LinearLayout> | ||||
|  | ||||
|         <LinearLayout | ||||
|             android:orientation="horizontal" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:gravity="right"> | ||||
| 		<LinearLayout | ||||
| 			android:orientation="horizontal" | ||||
| 			android:layout_width="match_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:gravity="right"> | ||||
|  | ||||
|             <Button | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:textAllCaps="false" | ||||
|                 android:text="Test Javascript Html Activity" | ||||
|                 android:onClick="onTestJavascriptHtmlActivity"/> | ||||
| 			<Button | ||||
| 				android:layout_width="wrap_content" | ||||
| 				android:layout_height="wrap_content" | ||||
| 				android:textAllCaps="false" | ||||
| 				android:text="Test Javascript Html Activity" | ||||
| 				android:onClick="onTestJavascriptHtmlActivity"/> | ||||
|  | ||||
|         </LinearLayout> | ||||
| 		</LinearLayout> | ||||
|  | ||||
|         <LinearLayout | ||||
|             android:orientation="horizontal" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:gravity="right"> | ||||
| 		<cc.winboll.studio.libappbase.LogView | ||||
| 			android:layout_width="match_parent" | ||||
| 			android:layout_height="0dp" | ||||
| 			android:text="Button" | ||||
| 			android:id="@+id/logview" | ||||
| 			android:layout_weight="1.0"/> | ||||
|  | ||||
|             <cc.winboll.studio.libapputils.view.AboutBranchButton | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:text="About" | ||||
|                 android:textAllCaps="false"/> | ||||
|  | ||||
|         </LinearLayout> | ||||
|          | ||||
| 	</LinearLayout> | ||||
|  | ||||
| </LinearLayout> | ||||
|   | ||||
| @@ -4,12 +4,12 @@ apply from: '../.winboll/winboll_lib_build.gradle' | ||||
| apply from: '../.winboll/winboll_lint_build.gradle' | ||||
|  | ||||
| android { | ||||
|     compileSdkVersion 32 | ||||
|     buildToolsVersion "33.0.3" | ||||
|     compileSdkVersion 30 | ||||
|     buildToolsVersion "30.0.3" | ||||
|  | ||||
|     defaultConfig { | ||||
|         minSdkVersion 21 | ||||
|         targetSdkVersion 30 | ||||
|         minSdkVersion 26 | ||||
|         targetSdkVersion 29 | ||||
|     } | ||||
|     buildTypes { | ||||
|         release { | ||||
| @@ -17,28 +17,32 @@ android { | ||||
|             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' | ||||
|         } | ||||
|     } | ||||
|     compileOptions { | ||||
|         sourceCompatibility JavaVersion.VERSION_11 | ||||
|         targetCompatibility JavaVersion.VERSION_11 | ||||
|     } | ||||
| } | ||||
|  | ||||
| dependencies { | ||||
|     // 二维码使用的类库 | ||||
|     api 'com.google.zxing:core:3.4.1' | ||||
|     api 'com.journeyapps:zxing-android-embedded:3.6.0' | ||||
|     implementation fileTree(dir: 'libs', include: ['*.jar']) | ||||
|      | ||||
|     api 'io.github.medyo:android-about-page:2.0.0' | ||||
|     api 'com.github.getActivity:ToastUtils:10.5' | ||||
|     api 'com.jcraft:jsch:0.1.55' | ||||
|     api 'org.jsoup:jsoup:1.13.1' | ||||
|     api 'com.squareup.okhttp3:okhttp:4.4.1' | ||||
|     // 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' | ||||
|      | ||||
|     api 'androidx.appcompat:appcompat:1.3.1' | ||||
|     api 'androidx.fragment:fragment:1.1.0' | ||||
|     api 'com.google.android.material:material:1.1.0' | ||||
|     // 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' | ||||
|      | ||||
|     api 'cc.winboll.studio:libappbase:1.4.1' | ||||
|      | ||||
|     api fileTree(dir: 'libs', include: ['*.jar']) | ||||
|     implementation 'cc.winboll.studio:libappbase:2.1.1' | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| #Created by .winboll/winboll_app_build.gradle | ||||
| #Wed Feb 12 19:50:03 HKT 2025 | ||||
| stageCount=3 | ||||
| #Fri Mar 07 19:11:42 GMT 2025 | ||||
| stageCount=0 | ||||
| libraryProject=libapputils | ||||
| baseVersion=9.3 | ||||
| publishVersion=9.3.2 | ||||
| buildCount=0 | ||||
| baseBetaVersion=9.3.3 | ||||
| baseVersion=9.4 | ||||
| publishVersion=9.4.0 | ||||
| buildCount=1 | ||||
| baseBetaVersion=9.4.1 | ||||
|   | ||||
| @@ -29,7 +29,7 @@ | ||||
|             android:launchMode="standard"/> | ||||
|  | ||||
|         <activity | ||||
|             android:name=".log.LogActivity" | ||||
|             android:name=".activities.LogActivity" | ||||
|             android:label="LogActivity" | ||||
|             android:launchMode="standard"/> | ||||
|  | ||||
|   | ||||
| @@ -9,7 +9,6 @@ import android.content.Intent; | ||||
| import android.os.Bundle; | ||||
| import android.view.Menu; | ||||
| import android.view.MenuItem; | ||||
| import android.view.View; | ||||
| import android.widget.LinearLayout; | ||||
| import androidx.appcompat.app.AppCompatActivity; | ||||
| import androidx.appcompat.widget.Toolbar; | ||||
| @@ -18,7 +17,6 @@ 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; | ||||
| import com.hjq.toast.ToastUtils; | ||||
|  | ||||
| final public class AboutActivity extends AppCompatActivity implements IWinBollActivity { | ||||
|  | ||||
|   | ||||
| @@ -1,15 +1,16 @@ | ||||
| package cc.winboll.studio.libapputils.log; | ||||
| package cc.winboll.studio.libapputils.activities; | ||||
| 
 | ||||
| /** | ||||
|  * @Author ZhanGSKen@QQ.COM | ||||
|  * @Date 2024/08/12 15:07:58 | ||||
|  * @Describe WinBoll 应用日志窗口 | ||||
|  * @Author ZhanGSKen@AliYun.Com | ||||
|  * @Date 2025/03/08 00:19:39 | ||||
|  * @Describe LogActivity | ||||
|  */ | ||||
| import android.os.Bundle; | ||||
| import androidx.appcompat.app.AppCompatActivity; | ||||
| import androidx.appcompat.widget.Toolbar; | ||||
| import cc.winboll.studio.libappbase.GlobalApplication; | ||||
| 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; | ||||
| @@ -19,7 +20,7 @@ public class LogActivity extends AppCompatActivity implements IWinBollActivity { | ||||
|     public static final String TAG = "LogActivity"; | ||||
| 
 | ||||
|     LogView mLogView; | ||||
|      | ||||
| 
 | ||||
|     @Override | ||||
|     public AppCompatActivity getActivity() { | ||||
|         return this; | ||||
| @@ -29,7 +30,7 @@ public class LogActivity extends AppCompatActivity implements IWinBollActivity { | ||||
|     public APPInfo getAppInfo() { | ||||
|         return null; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     @Override | ||||
|     public String getTag() { | ||||
|         return TAG; | ||||
| @@ -56,14 +57,13 @@ public class LogActivity extends AppCompatActivity implements IWinBollActivity { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setContentView(R.layout.activity_log); | ||||
|         mLogView = findViewById(R.id.logview); | ||||
| 
 | ||||
|         if (GlobalApplication.isDebuging()) { mLogView.start(); } | ||||
|         mLogView.start(); | ||||
|          | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onResume() { | ||||
|         LogUtils.d(TAG, "onResume"); | ||||
|         super.onResume(); | ||||
|         mLogView.start(); | ||||
|     } | ||||
| } | ||||
| @@ -1,18 +1,16 @@ | ||||
| package cc.winboll.studio.libapputils.app; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import cc.winboll.studio.libapputils.activities.AboutActivity; | ||||
| import cc.winboll.studio.libapputils.app.AboutActivityFactory; | ||||
| import cc.winboll.studio.libapputils.bean.APPInfo; | ||||
| import com.hjq.toast.ToastUtils; | ||||
| import java.util.regex.Matcher; | ||||
| import java.util.regex.Pattern; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen@QQ.COM | ||||
|  * @Date 2025/02/06 08:45:23 | ||||
|  * @Describe 关于活动窗口的介绍窗口工厂 | ||||
|  */ | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import cc.winboll.studio.libapputils.activities.AboutActivity; | ||||
| import cc.winboll.studio.libapputils.app.AboutActivityFactory; | ||||
| import cc.winboll.studio.libapputils.bean.APPInfo; | ||||
|  | ||||
| public class AboutActivityFactory { | ||||
|  | ||||
|     public static final String TAG = "AboutActivityFactory"; | ||||
|   | ||||
| @@ -1,11 +1,10 @@ | ||||
| package cc.winboll.studio.libapputils.app; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen@QQ.COM | ||||
|  * @Date 2025/02/04 10:20:16 | ||||
|  * @Describe WinBoll Activity 接口 | ||||
|  * @Author ZhanGSKen@AliYun.Com | ||||
|  * @Date 2025/03/08 00:15:36 | ||||
|  * @Describe WinBoll 活动窗口通用接口 | ||||
|  */ | ||||
| import android.view.View; | ||||
| import androidx.appcompat.app.AppCompatActivity; | ||||
| import androidx.appcompat.widget.Toolbar; | ||||
| import cc.winboll.studio.libapputils.bean.APPInfo; | ||||
| @@ -15,11 +14,10 @@ public interface IWinBollActivity { | ||||
|     public static final String TAG = "IWinBollActivity"; | ||||
|  | ||||
|     // 获取当前具有 IWinBoll 特征的 AppCompatActivity 活动窗口 | ||||
|     AppCompatActivity getActivity(); | ||||
|  | ||||
|     abstract public AppCompatActivity getActivity(); | ||||
|     abstract public APPInfo getAppInfo(); | ||||
|     abstract public String getTag(); | ||||
|     abstract Toolbar initToolBar(); | ||||
|     abstract boolean isEnableDisplayHomeAsUp(); | ||||
|     abstract boolean isAddWinBollToolBar(); | ||||
|     abstract public Toolbar initToolBar(); | ||||
|     abstract public boolean isEnableDisplayHomeAsUp(); | ||||
|     abstract public boolean isAddWinBollToolBar(); | ||||
| } | ||||
|   | ||||
| @@ -1,18 +0,0 @@ | ||||
| package cc.winboll.studio.libapputils.app; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen@QQ.COM | ||||
|  * @Date 2025/02/04 10:19:34 | ||||
|  * @Describe WinBoll 工厂 | ||||
|  */ | ||||
| import androidx.appcompat.app.AppCompatActivity; | ||||
|  | ||||
| public class WinBollFactory { | ||||
|  | ||||
|     public static final String TAG = "WinBollFactory"; | ||||
|  | ||||
|     public static AppCompatActivity buildAppCompatActivity(IWinBollActivity iWinBoll) { | ||||
|         return iWinBoll.getActivity(); | ||||
|     } | ||||
| } | ||||
| @@ -1,5 +1,4 @@ | ||||
| package cc.winboll.studio.libapputils.bean; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen@QQ.COM | ||||
|  * @Date 2025/01/20 14:19:02 | ||||
|   | ||||
| @@ -1,387 +0,0 @@ | ||||
| package cc.winboll.studio.libapputils.log; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen@QQ.COM | ||||
|  * @Date 2024/08/12 14:36:18 | ||||
|  * @Describe 日志视图类,继承 RelativeLayout 类。 | ||||
|  */ | ||||
| import android.content.ClipData; | ||||
| import android.content.ClipboardManager; | ||||
| import android.content.Context; | ||||
| import android.os.Handler; | ||||
| import android.os.Message; | ||||
| import android.util.AttributeSet; | ||||
| import android.view.LayoutInflater; | ||||
| import android.view.View; | ||||
| import android.view.ViewGroup; | ||||
| import android.widget.AdapterView; | ||||
| import android.widget.ArrayAdapter; | ||||
| 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.libapputils.R; | ||||
| import java.text.Collator; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.Comparator; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| public class LogView extends RelativeLayout { | ||||
|  | ||||
|     public static final String TAG = "LogView"; | ||||
|  | ||||
|     public volatile boolean mIsHandling; | ||||
|     public volatile boolean mIsAddNewLog; | ||||
|  | ||||
|     Context mContext; | ||||
|     ScrollView mScrollView; | ||||
|     TextView mTextView; | ||||
|     CheckBox mSelectableCheckBox; | ||||
|     CheckBox mSelectAllTAGCheckBox; | ||||
|     TAGListAdapter mTAGListAdapter; | ||||
|     LogViewThread mLogViewThread; | ||||
|     LogViewHandler mLogViewHandler; | ||||
|     Spinner mLogLevelSpinner; | ||||
|     ArrayAdapter<CharSequence> mLogLevelSpinnerAdapter; | ||||
|     // 标签列表 | ||||
|     RecyclerView recyclerView; | ||||
|  | ||||
|     public LogView(Context context) { | ||||
|         super(context); | ||||
|         initView(context); | ||||
|     } | ||||
|  | ||||
|     public LogView(Context context, AttributeSet attrs) { | ||||
|         super(context, attrs); | ||||
|         initView(context); | ||||
|     } | ||||
|  | ||||
|     public LogView(Context context, AttributeSet attrs, int defStyleAttr) { | ||||
|         super(context, attrs, defStyleAttr); | ||||
|         initView(context); | ||||
|     } | ||||
|  | ||||
|     public LogView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { | ||||
|         super(context, attrs, defStyleAttr, defStyleRes); | ||||
|         initView(context); | ||||
|     } | ||||
|  | ||||
|     public void start() { | ||||
|         mLogViewThread = new LogViewThread(LogView.this); | ||||
|         mLogViewThread.start(); | ||||
|         // 显示日志 | ||||
|         showAndScrollLogView(); | ||||
|     } | ||||
|  | ||||
|     public void scrollLogUp() { | ||||
|         mScrollView.post(new Runnable() { | ||||
|                 @Override | ||||
|                 public void run() { | ||||
|                     mScrollView.fullScroll(ScrollView.FOCUS_DOWN); | ||||
|                     // 日志显示结束 | ||||
|                     mLogViewHandler.setIsHandling(false); | ||||
|                     // 检查是否添加了新日志 | ||||
|                     if (mLogViewHandler.isAddNewLog()) { | ||||
|                         // 有新日志添加,先更改新日志标志 | ||||
|                         mLogViewHandler.setIsAddNewLog(false); | ||||
|                         // 再次发送显示日志的显示 | ||||
|                         Message message = mLogViewHandler.obtainMessage(LogViewHandler.MSG_LOGVIEW_UPDATE); | ||||
|                         mLogViewHandler.sendMessage(message); | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     void initView(Context context) { | ||||
|         mContext = context; | ||||
|         mLogViewHandler = new LogViewHandler(); | ||||
|         // 加载视图布局 | ||||
|         addView(inflate(mContext, cc.winboll.studio.libapputils.R.layout.view_log, null)); | ||||
|         // 初始化日志子控件视图 | ||||
|         // | ||||
|         mScrollView = findViewById(cc.winboll.studio.libapputils.R.id.viewlogScrollViewLog); | ||||
|         mTextView = findViewById(cc.winboll.studio.libapputils.R.id.viewlogTextViewLog); | ||||
|         // 获取Log Level spinner实例 | ||||
|         mLogLevelSpinner = findViewById(cc.winboll.studio.libapputils.R.id.viewlogSpinner1); | ||||
|  | ||||
|         (findViewById(cc.winboll.studio.libapputils.R.id.viewlogButtonClean)).setOnClickListener(new View.OnClickListener(){ | ||||
|  | ||||
|                 @Override | ||||
|                 public void onClick(View v) { | ||||
|                     LogUtils.cleanLog(); | ||||
|                     LogUtils.d(TAG, "Log is cleaned."); | ||||
|                 } | ||||
|             }); | ||||
|         (findViewById(cc.winboll.studio.libapputils.R.id.viewlogButtonCopy)).setOnClickListener(new View.OnClickListener(){ | ||||
|  | ||||
|                 @Override | ||||
|                 public void onClick(View v) { | ||||
|  | ||||
|                     ClipboardManager cm = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE); | ||||
|                     cm.setPrimaryClip(ClipData.newPlainText(mContext.getPackageName(), LogUtils.loadLog())); | ||||
|                     LogUtils.d(TAG, "Log is copied."); | ||||
|                 } | ||||
|             }); | ||||
|         mSelectableCheckBox = findViewById(cc.winboll.studio.libapputils.R.id.viewlogCheckBoxSelectable); | ||||
|         mSelectableCheckBox.setOnClickListener(new View.OnClickListener(){ | ||||
|                 @Override | ||||
|                 public void onClick(View v) { | ||||
|                     if (mSelectableCheckBox.isChecked()) { | ||||
|                         setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); | ||||
|                     } else { | ||||
|                         setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|         // 设置日志级别列表 | ||||
|         ArrayList<String> adapterItems = new ArrayList<>(); | ||||
|         for (LogUtils.LOG_LEVEL e : LogUtils.LOG_LEVEL.values()) { | ||||
|             adapterItems.add(e.name()); | ||||
|         } | ||||
|         // 假设你有一个字符串数组作为选项列表 | ||||
|         //String[] options = {"Option 1", "Option 2", "Option 3"}; | ||||
|         // 创建一个ArrayAdapter来绑定数据到spinner | ||||
|         mLogLevelSpinnerAdapter = ArrayAdapter.createFromResource( | ||||
|             context, cc.winboll.studio.libapputils.R.array.enum_loglevel_array, android.R.layout.simple_spinner_item); | ||||
|         mLogLevelSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); | ||||
|  | ||||
|         // 设置适配器并将它应用到spinner上 | ||||
|         mLogLevelSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // 设置下拉视图样式 | ||||
|         mLogLevelSpinner.setAdapter(mLogLevelSpinnerAdapter); | ||||
|         // 为Spinner添加监听器 | ||||
|         mLogLevelSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { | ||||
|                 @Override | ||||
|                 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { | ||||
|                     //String selectedOption = mLogLevelSpinnerAdapter.getItem(position); | ||||
|                     // 处理选中的选项... | ||||
|                     LogUtils.setLogLevel(LogUtils.LOG_LEVEL.values()[position]); | ||||
|                 } | ||||
|                 @Override | ||||
|                 public void onNothingSelected(AdapterView<?> parent) { | ||||
|                     // 如果没有选择,则执行此操作... | ||||
|                 } | ||||
|             }); | ||||
|         // 获取默认值的索引 | ||||
|         int defaultValueIndex = LogUtils.getLogLevel().ordinal(); | ||||
|  | ||||
|         if (defaultValueIndex != -1) { | ||||
|             // 如果找到了默认值,设置默认选项 | ||||
|             mLogLevelSpinner.setSelection(defaultValueIndex); | ||||
|         } | ||||
|  | ||||
|         // 加载标签列表 | ||||
|         Map<String, Boolean> mapTAGList = LogUtils.getMapTAGList(); | ||||
|         boolean isAllSelect = true; | ||||
|         for (Map.Entry<String, Boolean> entry : mapTAGList.entrySet()) { | ||||
|             if (entry.getValue() == false) { | ||||
|                 isAllSelect = false; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         CheckBox cbALLTAG = findViewById(cc.winboll.studio.libapputils.R.id.viewlogCheckBox1); | ||||
|         cbALLTAG.setChecked(isAllSelect); | ||||
|  | ||||
|         // 加载标签表 | ||||
|         recyclerView = findViewById(cc.winboll.studio.libapputils.R.id.viewlogRecyclerView1); | ||||
|         LinearLayoutManager layoutManager = new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false); | ||||
|         recyclerView.setLayoutManager(layoutManager); | ||||
|         mTAGListAdapter = new TAGListAdapter(mapTAGList); | ||||
|         recyclerView.setAdapter(mTAGListAdapter); | ||||
|  | ||||
|         // 可以添加点击监听器来处理勾选框状态变化后的逻辑,比如获取当前勾选情况等 | ||||
|         mTAGListAdapter.notifyDataSetChanged(); | ||||
|  | ||||
|         mSelectAllTAGCheckBox = findViewById(cc.winboll.studio.libapputils.R.id.viewlogCheckBox1); | ||||
|         mSelectAllTAGCheckBox.setOnClickListener(new View.OnClickListener(){ | ||||
|                 @Override | ||||
|                 public void onClick(View v) { | ||||
|                     LogUtils.setALlTAGListEnable(mSelectAllTAGCheckBox.isChecked()); | ||||
|                     //LogUtils.setALlTAGListEnable(false); | ||||
|                     //mTAGListAdapter.notifyDataSetChanged(); | ||||
|                     mTAGListAdapter.reload(); | ||||
|                     //ToastUtils.show(String.format("onClick\nmSelectAllTAGCheckBox.isChecked() : %s", mSelectAllTAGCheckBox.isChecked())); | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|  | ||||
|         // 设置滚动时不聚焦日志 | ||||
|         setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); | ||||
|     } | ||||
|  | ||||
|     public void updateLogView() { | ||||
|         if (mLogViewHandler.isHandling() == true) { | ||||
|             // 正在处理日志显示, | ||||
|             // 就先设置一个新日志标志位 | ||||
|             // 以便日志显示完后,再次显示新日志内容 | ||||
|             mLogViewHandler.setIsAddNewLog(true); | ||||
|         } else { | ||||
|             //LogUtils.d(TAG, "LogListener showLog(String path)"); | ||||
|             Message message = mLogViewHandler.obtainMessage(LogViewHandler.MSG_LOGVIEW_UPDATE); | ||||
|             mLogViewHandler.sendMessage(message); | ||||
|             mLogViewHandler.setIsAddNewLog(false); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void showAndScrollLogView() { | ||||
|         mTextView.setText(LogUtils.loadLog()); | ||||
|         scrollLogUp(); | ||||
|     } | ||||
|  | ||||
|     class LogViewHandler extends Handler { | ||||
|  | ||||
|         final static int MSG_LOGVIEW_UPDATE = 0; | ||||
|         volatile boolean isHandling; | ||||
|         volatile boolean isAddNewLog; | ||||
|  | ||||
|         public LogViewHandler() { | ||||
|             setIsHandling(false); | ||||
|             setIsAddNewLog(false); | ||||
|         } | ||||
|  | ||||
|         public void setIsHandling(boolean isHandling) { | ||||
|             this.isHandling = isHandling; | ||||
|         } | ||||
|  | ||||
|         public boolean isHandling() { | ||||
|             return isHandling; | ||||
|         } | ||||
|  | ||||
|         public void setIsAddNewLog(boolean isAddNewLog) { | ||||
|             this.isAddNewLog = isAddNewLog; | ||||
|         } | ||||
|  | ||||
|         public boolean isAddNewLog() { | ||||
|             return isAddNewLog; | ||||
|         } | ||||
|  | ||||
|         public void handleMessage(Message msg) { | ||||
|             switch (msg.what) { | ||||
|                 case MSG_LOGVIEW_UPDATE:{ | ||||
|                         if (isHandling() == false) { | ||||
|                             setIsHandling(true); | ||||
|                             showAndScrollLogView(); | ||||
|                         } | ||||
|                         break; | ||||
|                     } | ||||
|                 default: | ||||
|                     break; | ||||
|             } | ||||
|             super.handleMessage(msg); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public class TAGItemModel { | ||||
|         private String tag; | ||||
|         private boolean isChecked; | ||||
|  | ||||
|         public TAGItemModel(String tag, boolean isChecked) { | ||||
|             this.tag = tag; | ||||
|             this.isChecked = isChecked; | ||||
|         } | ||||
|  | ||||
|         public String getTag() { | ||||
|             return tag; | ||||
|         } | ||||
|  | ||||
|         public void setTag(String tag) { | ||||
|             this.tag = tag; | ||||
|         } | ||||
|  | ||||
|         public boolean isChecked() { | ||||
|             return isChecked; | ||||
|         } | ||||
|  | ||||
|         public void setChecked(boolean checked) { | ||||
|             isChecked = checked; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public class TAGListAdapter extends RecyclerView.Adapter<TAGListAdapter.ViewHolder> { | ||||
|  | ||||
|         private Map<String, Boolean> mapOrigin; | ||||
|         private List<TAGItemModel> itemList; | ||||
|  | ||||
|         public TAGListAdapter(Map<String, Boolean> map) { | ||||
|             mapOrigin = map; | ||||
|             loadMap(mapOrigin); | ||||
|         } | ||||
|  | ||||
|         void loadMap(Map<String, Boolean> map) { | ||||
|             itemList = new ArrayList<TAGItemModel>(); | ||||
|             for (Map.Entry<String, Boolean> entry : map.entrySet()) { | ||||
|                 itemList.add(new TAGItemModel(entry.getKey(), entry.getValue())); | ||||
|             } | ||||
|             // 添加排序功能,按照tag进行升序排序 | ||||
|             Collections.sort(itemList, new SortMapEntryByKeyString(true)); | ||||
|             //Collections.sort(itemList, new SortMapEntryByKeyString(false)); | ||||
|         } | ||||
|  | ||||
|         public void reload() { | ||||
|             loadMap(mapOrigin); | ||||
|             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); | ||||
|         } | ||||
|  | ||||
|         @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()); | ||||
|             holder.cbChecked.setOnClickListener(new View.OnClickListener(){ | ||||
|  | ||||
|                     @Override | ||||
|                     public void onClick(View v) { | ||||
|                         LogUtils.setTAGListEnable(item.getTag(), ((CheckBox)v).isChecked()); | ||||
|                     } | ||||
|                 }); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public int getItemCount() { | ||||
|             return itemList.size(); | ||||
|         } | ||||
|  | ||||
|         public class ViewHolder extends RecyclerView.ViewHolder { | ||||
|             TextView tvText; | ||||
|             CheckBox cbChecked; | ||||
|  | ||||
|             public ViewHolder(@NonNull View itemView) { | ||||
|                 super(itemView); | ||||
|                 tvText = itemView.findViewById(R.id.viewlogtagTextView1); | ||||
|                 cbChecked = itemView.findViewById(R.id.viewlogtagCheckBox1); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     class SortMapEntryByKeyString implements Comparator<TAGItemModel> { | ||||
|         private boolean mIsDesc = true; | ||||
|         // isDesc 是否降序排列 | ||||
|         public SortMapEntryByKeyString(boolean isDesc) { | ||||
|             mIsDesc = isDesc; | ||||
|         } | ||||
|         Collator cmp = Collator.getInstance(java.util.Locale.CHINA); | ||||
|         @Override | ||||
|         public int compare(TAGItemModel o1, TAGItemModel o2) { | ||||
|             if (mIsDesc) { | ||||
|                 return o1.getTag().compareTo(o2.getTag()); | ||||
|             } else { | ||||
|                 return o2.getTag().compareTo(o1.getTag()); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,80 +0,0 @@ | ||||
| package cc.winboll.studio.libapputils.log; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen@QQ.COM | ||||
|  * @Date 2024/08/12 14:43:50 | ||||
|  * @Describe 日志视图线程类 | ||||
|  */ | ||||
| import android.os.FileObserver; | ||||
| import cc.winboll.studio.libappbase.LogUtils; | ||||
| import java.lang.ref.WeakReference; | ||||
|  | ||||
| public class LogViewThread extends Thread { | ||||
|  | ||||
|     public static final String TAG = "LogViewThread"; | ||||
|  | ||||
|     // 线程退出标志 | ||||
|     volatile boolean isExist = false; | ||||
|     // 应用日志文件监听实例 | ||||
|     LogListener mLogListener; | ||||
|     // 日志视图弱引用 | ||||
|     WeakReference<LogView> mwrLogView; | ||||
|  | ||||
|     // | ||||
|     // 构造函数 | ||||
|     // @logView : 日志显示输出视图类 | ||||
|     public LogViewThread(LogView logView) { | ||||
|         mwrLogView = new WeakReference<LogView>(logView); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public void setIsExist(boolean isExist) { | ||||
|         this.isExist = isExist; | ||||
|     } | ||||
|  | ||||
|     public boolean isExist() { | ||||
|         return isExist; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void run() { | ||||
|         String szLogDir = LogUtils.getLogCacheDir().getPath(); | ||||
|         mLogListener = new LogListener(szLogDir); | ||||
|         mLogListener.startWatching(); | ||||
|         while (isExist() == false) { | ||||
|             try { | ||||
|                 Thread.sleep(1000); | ||||
|             } catch (InterruptedException e) {} | ||||
|         } | ||||
|         mLogListener.stopWatching(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     // | ||||
|     // 日志文件监听类 | ||||
|     // | ||||
|     class LogListener extends FileObserver { | ||||
|         public LogListener(String path) { | ||||
|             super(path); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void onEvent(int event, String path) { | ||||
|             int e = event & FileObserver.ALL_EVENTS; | ||||
|             switch (e) { | ||||
|                 case FileObserver.CLOSE_WRITE:{ | ||||
|                         if (mwrLogView.get() != null) { | ||||
|                             mwrLogView.get().updateLogView(); | ||||
|                         } | ||||
|                         break; | ||||
|                     } | ||||
|                 case FileObserver.DELETE:{ | ||||
|                         if (mwrLogView.get() != null) { | ||||
|                             mwrLogView.get().updateLogView(); | ||||
|                         } | ||||
|                         break; | ||||
|                     } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,34 +0,0 @@ | ||||
| package cc.winboll.studio.libapputils.view; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen@QQ.COM | ||||
|  * @Date 2025/02/06 09:02:28 | ||||
|  * @Describe 应用分支介绍按钮 | ||||
|  */ | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.util.AttributeSet; | ||||
| import android.view.View; | ||||
| import android.widget.Button; | ||||
| import cc.winboll.studio.libapputils.activities.AboutActivity; | ||||
| import cc.winboll.studio.libapputils.app.AboutActivityFactory; | ||||
| import cc.winboll.studio.libapputils.app.IWinBollActivity; | ||||
| import cc.winboll.studio.libapputils.app.WinBollActivityManager; | ||||
| import com.hjq.toast.ToastUtils; | ||||
| import java.util.regex.Matcher; | ||||
| import java.util.regex.Pattern; | ||||
|  | ||||
| public class AboutBranchButton extends Button { | ||||
|      | ||||
|     public static final String TAG = "AboutBranchButton"; | ||||
|      | ||||
|     public AboutBranchButton(final Context context, AttributeSet attrs) { | ||||
|         super(context, attrs); | ||||
|         setOnClickListener(new View.OnClickListener(){ | ||||
|                 @Override | ||||
|                 public void onClick(View view) { | ||||
|                     AboutActivityFactory.showAboutActivity(context, ((IWinBollActivity)context).getAppInfo()); | ||||
|                 } | ||||
|             }); | ||||
|     } | ||||
| } | ||||
| @@ -6,7 +6,7 @@ | ||||
| 	android:layout_width="match_parent" | ||||
| 	android:layout_height="match_parent"> | ||||
|  | ||||
|     <cc.winboll.studio.libapputils.log.LogView | ||||
|     <cc.winboll.studio.libappbase.LogView | ||||
|         android:orientation="horizontal" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="0dp" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 ZhanGSKen
					ZhanGSKen