Compare commits

..

4 Commits

Author SHA1 Message Date
ZhanGSKen
f02dc215ca <ollama>APK 15.0.0 release Publish. 2025-03-28 05:09:21 +08:00
ZhanGSKen
1c27d0ccdc Ollama 问答模块完成。 2025-03-28 05:04:15 +08:00
ZhanGSKen
803745d12e 添加简单http访问功能 2025-03-27 20:45:57 +08:00
ZhanGSKen
a66be9cd37 添加WinBoll Ollama 访问项目。 2025-03-27 19:39:54 +08:00
153 changed files with 1926 additions and 4140 deletions

View File

@@ -19,17 +19,17 @@ def genVersionName(def versionName){
android {
compileSdkVersion 32
buildToolsVersion "32.0.0"
buildToolsVersion "33.0.3"
defaultConfig {
applicationId "cc.winboll.studio.aes"
minSdkVersion 24
targetSdkVersion 29
targetSdkVersion 30
versionCode 1
// versionName 更新后需要手动设置
// 项目模块目录的 build.gradle 文件的 stageCount=0
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
versionName "15.2"
versionName "7.6"
if(true) {
versionName = genVersionName("${versionName}")
}
@@ -41,9 +41,29 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
}
dependencies {
api project(':libaes')
//api 'cc.winboll.studio:winboll-shared:1.6.5'
api 'io.github.medyo:android-about-page:2.0.0'
api 'com.github.getActivity:ToastUtils:10.5'
api 'com.jcraft:jsch:0.1.55'
api 'org.jsoup:jsoup:1.13.1'
api 'com.squareup.okhttp3:okhttp:4.4.1'
api 'androidx.appcompat:appcompat:1.0.0'
api 'androidx.fragment:fragment:1.0.0'
api 'com.google.android.material:material:1.0.0'
api 'cc.winboll.studio:libapputils:9.2.1'
api 'cc.winboll.studio:libappbase:1.0.3'
api fileTree(dir: 'libs', include: ['*.jar'])
}

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Mon Mar 31 02:04:47 HKT 2025
stageCount=4
#Sun Jan 19 04:58:59 GMT 2025
stageCount=3
libraryProject=libaes
baseVersion=15.2
publishVersion=15.2.3
buildCount=0
baseBetaVersion=15.2.4
baseVersion=7.6
publishVersion=7.6.2
buildCount=4
baseBetaVersion=7.6.3

View File

@@ -8,10 +8,9 @@
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/MyAESTheme"
android:theme="@style/WinBoll.SupportThemeNoActionBar"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
android:networkSecurityConfig="@xml/network_security_config">
android:supportsRtl="true">
<activity
android:name=".MainActivity"
@@ -31,8 +30,6 @@
android:name="android.max_aspect"
android:value="4.0"/>
<activity android:name=".AboutActivity"/>
</application>
</manifest>

View File

@@ -1,91 +0,0 @@
package cc.winboll.studio.aes;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/24 23:52:29
* @Describe AES应用介绍窗口
*/
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.libaes.winboll.APPInfo;
import cc.winboll.studio.libaes.winboll.AboutView;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
public class AboutActivity extends WinBollActivity implements IWinBollActivity {
public static final String TAG = "AboutActivity";
Context mContext;
Toolbar mToolbar;
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
setContentView(R.layout.activity_about);
mToolbar = findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
mToolbar.setSubtitle(TAG);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
AboutView aboutView = CreateAboutView();
// 在 Activity 的 onCreate 或其他生命周期方法中调用
// LinearLayout layout = new LinearLayout(this);
// layout.setOrientation(LinearLayout.VERTICAL);
// // 创建布局参数(宽度和高度)
// ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
// ViewGroup.LayoutParams.MATCH_PARENT,
// ViewGroup.LayoutParams.MATCH_PARENT
// );
// addContentView(aboutView, params);
LinearLayout layout = findViewById(R.id.aboutviewroot_ll);
// 创建布局参数(宽度和高度)
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
);
layout.addView(aboutView, params);
GlobalApplication.getWinBollActivityManager().add(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
GlobalApplication.getWinBollActivityManager().registeRemove(this);
}
public AboutView CreateAboutView() {
String szBranchName = "aes";
APPInfo appInfo = new APPInfo();
appInfo.setAppName("AES");
appInfo.setAppIcon(cc.winboll.studio.libaes.R.drawable.ic_winboll);
appInfo.setAppDescription("AES Description");
appInfo.setAppGitName("APP");
appInfo.setAppGitOwner("Studio");
appInfo.setAppGitAPPBranch(szBranchName);
appInfo.setAppGitAPPSubProjectFolder(szBranchName);
appInfo.setAppHomePage("https://www.winboll.cc/studio/details.php?app=AES");
appInfo.setAppAPKName("AES");
appInfo.setAppAPKFolderName("AES");
return new AboutView(mContext, appInfo);
}
}

View File

@@ -6,8 +6,6 @@ package cc.winboll.studio.aes;
* @Describe AES应用类
*/
import cc.winboll.studio.libappbase.GlobalApplication;
import com.hjq.toast.ToastUtils;
public class App extends GlobalApplication {
@@ -16,8 +14,7 @@ public class App extends GlobalApplication {
@Override
public void onCreate() {
super.onCreate();
ToastUtils.init(this);
//ToastUtils.show("App onCreate");
//setIsDebug(BuildConfig.DEBUG);
}
}

View File

@@ -5,193 +5,12 @@ package cc.winboll.studio.aes;
* @Date 2024/06/13 19:05:52
* @Describe 应用主窗口
*/
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Toast;
import cc.winboll.studio.aes.R;
import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity;
import cc.winboll.studio.libaes.beans.DrawerMenuBean;
import cc.winboll.studio.libaes.dialogs.LocalFileSelectDialog;
import cc.winboll.studio.libaes.dialogs.StoragePathDialog;
import cc.winboll.studio.libaes.unittests.SecondaryLibraryActivity;
import cc.winboll.studio.libaes.unittests.TestAButtonFragment;
import cc.winboll.studio.libaes.unittests.TestASupportToolbarActivity;
import cc.winboll.studio.libaes.unittests.TestAToolbarActivity;
import cc.winboll.studio.libaes.unittests.TestDrawerFragmentActivity;
import cc.winboll.studio.libaes.unittests.TestViewPageFragment;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import com.a4455jkjh.colorpicker.ColorPickerDialog;
import com.hjq.toast.ToastUtils;
import java.util.ArrayList;
import cc.winboll.studio.libaes.unittests.LibraryActivity;
public class MainActivity extends DrawerFragmentActivity implements IWinBollActivity {
public static final String TAG = "MainActivity";
TestAButtonFragment mTestAButtonFragment;
TestViewPageFragment mTestViewPageFragment;
public class MainActivity extends LibraryActivity {
public static final String TAG = "MainActivity";
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (mTestAButtonFragment == null) {
mTestAButtonFragment = new TestAButtonFragment();
addFragment(mTestAButtonFragment);
}
showFragment(mTestAButtonFragment);
//setSubtitle(TAG);
//ToastUtils.show("onCreate");
}
@Override
public void initDrawerMenuItemList(ArrayList<DrawerMenuBean> listDrawerMenu) {
super.initDrawerMenuItemList(listDrawerMenu);
LogUtils.d(TAG, "initDrawerMenuItemList");
//listDrawerMenu.clear();
// 添加抽屉菜单项
listDrawerMenu.add(new DrawerMenuBean(R.drawable.ic_launcher, TestAButtonFragment.TAG));
listDrawerMenu.add(new DrawerMenuBean(R.drawable.ic_launcher, TestViewPageFragment.TAG));
notifyDrawerMenuDataChanged();
}
@Override
public void reinitDrawerMenuItemList(ArrayList<DrawerMenuBean> listDrawerMenu) {
super.reinitDrawerMenuItemList(listDrawerMenu);
LogUtils.d(TAG, "reinitDrawerMenuItemList");
//listDrawerMenu.clear();
// 添加抽屉菜单项
listDrawerMenu.add(new DrawerMenuBean(R.drawable.ic_launcher, TestAButtonFragment.TAG));
listDrawerMenu.add(new DrawerMenuBean(R.drawable.ic_launcher, TestViewPageFragment.TAG));
notifyDrawerMenuDataChanged();
}
@Override
public DrawerFragmentActivity.ActivityType initActivityType() {
return DrawerFragmentActivity.ActivityType.Main;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar_library, menu);
if(App.isDebuging()) {
getMenuInflater().inflate(cc.winboll.studio.libapputils.R.menu.toolbar_studio_debug, menu);
}
return super.onCreateOptionsMenu(menu);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
super.onItemClick(parent, view, position, id);
switch (position) {
case 0 : {
if (mTestAButtonFragment == null) {
mTestAButtonFragment = new TestAButtonFragment();
addFragment(mTestAButtonFragment);
}
showFragment(mTestAButtonFragment);
break;
}
case 1 : {
if (mTestViewPageFragment == null) {
mTestViewPageFragment = new TestViewPageFragment();
addFragment(mTestViewPageFragment);
}
showFragment(mTestViewPageFragment);
break;
}
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int nItemId = item.getItemId();
// if (item.getItemId() == R.id.item_log) {
// WinBollActivityManager.getInstance(this).startWinBollActivity(getApplicationContext(), LogActivity.class);
// } else
if (nItemId == R.id.item_atoast) {
Toast.makeText(getApplication(), "item_testatoast", Toast.LENGTH_SHORT).show();
} else if (nItemId == R.id.item_atoolbar) {
Intent intent = new Intent(this, TestAToolbarActivity.class);
startActivity(intent);
} else if (nItemId == R.id.item_asupporttoolbar) {
Intent intent = new Intent(this, TestASupportToolbarActivity.class);
startActivity(intent);
} else if (nItemId == R.id.item_colordialog) {
ColorPickerDialog dlg = new ColorPickerDialog(this, getResources().getColor(R.color.colorPrimary));
dlg.setOnColorChangedListener(new com.a4455jkjh.colorpicker.view.OnColorChangedListener() {
@Override
public void beforeColorChanged() {
}
@Override
public void onColorChanged(int color) {
}
@Override
public void afterColorChanged() {
}
});
dlg.show();
} else if (nItemId == R.id.item_dialogstoragepath) {
final StoragePathDialog dialog = new StoragePathDialog(this, 0);
dialog.setOnOKClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
} else if (nItemId == R.id.item_localfileselectdialog) {
final LocalFileSelectDialog dialog = new LocalFileSelectDialog(this);
dialog.setOnOKClickListener(new LocalFileSelectDialog.OKClickListener() {
@Override
public void onOKClick(String sz) {
Toast.makeText(getApplication(), sz, Toast.LENGTH_SHORT).show();
//dialog.dismiss();
}
});
dialog.open();
} else if (nItemId == R.id.item_secondarylibraryactivity) {
Intent intent = new Intent(this, SecondaryLibraryActivity.class);
startActivity(intent);
} else if (nItemId == R.id.item_drawerfragmentactivity) {
Intent intent = new Intent(this, TestDrawerFragmentActivity.class);
startActivity(intent);
}
else if (nItemId == R.id.item_about) {
Intent intent = new Intent(this, AboutActivity.class);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
}

View File

@@ -1,50 +0,0 @@
package cc.winboll.studio.aes;
import android.app.Activity;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import cc.winboll.studio.libaes.beans.AESThemeBean;
import cc.winboll.studio.libaes.utils.AESThemeUtil;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/30 00:34:02
* @Describe WinBoll 活动窗口通用基类
*/
public class WinBollActivity extends AppCompatActivity implements IWinBollActivity {
public static final String TAG = "WinBollActivity";
protected volatile AESThemeBean.ThemeType mThemeType;
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
mThemeType = getThemeType();
setThemeStyle();
super.onCreate(savedInstanceState);
}
AESThemeBean.ThemeType getThemeType() {
/*SharedPreferences sharedPreferences = getSharedPreferences(
SHAREDPREFERENCES_NAME, MODE_PRIVATE);
return AESThemeBean.ThemeType.values()[((sharedPreferences.getInt(DRAWER_THEME_TYPE, AESThemeBean.ThemeType.DEFAULT.ordinal())))];
*/
return AESThemeBean.getThemeStyleType(AESThemeUtil.getThemeTypeID(getApplicationContext()));
}
void setThemeStyle() {
//setTheme(AESThemeBean.getThemeStyle(getThemeType()));
setTheme(AESThemeUtil.getThemeTypeID(getApplicationContext()));
}
}

View File

@@ -1,22 +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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<cc.winboll.studio.libaes.views.ASupportToolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/toolbar"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0"
android:id="@+id/aboutviewroot_ll"/>
</LinearLayout>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#FF00B322</color>
<color name="colorPrimaryDark">#FF005C12</color>
<color name="colorAccent">#FF8DFFA2</color>
<color name="colorText">#FFFFFB8D</color>
</resources>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MyAESTheme" parent="AESTheme">
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
</style>
</resources>

View File

@@ -23,7 +23,7 @@ android {
defaultConfig {
applicationId "cc.winboll.studio.androiddemo"
minSdkVersion 24
minSdkVersion 26
targetSdkVersion 29
versionCode 1
// versionName 更新后需要手动设置
@@ -46,11 +46,11 @@ android {
dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
// 吐司类库
api 'com.github.getActivity:ToastUtils:10.5'
// Android 类库
//api 'com.android.support:appcompat-v7:28.0.0'
api('com.android.support:appcompat-v7:28.0.0'){
exclude group: "com.android.support", module: "support-vector-drawable"
}
api 'com.android.support:appcompat-v7:28.0.0' // 包含 AppCompatActivity
// https://mvnrepository.com/artifact/com.android.support/support-compat
api 'com.android.support:support-compat:28.0.0' // 保留原有依赖(可选)
// https://mvnrepository.com/artifact/com.android.support/support-v4
@@ -66,6 +66,6 @@ dependencies {
// https://mvnrepository.com/artifact/com.android.support/recyclerview-v7
api 'com.android.support:recyclerview-v7:28.0.0'
api 'cc.winboll.studio:libapputils:15.2.1'
api 'cc.winboll.studio:libappbase:15.2.2'
api 'cc.winboll.studio:libappbase:15.0.9'
api 'cc.winboll.studio:libapputils:15.0.11'
}

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Sat Mar 29 04:34:14 GMT 2025
#Wed Mar 26 07:23:51 GMT 2025
stageCount=0
libraryProject=
baseVersion=15.0
publishVersion=15.0.0
buildCount=15
buildCount=11
baseBetaVersion=15.0.1

View File

@@ -23,7 +23,7 @@ android {
defaultConfig {
applicationId "cc.winboll.studio.androidxdemo"
minSdkVersion 24
minSdkVersion 26
targetSdkVersion 29
versionCode 1
// versionName 更新后需要手动设置
@@ -60,14 +60,13 @@ dependencies {
// 网络连接类库
api 'com.squareup.okhttp3:okhttp:4.4.1'
// AndroidX 类库
api 'androidx.appcompat:appcompat:1.1.0'
api 'androidx.appcompat:appcompat:1.0.0'
api 'com.google.android.material:material:1.4.0'
//api 'androidx.viewpager:viewpager:1.0.0'
//api 'androidx.vectordrawable:vectordrawable:1.1.0'
//api 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
//api 'androidx.fragment:fragment:1.1.0'
api 'cc.winboll.studio:libaes:15.2.3'
api 'cc.winboll.studio:libapputils:15.2.1'
api 'cc.winboll.studio:libappbase:15.2.2'
api 'cc.winboll.studio:libappbase:15.0.9'
api 'cc.winboll.studio:libapputils:15.0.11'
}

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Mon Mar 31 03:57:35 GMT 2025
#Mon Mar 24 06:19:57 GMT 2025
stageCount=0
libraryProject=
baseVersion=15.0
publishVersion=15.0.0
buildCount=12
buildCount=8
baseBetaVersion=15.0.1

View File

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

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Sat Mar 29 11:28:02 HKT 2025
stageCount=3
#Thu Mar 27 10:59:31 GMT 2025
stageCount=1
libraryProject=libappbase
baseVersion=15.2
publishVersion=15.2.2
buildCount=0
baseBetaVersion=15.2.3
baseVersion=15.1
publishVersion=15.1.0
buildCount=130
baseBetaVersion=15.1.1

View File

@@ -32,15 +32,12 @@
</activity>
<activity
android:name=".activities.NewActivity"
android:label="NewActivity"
<activity android:name=".activities.NewActivity"
android:exported="true"
android:resizeableActivity="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"/>
<activity android:name=".activities.New2Activity"
android:label="New2Activity"
android:exported="true"
android:resizeableActivity="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"/>

View File

@@ -1,10 +1,12 @@
package cc.winboll.studio.appbase;
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.ComponentName;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -14,17 +16,17 @@ import cc.winboll.studio.appbase.activities.NewActivity;
import cc.winboll.studio.appbase.services.MainService;
import cc.winboll.studio.appbase.services.TestDemoBindService;
import cc.winboll.studio.appbase.services.TestDemoService;
import cc.winboll.studio.libappbase.CrashHandler;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.GlobalCrashActivity;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.sos.SOS;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import cc.winboll.studio.libappbase.widgets.StatusWidget;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import cc.winboll.studio.libappbase.dialogs.YesNoAlertDialog;
import cc.winboll.studio.libappbase.winboll.LogActivity;
import cc.winboll.studio.libappbase.winboll.WinBollActivityManager;
import android.support.v7.widget.Toolbar;
public class MainActivity extends WinBollActivityBase implements IWinBollActivity {
public class MainActivity extends AppCompatActivity implements IWinBollActivity {
public static final String TAG = "MainActivity";
@@ -69,6 +71,12 @@ public class MainActivity extends WinBollActivityBase implements IWinBollActivit
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == cc.winboll.studio.appbase.R.id.item_log) {
WinBollActivityManager.getInstance(this).startLogActivity(this);
return true;
} else if(item.getItemId() == cc.winboll.studio.appbase.R.id.item_minimal) {
moveTaskToBack(true);
}
// 在switch语句中处理每个ID并在处理完后返回true未处理的情况返回false。
return super.onOptionsItemSelected(item);
}
@@ -86,13 +94,6 @@ public class MainActivity extends WinBollActivityBase implements IWinBollActivit
public void onSwitchDebugMode(View view) {
boolean isDebuging = ((CheckBox)view).isChecked();
GlobalApplication.setIsDebuging(isDebuging);
GlobalApplication.saveDebugStatus();
}
public void onPreviewGlobalCrashActivity(View view) {
Intent intent = new Intent(this, GlobalCrashActivity.class);
intent.putExtra(CrashHandler.EXTRA_CRASH_INFO, "Demo log...");
startActivity(intent);
}
public void onStartCenter(View view) {
@@ -138,8 +139,6 @@ public class MainActivity extends WinBollActivityBase implements IWinBollActivit
startService(intent);
}
public void onStopTestDemoService(View view) {
Intent intent = new Intent(this, TestDemoService.class);
@@ -177,7 +176,7 @@ public class MainActivity extends WinBollActivityBase implements IWinBollActivit
}
public void onTestOpenNewActivity(View view) {
GlobalApplication.getWinBollActivityManager().startWinBollActivity(this, NewActivity.class);
WinBollActivityManager.getInstance(this).startWinBollActivity(this, NewActivity.class);
}

View File

@@ -1,82 +0,0 @@
package cc.winboll.studio.appbase;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 15:34:16
* @Describe 应用活动窗口基类
*/
import android.app.Activity;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import cc.winboll.studio.appbase.App;
import cc.winboll.studio.appbase.R;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.dialogs.YesNoAlertDialog;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import cc.winboll.studio.libappbase.winboll.WinBollActivityManager;
public class WinBollActivityBase extends AppCompatActivity implements IWinBollActivity {
public static final String TAG = "WinBollActivityBase";
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
WinBollActivityManager getWinBollActivityManager() {
return WinBollActivityManager.getInstance(GlobalApplication.getInstance());
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWinBollActivityManager().add(this);
}
@Override
public void onPostCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onPostCreate(savedInstanceState, persistentState);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == cc.winboll.studio.appbase.R.id.item_log) {
GlobalApplication.getWinBollActivityManager().startLogActivity(this);
return true;
} else if(item.getItemId() == cc.winboll.studio.appbase.R.id.item_minimal) {
//moveTaskToBack(true);
exit();
}
// 在switch语句中处理每个ID并在处理完后返回true未处理的情况返回false。
return super.onOptionsItemSelected(item);
}
void exit() {
YesNoAlertDialog.show(this, "Exit " + getString(R.string.app_name), "Close all activity and exit?", new YesNoAlertDialog.OnDialogResultListener(){
@Override
public void onYes() {
App.getWinBollActivityManager().finishAll();
}
@Override
public void onNo() {
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
getWinBollActivityManager().registeRemove(this);
}
}

View File

@@ -7,16 +7,16 @@ package cc.winboll.studio.appbase.activities;
*/
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import cc.winboll.studio.appbase.R;
import cc.winboll.studio.appbase.WinBollActivityBase;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import cc.winboll.studio.libappbase.winboll.WinBollActivityManager;
public class New2Activity extends WinBollActivityBase implements IWinBollActivity {
public class New2Activity extends AppCompatActivity implements IWinBollActivity {
public static final String TAG = "New2Activity";
@@ -52,15 +52,15 @@ public class New2Activity extends WinBollActivityBase implements IWinBollActivit
}
public void onCloseThisActivity(View view) {
GlobalApplication.getWinBollActivityManager().finish(this);
WinBollActivityManager.getInstance(this).finish(this);
}
public void onCloseAllActivity(View view) {
GlobalApplication.getWinBollActivityManager().finishAll();
WinBollActivityManager.getInstance(this).finishAll();
}
public void onNewActivity(View view) {
GlobalApplication.getWinBollActivityManager().startWinBollActivity(this, NewActivity.class);
WinBollActivityManager.getInstance(this).startWinBollActivity(this, NewActivity.class);
}
@@ -74,8 +74,10 @@ public class New2Activity extends WinBollActivityBase implements IWinBollActivit
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == cc.winboll.studio.appbase.R.id.item_log) {
GlobalApplication.getWinBollActivityManager().startLogActivity(this);
WinBollActivityManager.getInstance(this).startLogActivity(this);
return true;
} else if(item.getItemId() == cc.winboll.studio.appbase.R.id.item_minimal) {
moveTaskToBack(true);
}
// 在switch语句中处理每个ID并在处理完后返回true未处理的情况返回false。
return super.onOptionsItemSelected(item);

View File

@@ -6,16 +6,16 @@ package cc.winboll.studio.appbase.activities;
*/
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import cc.winboll.studio.appbase.R;
import cc.winboll.studio.appbase.WinBollActivityBase;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import cc.winboll.studio.libappbase.winboll.WinBollActivityManager;
public class NewActivity extends WinBollActivityBase implements IWinBollActivity {
public class NewActivity extends AppCompatActivity implements IWinBollActivity {
public static final String TAG = "NewActivity";
@@ -50,15 +50,15 @@ public class NewActivity extends WinBollActivityBase implements IWinBollActivity
}
public void onCloseThisActivity(View view) {
GlobalApplication.getWinBollActivityManager().finish(this);
WinBollActivityManager.getInstance(this).finish(this);
}
public void onCloseAllActivity(View view) {
GlobalApplication.getWinBollActivityManager().finishAll();
WinBollActivityManager.getInstance(this).finishAll();
}
public void onNew2Activity(View view) {
GlobalApplication.getWinBollActivityManager().startWinBollActivity(this, New2Activity.class);
WinBollActivityManager.getInstance(this).startWinBollActivity(this, New2Activity.class);
}
@@ -72,8 +72,10 @@ public class NewActivity extends WinBollActivityBase implements IWinBollActivity
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == cc.winboll.studio.appbase.R.id.item_log) {
GlobalApplication.getWinBollActivityManager().startLogActivity(this);
WinBollActivityManager.getInstance(this).startLogActivity(this);
return true;
} else if(item.getItemId() == cc.winboll.studio.appbase.R.id.item_minimal) {
moveTaskToBack(true);
}
// 在switch语句中处理每个ID并在处理完后返回true未处理的情况返回false。
return super.onOptionsItemSelected(item);

View File

@@ -39,41 +39,28 @@
android:layout_height="wrap_content"
android:text="Android版本10的代号是“Q”API级别是29。 Android 10开始谷歌不再公开使用甜品作为版本代号但内部仍保留了大量与“Q”相关的元素。Android 10本身并没有严格对应某个特定的Java版本但在开发Android 10应用时通常可以使用Java 8或更高版本。 Java 8为Android开发带来了诸如Lambda表达式、方法引用等新特性能提高开发效率和代码可读性与Android 10开发适配良好。Java 9及更高版本也可用于Android 10开发能使用一些新的语言特性和API但可能需要注意兼容性和配置问题。"/>
<HorizontalScrollView
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:gravity="right|center_vertical">
<LinearLayout
android:orientation="horizontal"
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right|center_vertical"
android:layout_width="wrap_content">
android:text="Debug Mode"
android:layout_weight="1.0"
android:onClick="onSwitchDebugMode"
android:id="@+id/activitymainCheckBox1"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Debug Mode"
android:layout_weight="1.0"
android:onClick="onSwitchDebugMode"
android:id="@+id/activitymainCheckBox1"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test Application CrashReport"
android:textAllCaps="false"
android:onClick="onTestApplicationCrashReport"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test Application CrashReport"
android:textAllCaps="false"
android:onClick="onTestApplicationCrashReport"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="PreviewGlobalCrashActivity"
android:textAllCaps="false"
android:onClick="onPreviewGlobalCrashActivity"/>
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
<ScrollView
android:layout_width="match_parent"
@@ -85,27 +72,26 @@
android:layout_height="wrap_content"
android:gravity="right">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="StartCenter"
android:textAllCaps="false"
android:onClick="onStartCenter"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="StopCenter"
android:textAllCaps="false"
android:onClick="onStopCenter"/>
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="StartCenter"
android:textAllCaps="false"
android:onClick="onStartCenter"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="StopCenter"
android:textAllCaps="false"
android:onClick="onStopCenter"/>
</LinearLayout>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
@@ -174,6 +160,7 @@
</HorizontalScrollView>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -194,14 +181,14 @@
android:text="TestDemoServiceSOS"
android:textAllCaps="false"
android:onClick="onTestDemoServiceSOS"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TestOpenNewActivity"
android:textAllCaps="false"
android:onClick="onTestOpenNewActivity"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TestOpenNewActivity"
android:textAllCaps="false"
android:onClick="onTestOpenNewActivity"/>
</LinearLayout>
</ScrollView>
@@ -211,6 +198,6 @@
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@@ -4,12 +4,14 @@ apply from: '../.winboll/winboll_lib_build.gradle'
apply from: '../.winboll/winboll_lint_build.gradle'
android {
namespace 'cc.winboll.studio.libaes'
compileSdkVersion 32
buildToolsVersion "32.0.0"
buildToolsVersion "33.0.3"
defaultConfig {
minSdkVersion 24
targetSdkVersion 29
targetSdkVersion 30
}
buildTypes {
release {
@@ -17,40 +19,30 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
}
dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
//api 'cc.winboll.studio:winboll-shared:1.6.5'
// 吐司类库
api 'com.github.getActivity:ToastUtils:10.5'
// 权限请求框架https://github.com/getActivity/XXPermissions
api 'com.github.getActivity:XXPermissions:18.63'
// 下拉控件
api 'com.baoyz.pullrefreshlayout:library:1.2.0'
// 拼音搜索
// https://mvnrepository.com/artifact/com.github.open-android/pinyin4j
api 'com.github.open-android:pinyin4j:2.5.0'
// SSH
api 'com.jcraft:jsch:0.1.55'
// Html 解析
api 'org.jsoup:jsoup:1.13.1'
// 二维码类库
api 'com.google.zxing:core:3.4.1'
api 'com.journeyapps:zxing-android-embedded:3.6.0'
// 应用介绍页类库
api 'io.github.medyo:android-about-page:2.0.0'
// 网络连接类库
api 'com.github.getActivity:ToastUtils:10.5'
api 'com.jcraft:jsch:0.1.55'
api 'org.jsoup:jsoup:1.13.1'
api 'com.squareup.okhttp3:okhttp:4.4.1'
// AndroidX 类库
api 'androidx.appcompat:appcompat:1.1.0'
api 'com.google.android.material:material:1.4.0'
//api 'androidx.viewpager:viewpager:1.0.0'
//api 'androidx.vectordrawable:vectordrawable:1.1.0'
//api 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
//api 'androidx.fragment:fragment:1.1.0'
api 'cc.winboll.studio:libappbase:15.2.0'
api 'cc.winboll.studio:libapputils:15.2.0'
api 'androidx.appcompat:appcompat:1.0.0'
api 'androidx.fragment:fragment:1.0.0'
api 'com.google.android.material:material:1.0.0'
// https://github.com/baoyongzhang/android-PullRefreshLayout
api 'com.baoyz.pullrefreshlayout:library:1.2.0'
api 'cc.winboll.studio:libapputils:9.2.1'
api 'cc.winboll.studio:libappbase:1.0.3'
api fileTree(dir: 'libs', include: ['*.jar'])
}

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Mon Mar 31 02:04:35 HKT 2025
stageCount=4
#Sun Jan 19 04:58:59 GMT 2025
stageCount=3
libraryProject=libaes
baseVersion=15.2
publishVersion=15.2.3
buildCount=0
baseBetaVersion=15.2.4
baseVersion=7.6
publishVersion=7.6.2
buildCount=4
baseBetaVersion=7.6.3

View File

@@ -5,27 +5,16 @@
<application>
<activity android:name="cc.winboll.studio.libaes.unittests.SecondaryLibraryActivity"
android:exported="true"/>
<activity android:name="cc.winboll.studio.libaes.unittests.SecondaryLibraryActivity"/>
<activity android:name="cc.winboll.studio.libaes.unittests.TestDrawerFragmentActivity"
android:exported="true"/>
<activity android:name="cc.winboll.studio.libaes.activitys.AboutActivity"/>
<activity android:name="cc.winboll.studio.libaes.unittests.TestAToolbarActivity"
android:exported="true"/>
<activity android:name="cc.winboll.studio.libaes.unittests.TestASupportToolbarActivity"
android:exported="true"/>
<service android:name="cc.winboll.studio.libaes.winboll.WinBollClientService"
android:exported="true"/>
<service android:name="cc.winboll.studio.libaes.winboll.AssistantService"
android:exported="true"/>
<service android:name="cc.winboll.studio.libaes.winboll.WinBollMail"
android:exported="true"/>
<activity android:name="cc.winboll.studio.libaes.unittests.TestDrawerFragmentActivity"/>
<activity android:name="cc.winboll.studio.libaes.unittests.TestAToolbarActivity"/>
<activity android:name="cc.winboll.studio.libaes.unittests.TestASupportToolbarActivity"/>
</application>
</manifest>

View File

@@ -27,20 +27,18 @@ import cc.winboll.studio.libaes.beans.AESThemeBean;
import cc.winboll.studio.libaes.beans.DrawerMenuBean;
import cc.winboll.studio.libaes.utils.AESThemeUtil;
import cc.winboll.studio.libaes.views.ADrawerMenuListView;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import cc.winboll.studio.libapputils.log.LogUtils;
import com.baoyz.widget.PullRefreshLayout;
import java.util.ArrayList;
public abstract class DrawerFragmentActivity extends AppCompatActivity implements IWinBollActivity,AdapterView.OnItemClickListener {
public abstract class DrawerFragmentActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
public static final String TAG = "DrawerFragmentActivity";
static final String SHAREDPREFERENCES_NAME = "SHAREDPREFERENCES_NAME";
static final String DRAWER_THEME_TYPE = "DRAWER_THEME_TYPE";
//protected Context mContext;
protected Context mContext;
ActivityType mActivityType;
ActionBarDrawerToggle mActionBarDrawerToggle;
DrawerLayout mDrawerLayout;
@@ -60,7 +58,7 @@ public abstract class DrawerFragmentActivity extends AppCompatActivity implement
@Override
protected void onCreate(Bundle savedInstanceState) {
//mContext = this;
mContext = this;
mThemeType = getThemeType();
setThemeStyle();
super.onCreate(savedInstanceState);
@@ -74,7 +72,7 @@ public abstract class DrawerFragmentActivity extends AppCompatActivity implement
super.onDestroy();
}
/*@Override
@Override
public Intent getIntent() {
// TODO: Implement this method
return super.getIntent();
@@ -82,7 +80,7 @@ public abstract class DrawerFragmentActivity extends AppCompatActivity implement
public Context getContext() {
return this.mContext;
}*/
}
@Override
public MenuInflater getMenuInflater() {
@@ -90,20 +88,20 @@ public abstract class DrawerFragmentActivity extends AppCompatActivity implement
return super.getMenuInflater();
}
/*public void setSubtitle(CharSequence context) {
public void setSubtitle(CharSequence context) {
// TODO: Implement this method
getSupportActionBar().setSubtitle(context);
}*/
}
@Override
public void recreate() {
super.recreate();
}
/*@Override
@Override
public boolean moveTaskToBack(boolean nonRoot) {
return super.moveTaskToBack(nonRoot);
}*/
}
@Override
public void startActivity(Intent intent) {
@@ -115,7 +113,7 @@ public abstract class DrawerFragmentActivity extends AppCompatActivity implement
super.startActivityForResult(intent, requestCode, options);
}
/*@Override
@Override
public FragmentManager getSupportFragmentManager() {
return super.getSupportFragmentManager();
}
@@ -133,7 +131,7 @@ public abstract class DrawerFragmentActivity extends AppCompatActivity implement
public void setTitle(int resId) {
// TODO: Implement this method
getSupportActionBar().setTitle(resId);
}*/
}
@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
@@ -153,7 +151,7 @@ public abstract class DrawerFragmentActivity extends AppCompatActivity implement
void setThemeStyle() {
//setTheme(AESThemeBean.getThemeStyle(getThemeType()));
setTheme(AESThemeUtil.getThemeTypeID(getApplicationContext()));
setTheme(AESThemeUtil.getThemeTypeID(this));
}
boolean checkThemeStyleChange() {
@@ -165,7 +163,7 @@ public abstract class DrawerFragmentActivity extends AppCompatActivity implement
SHAREDPREFERENCES_NAME, MODE_PRIVATE);
return AESThemeBean.ThemeType.values()[((sharedPreferences.getInt(DRAWER_THEME_TYPE, AESThemeBean.ThemeType.DEFAULT.ordinal())))];
*/
return AESThemeBean.getThemeStyleType(AESThemeUtil.getThemeTypeID(getApplicationContext()));
return AESThemeBean.getThemeStyleType(AESThemeUtil.getThemeTypeID(this));
}
@Override
@@ -176,8 +174,6 @@ public abstract class DrawerFragmentActivity extends AppCompatActivity implement
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
getString(i);
}
} else if (R.id.item_log == item.getItemId()) {
GlobalApplication.getWinBollActivityManager().startLogActivity(this);
} else if (R.id.item_about == item.getItemId()) {
LogUtils.d(TAG, "onAbout");
} else if (android.R.id.home == item.getItemId()) {

View File

@@ -8,7 +8,7 @@ package cc.winboll.studio.libaes.beans;
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libappbase.BaseBean;
import cc.winboll.studio.libapputils.bean.BaseBean;
import java.io.IOException;
public class AESThemeBean extends BaseBean {
@@ -16,7 +16,7 @@ public class AESThemeBean extends BaseBean {
public static final String TAG = "AESThemeBean";
public enum ThemeType {
AES("默认主题"),
DEFAULT("默认主题"),
DEPTH("深奥主题"),
SKY("天空主题"),
GOLDEN("辉煌主题"),
@@ -42,7 +42,7 @@ public class AESThemeBean extends BaseBean {
}
// 保存当前主题
int currentThemeStyleID = getThemeStyleID(ThemeType.AES);
int currentThemeStyleID = getThemeStyleID(ThemeType.DEFAULT);
public AESThemeBean() {
}
@@ -99,7 +99,7 @@ public class AESThemeBean extends BaseBean {
}
public static int getThemeStyleID(ThemeType themeType) {
int themeStyleID = R.style.AESTheme;
int themeStyleID = R.style.DefaultAESTheme;
if (AESThemeBean.ThemeType.DEPTH == themeType) {
themeStyleID = R.style.DepthAESTheme;
} else if (AESThemeBean.ThemeType.SKY == themeType) {
@@ -110,15 +110,15 @@ public class AESThemeBean extends BaseBean {
themeStyleID = R.style.MemorAESTheme;
} else if (AESThemeBean.ThemeType.TAO == themeType) {
themeStyleID = R.style.TaoAESTheme;
} else if (AESThemeBean.ThemeType.AES == themeType) {
themeStyleID = R.style.AESTheme;
} else if (AESThemeBean.ThemeType.DEFAULT == themeType) {
themeStyleID = R.style.DefaultAESTheme;
}
//LogUtils.d(TAG, "themeStyleID " + Integer.toString(themeStyleID));
return themeStyleID;
}
public static AESThemeBean.ThemeType getThemeStyleType(int nThemeStyleID) {
AESThemeBean.ThemeType themeStyle = AESThemeBean.ThemeType.AES;
AESThemeBean.ThemeType themeStyle = AESThemeBean.ThemeType.DEFAULT;
if (R.style.DepthAESTheme == nThemeStyleID) {
themeStyle = AESThemeBean.ThemeType.DEPTH ;
} else if (R.style.SkyAESTheme == nThemeStyleID) {
@@ -129,8 +129,8 @@ public class AESThemeBean extends BaseBean {
themeStyle = AESThemeBean.ThemeType.MEMOR ;
} else if (R.style.TaoAESTheme == nThemeStyleID) {
themeStyle = AESThemeBean.ThemeType.TAO ;
} else if (R.style.AESTheme == nThemeStyleID) {
themeStyle = AESThemeBean.ThemeType.AES;
} else if (R.style.DefaultAESTheme == nThemeStyleID) {
themeStyle = AESThemeBean.ThemeType.DEFAULT;
}
//LogUtils.d(TAG, "themeStyle " + Integer.toString(themeStyle.ordinal()));
return themeStyle;

View File

@@ -5,7 +5,7 @@ import android.content.DialogInterface;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libapputils.log.LogUtils;
import java.io.File;
import java.lang.reflect.Field;
import java.text.Collator;

View File

@@ -0,0 +1,170 @@
package cc.winboll.studio.libaes.unittests;
/**
* @Author ZhanGSKen@QQ.COM
* @Date 2024/06/14 03:43:23
* @Describe AES类库主窗口
*/
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Toast;
import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity;
import cc.winboll.studio.libaes.beans.DrawerMenuBean;
import cc.winboll.studio.libaes.dialogs.LocalFileSelectDialog;
import cc.winboll.studio.libaes.dialogs.StoragePathDialog;
import cc.winboll.studio.libapputils.log.LogUtils;
import com.a4455jkjh.colorpicker.ColorPickerDialog;
import java.util.ArrayList;
public class LibraryActivity extends DrawerFragmentActivity {
public static final String TAG = "LibraryActivity";
TestAButtonFragment mTestAButtonFragment;
TestViewPageFragment mTestViewPageFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (mTestAButtonFragment == null) {
mTestAButtonFragment = new TestAButtonFragment();
addFragment(mTestAButtonFragment);
}
showFragment(mTestAButtonFragment);
setSubtitle(TAG);
}
@Override
public void initDrawerMenuItemList(ArrayList<DrawerMenuBean> listDrawerMenu) {
super.initDrawerMenuItemList(listDrawerMenu);
LogUtils.d(TAG, "initDrawerMenuItemList");
//listDrawerMenu.clear();
// 添加抽屉菜单项
listDrawerMenu.add(new DrawerMenuBean(R.drawable.ic_launcher, TestAButtonFragment.TAG));
listDrawerMenu.add(new DrawerMenuBean(R.drawable.ic_launcher, TestViewPageFragment.TAG));
notifyDrawerMenuDataChanged();
}
@Override
public void reinitDrawerMenuItemList(ArrayList<DrawerMenuBean> listDrawerMenu) {
super.reinitDrawerMenuItemList(listDrawerMenu);
LogUtils.d(TAG, "reinitDrawerMenuItemList");
//listDrawerMenu.clear();
// 添加抽屉菜单项
listDrawerMenu.add(new DrawerMenuBean(R.drawable.ic_launcher, TestAButtonFragment.TAG));
listDrawerMenu.add(new DrawerMenuBean(R.drawable.ic_launcher, TestViewPageFragment.TAG));
notifyDrawerMenuDataChanged();
}
@Override
public DrawerFragmentActivity.ActivityType initActivityType() {
return DrawerFragmentActivity.ActivityType.Main;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar_library, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
super.onItemClick(parent, view, position, id);
switch (position) {
case 0 : {
if (mTestAButtonFragment == null) {
mTestAButtonFragment = new TestAButtonFragment();
addFragment(mTestAButtonFragment);
}
showFragment(mTestAButtonFragment);
break;
}
case 1 : {
if (mTestViewPageFragment == null) {
mTestViewPageFragment = new TestViewPageFragment();
addFragment(mTestViewPageFragment);
}
showFragment(mTestViewPageFragment);
break;
}
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int nItemId = item.getItemId();
// if (item.getItemId() == R.id.item_log) {
// WinBollActivityManager.getInstance(this).startWinBollActivity(getApplicationContext(), LogActivity.class);
// } else
if (nItemId == R.id.item_atoast) {
Toast.makeText(getApplication(), "item_testatoast", Toast.LENGTH_SHORT).show();
} else if (nItemId == R.id.item_atoolbar) {
Intent intent = new Intent(this, TestAToolbarActivity.class);
startActivity(intent);
} else if (nItemId == R.id.item_asupporttoolbar) {
Intent intent = new Intent(this, TestASupportToolbarActivity.class);
startActivity(intent);
} else if (nItemId == R.id.item_colordialog) {
ColorPickerDialog dlg = new ColorPickerDialog(this, getResources().getColor(R.color.colorPrimary));
dlg.setOnColorChangedListener(new com.a4455jkjh.colorpicker.view.OnColorChangedListener() {
@Override
public void beforeColorChanged() {
}
@Override
public void onColorChanged(int color) {
}
@Override
public void afterColorChanged() {
}
});
dlg.show();
} else if (nItemId == R.id.item_dialogstoragepath) {
final StoragePathDialog dialog = new StoragePathDialog(this, 0);
dialog.setOnOKClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
} else if (nItemId == R.id.item_localfileselectdialog) {
final LocalFileSelectDialog dialog = new LocalFileSelectDialog(this);
dialog.setOnOKClickListener(new LocalFileSelectDialog.OKClickListener() {
@Override
public void onOKClick(String sz) {
Toast.makeText(getApplication(), sz, Toast.LENGTH_SHORT).show();
//dialog.dismiss();
}
});
dialog.open();
} else if (nItemId == R.id.item_secondarylibraryactivity) {
Intent intent = new Intent(this, SecondaryLibraryActivity.class);
startActivity(intent);
} else if (nItemId == R.id.item_drawerfragmentactivity) {
Intent intent = new Intent(this, TestDrawerFragmentActivity.class);
startActivity(intent);
}
// else if (nItemId == R.id.item_about) {
// Intent intent = new Intent(this, AboutActivity.class);
// startActivity(intent);
// }
return super.onOptionsItemSelected(item);
}
}

View File

@@ -1,35 +1,23 @@
package cc.winboll.studio.libaes.unittests;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
/**
* @Author ZhanGSKen@QQ.COM
* @Date 2024/06/15 00:58:10
* @Describe 第二级窗口
*/
public class SecondaryLibraryActivity extends DrawerFragmentActivity implements IWinBollActivity {
public class SecondaryLibraryActivity extends DrawerFragmentActivity {
public static final String TAG = "SecondaryLibraryActivity";
SecondaryLibraryFragment mSecondaryLibraryFragment;
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return null;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -55,7 +43,7 @@ public class SecondaryLibraryActivity extends DrawerFragmentActivity implements
public boolean onOptionsItemSelected(MenuItem item) {
int nItemId = item.getItemId();
if (nItemId == R.id.item_test) {
Toast.makeText(getApplicationContext(), "item_test", Toast.LENGTH_SHORT).show();
Toast.makeText(getApplication(), "item_test", Toast.LENGTH_SHORT).show();
}
return super.onOptionsItemSelected(item);
}

View File

@@ -9,11 +9,11 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.fragment.app.Fragment;
import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.views.AButton;
import cc.winboll.studio.libappbase.LogUtils;
import com.hjq.toast.ToastUtils;
import cc.winboll.studio.libapputils.log.LogUtils;
public class TestAButtonFragment extends Fragment {
@@ -28,7 +28,7 @@ public class TestAButtonFragment extends Fragment {
@Override
public void onClick(View view) {
LogUtils.d(TAG, "onClick");
ToastUtils.show("AButton");
Toast.makeText(getActivity(), "AButton", Toast.LENGTH_SHORT).show();
}
});

View File

@@ -5,27 +5,19 @@ package cc.winboll.studio.libaes.unittests;
* @Date 2024/07/16 01:14:00
* @Describe TestASupportToolbarActivity
*/
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.beans.AESThemeBean;
import cc.winboll.studio.libaes.utils.AESThemeUtil;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
public class TestASupportToolbarActivity extends AppCompatActivity implements IWinBollActivity {
public class TestASupportToolbarActivity extends AppCompatActivity {
public static final String TAG = "TestASupportToolbarActivity";
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
@Override
protected void onCreate(Bundle savedInstanceState) {

View File

@@ -10,22 +10,11 @@ import android.os.Bundle;
import android.widget.Toolbar;
import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.utils.AESThemeUtil;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
public class TestAToolbarActivity extends Activity implements IWinBollActivity {
public class TestAToolbarActivity extends Activity {
public static final String TAG = "TestAToolbarActivity";
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
AESThemeUtil.applyAppTheme(this);

View File

@@ -4,40 +4,26 @@ package cc.winboll.studio.libaes.unittests;
* @Author ZhanGSKen@QQ.COM
* @Date 2024/06/30 15:00:51
*/
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.Toolbar;
import androidx.fragment.app.Fragment;
import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity;
import cc.winboll.studio.libaes.beans.DrawerMenuBean;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import cc.winboll.studio.libapputils.log.LogUtils;
import java.util.ArrayList;
public class TestDrawerFragmentActivity extends DrawerFragmentActivity implements IWinBollActivity {
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return null;
}
public class TestDrawerFragmentActivity extends DrawerFragmentActivity {
public static final String TAG = "TestDrawerFragmentActivity";
TestFragment1 mTestFragment1;
TestFragment2 mTestFragment2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -80,7 +66,7 @@ public class TestDrawerFragmentActivity extends DrawerFragmentActivity implement
super.onItemClick(parent, view, position, id);
switch (position) {
case 0 : {
Toast.makeText(getApplicationContext(), "0", Toast.LENGTH_SHORT).show();
Toast.makeText(getContext(), "0", Toast.LENGTH_SHORT).show();
//LogUtils.d(TAG, "MenuItem 1");
showFragment(mTestFragment1);
break;

View File

@@ -5,7 +5,6 @@ package cc.winboll.studio.libaes.unittests;
* @Date 2024/07/16 01:35:56
* @Describe TestViewPageFragment
*/
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -18,17 +17,12 @@ import androidx.viewpager.widget.ViewPager;
import cc.winboll.studio.libaes.ImagePagerAdapter;
import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.views.AOHPCTCSeekBar;
import cc.winboll.studio.libappbase.LogView;
import com.hjq.toast.ToastUtils;
import java.util.ArrayList;
import java.util.List;
public class TestViewPageFragment extends Fragment implements ViewPager.OnPageChangeListener, View.OnClickListener {
public static final String TAG = "TestViewPageFragment";
Context mContext;
LogView mLogView;
private ViewPager viewPager;
private List<View> views; //用来存放放进ViewPager里面的布局
@@ -42,10 +36,6 @@ public class TestViewPageFragment extends Fragment implements ViewPager.OnPageCh
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.fragment_viewpage, container, false);
mContext = getActivity();
mLogView = mView.findViewById(R.id.logview);
mLogView.start();
//viewPager = findViewById(R.id.activitymainViewPager1);
initData();
@@ -70,13 +60,12 @@ public class TestViewPageFragment extends Fragment implements ViewPager.OnPageCh
initPoint();//初始化页面下方的点
viewPager.setOnPageChangeListener(this);
initAOHPCTCSeekBar();
initAOHPCTCSeekBar2();
}
//初始化所要显示的布局
void initData() {
ViewPager viewPager = mView.findViewById(R.id.fragmentviewpageViewPager1);
LayoutInflater inflater = LayoutInflater.from(mContext);
LayoutInflater inflater = LayoutInflater.from(getActivity());
View view1 = inflater.inflate(R.layout.viewpage_atickprogressbar, viewPager, false);
View view2 = inflater.inflate(R.layout.viewpage_acard, viewPager, false);
View view3 = inflater.inflate(R.layout.viewpage_aohpctccard, viewPager, false);
@@ -196,31 +185,14 @@ public class TestViewPageFragment extends Fragment implements ViewPager.OnPageCh
}
void initAOHPCTCSeekBar() {
AOHPCTCSeekBar seekbar = views.get(3).findViewById(R.id.fragmentviewpageAOHPCTCSeekBar1);
seekbar.setThumb(mContext.getDrawable(R.drawable.ic_launcher));
//seekbar.setThumbOffset(200);
//seekbar.setThumbOffset(1);
seekbar.setBlurRightDP(50);
AOHPCTCSeekBar seekbar = mView.findViewById(R.id.fragmentviewpageAOHPCTCSeekBar1);
seekbar.setThumb(getActivity().getDrawable(R.drawable.ic_launcher));
seekbar.setThumbOffset(10);
seekbar.setOnOHPCListener(new AOHPCTCSeekBar.OnOHPCListener() {
@Override
public void onOHPCommit() {
ToastUtils.show("onOHPCommit");
}
});
}
void initAOHPCTCSeekBar2() {
AOHPCTCSeekBar seekbar = views.get(3).findViewById(R.id.fragmentviewpageAOHPCTCSeekBar2);
seekbar.setThumb(mContext.getDrawable(R.drawable.ic_call));
//seekbar.setThumbOffset(200);
//seekbar.setThumbOffset(1);
seekbar.setBlurRightDP(50);
seekbar.setOnOHPCListener(new AOHPCTCSeekBar.OnOHPCListener() {
@Override
public void onOHPCommit() {
ToastUtils.show("onOHPCommit 2");
Toast.makeText(getActivity(), "onOHPCommit ", Toast.LENGTH_SHORT).show();
}
});
}

View File

@@ -11,8 +11,8 @@ import android.view.Menu;
import android.view.MenuItem;
import androidx.appcompat.app.AppCompatActivity;
import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity;
import cc.winboll.studio.libaes.beans.AESThemeBean;
import cc.winboll.studio.libapputils.app.WinBollActivity;
public class AESThemeUtil {
@@ -25,7 +25,7 @@ public class AESThemeUtil {
public static <T extends Context> int getThemeTypeID(T context) {
AESThemeBean bean = AESThemeBean.loadBean(context, AESThemeBean.class);
return bean == null ? AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.AES): bean.getCurrentThemeTypeID();
return bean == null ? AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEFAULT): bean.getCurrentThemeTypeID();
}
public static <T extends Context> void saveThemeStyleID(T context, int nThemeTypeID) {
@@ -41,9 +41,9 @@ public class AESThemeUtil {
activity.setTheme(getThemeTypeID(activity));
}
/*public static <T extends WinBollActivity> void applyWinBollTheme(T activity) {
public static <T extends WinBollActivity> void applyWinBollTheme(T activity) {
activity.setTheme(getThemeTypeID(activity.getApplicationContext()));
}*/
}
public static <T extends Activity> void applyAppTheme(Activity activity, AESThemeBean.ThemeType themeType) {
activity.setTheme(AESThemeBean.getThemeStyleID(themeType));
@@ -53,9 +53,9 @@ public class AESThemeUtil {
activity.setTheme(AESThemeBean.getThemeStyleID(themeType));
}
/*public static <T extends WinBollActivity> void applyWinBollTheme(Activity activity, AESThemeBean.ThemeType themeType) {
public static <T extends WinBollActivity> void applyWinBollTheme(Activity activity, AESThemeBean.ThemeType themeType) {
activity.setTheme(AESThemeBean.getThemeStyleID(themeType));
}*/
}
public static <T extends Activity> void inflateMenu(T activity, Menu menu) {
activity.getMenuInflater().inflate(R.menu.toolbar_apptheme, menu);
@@ -65,9 +65,9 @@ public class AESThemeUtil {
activity.getMenuInflater().inflate(R.menu.toolbar_apptheme, menu);
}
/*public static <T extends WinBollActivity> void inflateWinBollMenu(T activity, Menu menu) {
public static <T extends WinBollActivity> void inflateWinBollMenu(T activity, Menu menu) {
activity.getMenuInflater().inflate(R.menu.toolbar_apptheme, menu);
}*/
}
public static <T extends Activity> boolean onAppThemeItemSelected(T activity, MenuItem item) {
int nThemeStyleID;
@@ -92,7 +92,7 @@ public class AESThemeUtil {
saveThemeStyleID(activity, nThemeStyleID);
return true;
} else if (R.id.item_defaulttheme == item.getItemId()) {
nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.AES);
nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEFAULT);
saveThemeStyleID(activity, nThemeStyleID);
return true;
}
@@ -123,7 +123,7 @@ public class AESThemeUtil {
saveThemeStyleID(activity, nThemeStyleID);
return true;
} else if (R.id.item_defaulttheme == item.getItemId()) {
nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.AES);
nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEFAULT);
saveThemeStyleID(activity, nThemeStyleID);
return true;
}
@@ -131,7 +131,7 @@ public class AESThemeUtil {
return false;
}
public static <T extends AppCompatActivity> boolean onWinBollThemeItemSelected(T activity, MenuItem item) {
public static <T extends WinBollActivity> boolean onWinBollThemeItemSelected(T activity, MenuItem item) {
int nThemeStyleID;
if (R.id.item_depththeme == item.getItemId()) {
nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEPTH);
@@ -154,38 +154,7 @@ public class AESThemeUtil {
saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID);
return true;
} else if (R.id.item_defaulttheme == item.getItemId()) {
nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.AES);
saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID);
return true;
}
return false;
}
public static <T extends DrawerFragmentActivity> boolean onWinBollThemeItemSelected(T activity, MenuItem item) {
int nThemeStyleID;
if (R.id.item_depththeme == item.getItemId()) {
nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEPTH);
saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID);
return true;
} else if (R.id.item_skytheme == item.getItemId()) {
nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.SKY);
saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID);
return true;
} else if (R.id.item_goldentheme == item.getItemId()) {
nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.GOLDEN);
saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID);
return true;
} else if (R.id.item_memortheme == item.getItemId()) {
nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.MEMOR);
saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID);
return true;
} else if (R.id.item_taotheme == item.getItemId()) {
nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.TAO);
saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID);
return true;
} else if (R.id.item_defaulttheme == item.getItemId()) {
nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.AES);
nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEFAULT);
saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID);
return true;
}

View File

@@ -1,162 +0,0 @@
package cc.winboll.studio.libaes.utils;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2024/08/12 14:45:35
* @Describe 应用版本工具集
*/
import cc.winboll.studio.libappbase.LogUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class AppVersionUtils {
public static final String TAG = "AppVersionUtils";
//
// 检查新版本是否成立
// szCurrentCode : 当前版本应用包名
// szNextCode : 新版本应用包名
// 返回 情况1当前版本是发布版
// 返回 true (新版本 > 当前版本)
// 情况1当前版本是Beta版
// true 新版本 == 当前版本
//
public static boolean isHasNewVersion2(String szCurrentName, String szNextName) {
LogUtils.d(TAG, String.format("isHasNewVersion2\nszCurrentName : %s\nszNextName : %s", szCurrentName, szNextName));
//szCurrentName = "AES_6.2.0-beta0_3234.apk";
//szNextName = "AES_6.1.12.apk";
//szCurrentName = "AES_6.2.0-beta0_3234.apk";
//szNextName = "AES_6.2.0.apk";
//szCurrentName = "AES_6.2.0-beta0_3234.apk";
//szNextName = "AES_6.2.2.apk";
//szCurrentName = "AES_6.2.0-beta0_3234.apk";
//szNextName = "AES_6.2.0.apk";
//szCurrentName = "AES_6.1.0.apk";
//szNextName = "AES_6.2.0.apk";
//LogUtils.d(TAG, "szCurrentName : " + szCurrentName);
//LogUtils.d(TAG, "szNextName : " + szNextName);
//boolean isVersionNewer = false;
//if(szCurrentName.equals(szNextName)) {
// isVersionNewer = false;
//} else {
//ToastUtils.show("szCurrent : " + szCurrent + "\nszNext : " + szNext);
//int nApk = szNextName.lastIndexOf(".apk");
//ToastUtils.show("nApk : " + Integer.toString(nApk));
//String szNextNoApkName = szNextName.substring(0, nApk);
//ToastUtils.show("szNextNoApkName : " + szNextNoApkName);
//String szCurrentNoApkName = szCurrentName.substring(0, szNextNoApkName.length());
//ToastUtils.show("szCurrentNoApkName : " + szCurrentNoApkName);
//String str1 = "3.4.50";
//String str2 = "3.3.60";
//String str1 = getCodeInPackageName(szCurrentName);
//String str2 = getCodeInPackageName(szNextName);
//String str1 = getCodeInPackageName(szNextName);
//String str2 = getCodeInPackageName(szCurrentName);
//Boolean isVersionNewer2 = checkNewVersion(str1,str2);
//ToastUtils.show("isVersionNewer2 : " + Boolean.toString(isVersionNewer2));
//ToastUtils.show(checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName)));
//return checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName));
//}
//return isVersionNewer;
if (checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName))) {
// 比 AES_6.2.0.apk 版本大,如 AES_6.2.1.apk。
// 比 AES_6.2.0-beta0_3234.apk 大,如 AES_6.2.1.apk。
//LogUtils.d(TAG, "App newer stage version is released. Release name : " + szNextName);
return true;
}
if (szCurrentName.matches(".*_\\d+\\.\\d+\\.\\d+-beta.*\\.apk")) {
String szCurrentReleasePackageName = getReleasePackageName(szCurrentName);
//LogUtils.d(TAG, "szCurrentReleasePackageName : " + szCurrentReleasePackageName);
if (szCurrentReleasePackageName.equals(szNextName)) {
// 与 AES_6.2.0-beta0_3234.apk 版本相同,如 AES_6.2.0.apk。
//LogUtils.d(TAG, "App stage version is released. Release name : " + szNextName);
return true;
}
}
//LogUtils.d(TAG, "App version is the newest. ");
return false;
}
public static boolean isHasNewStageReleaseVersion(String szCurrentName, String szNextName) {
LogUtils.d(TAG, String.format("isHasNewStageReleaseVersion\nszCurrentName : %s\nszNextName : %s", szCurrentName, szNextName));
//szCurrentName = "AES_6.2.12.apk";
//szNextName = "AES_6.3.12.apk";
if (checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName))) {
// 比 AES_6.2.0.apk 版本大,如 AES_6.2.1.apk。
//LogUtils.d(TAG, "App newer stage version is released. Release name : " + szNextName);
return true;
}
return false;
}
//
// 检查新版本是否成立
// szCurrentCode : 当前版本
// szNextCode : 新版本
// 返回 true 新版本 > 当前版本
//
public static Boolean checkNewVersion(String szCurrentCode, String szNextCode) {
if (szCurrentCode == null || szCurrentCode.equals("") || szNextCode == null || szNextCode.equals("")) {
LogUtils.d(TAG, String.format("checkNewVersion unexpected parameters:\nszCurrentCode : %s\nszNextCode : %s", szCurrentCode, szNextCode));
return false;
}
boolean isNew = false;
String[] appVersionCurrent = szCurrentCode.split("\\.");
String[] appVersionNext = szNextCode.split("\\.");
//根据位数最短的判断
int lim = appVersionCurrent.length > appVersionNext.length ? appVersionNext.length : appVersionCurrent.length;
//根据位数循环判断各个版本
for (int i = 0; i < lim; i++) {
if (Integer.parseInt(appVersionNext[i]) > Integer.parseInt(appVersionCurrent[i])) {
isNew = true;
return isNew;
} else if (Integer.parseInt(appVersionNext[i]) == Integer.parseInt(appVersionCurrent[i])) {
continue ;
} else {
isNew = false;
return isNew;
}
}
return isNew;
}
//
// 截取应用包名称版本号信息
// 如 AppUtils_7.0.4-beta1_0120.apk 版本号为 7.0.4
// 如 AppUtils_7.0.4.apk 版本号为 7.0.4
//
public static String getCodeInPackageName(String apkName) {
LogUtils.d(TAG, String.format("getCodeInPackageName apkName : %s", apkName));
//String apkName = "AppUtils_7.0.0.apk";
Pattern pattern = Pattern.compile("\\d+\\.\\d+\\.\\d+");
Matcher matcher = pattern.matcher(apkName);
if (matcher.find()) {
String version = matcher.group();
LogUtils.d(TAG, String.format("version is %s", version));
return version;
//System.out.println("Version number: " + version); // 输出7.0.0
}
LogUtils.d(TAG, String.format("No result."));
return "";
}
//
// 根据Beta版名称生成发布版应用包名称
// 如 AppUtils_7.0.4-beta1_0120.apk
// 发布版名称就为AppUtils_7.0.4.apk
//
public static String getReleasePackageName(String szBetaPackageName) {
//String szBetaPackageName = "AppUtils_7.0.4-beta1_0120.apk";
Pattern pattern = Pattern.compile(".*\\d+\\.\\d+\\.\\d+");
Matcher matcher = pattern.matcher(szBetaPackageName);
if (matcher.find()) {
String szReleasePackageName = matcher.group();
return szReleasePackageName + ".apk";
//System.out.println("Version number: " + version); // 输出7.0.0
}
return "";
}
}

View File

@@ -6,30 +6,24 @@ package cc.winboll.studio.libaes.views;
* @Describe AOneHundredPercantClickToCommitSeekBar
*/
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.SeekBar;
import cc.winboll.studio.libappbase.LogUtils;
public class AOHPCTCSeekBar extends SeekBar {
public static final String TAG = "AOHPCTCSeekBar";
volatile int thumbWidth = 1;
volatile int progressBarWidth = 1;
// 设置按钮模糊右边边缘像素
volatile int blurRightDP = 1;
// 是否从起点拉动的标志
volatile boolean isStartSeek = false;
// 可开始拉动的起始位置(百分比值)
static final int ENABLE_POST_PERCENT_X = 20;
// 最小拉动值,滑块拉动值要超过这个值,确定事件才会提交。
static final int TO_MIN_VALUE = 15;
// 外部接口对象,确定事件提交会调用该对象的方法
OnOHPCListener mOnOHPCListener;
public void setBlurRightDP(int blurRight) {
this.blurRightDP = blurRight;
}
// 是否从起点拉动的标志
boolean mIsStartTo = false;
// 拉动的滑动值
int mnTo = 0;
public void setOnOHPCListener(OnOHPCListener listener) {
mOnOHPCListener = listener;
@@ -41,68 +35,83 @@ public class AOHPCTCSeekBar extends SeekBar {
public AOHPCTCSeekBar(Context context) {
super(context);
initView(context);
}
public AOHPCTCSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
//LogUtils.d(TAG, "AOHPCTCSeekBar(...)");
// 获得TypedArray
//TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AToolbar);
// 获得attrs.xml里面的属性值,格式为:名称_属性名,后面是默认值
//int colorBackgroud = a.getColor(R.styleable.ACard_backgroudColor, context.getColor(R.color.colorACardBackgroung));
//int centerColor = a.getColor(R.styleable.AToolbar_centerColor, context.getColor(R.color.colorAToolbarCenterColor));
//int endColor = a.getColor(R.styleable.AToolbar_endColor, context.getColor(R.color.colorAToolbarEndColor));
//float tSize = a.getDimension(R.styleable.CustomView_tSize, 35);
//p.setColor(tColor);
//p.setTextSize(tSize);
//Drawable drawable = context.getDrawable(R.drawable.frame_atoolbar);
//setBackground(context.getDrawable(R.drawable.acard_frame_main));
// 返回一个绑定资源结束的信号给资源
//a.recycle();
}
public AOHPCTCSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
void initView(Context context) {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (thumbWidth + blurRightDP > event.getX() && event.getX() > 0) {
getParent().requestDisallowInterceptTouchEvent(true);
isStartSeek = true;
//LogUtils.d(TAG, "ACTION_DOWN");
// 有效的拖动起始位置(ENABLE_POST_PERCENT_X)%
int nEnablePostX = ((getRight() - getLeft()) * ENABLE_POST_PERCENT_X / 100) + getLeft();
if ((getLeft() < event.getX())
&& (event.getX() < nEnablePostX)) {
//LogUtils.d(TAG, "event.getX() is " + Float.toString(event.getX()));
mIsStartTo = true;
return super.dispatchTouchEvent(event);
}
if (!mIsStartTo) {
resetView();
return false;
}
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (isStartSeek) {
super.dispatchTouchEvent(event);
//LogUtils.d(TAG, "ACTION_MOVE");
if (mIsStartTo) {
mnTo++;
}
} else if (event.getAction() == MotionEvent.ACTION_UP
|| event.getAction() == MotionEvent.ACTION_CANCEL) {
getParent().requestDisallowInterceptTouchEvent(false);
if (getProgress() == progressBarWidth) {
} else if (event.getAction() == MotionEvent.ACTION_UP) {
//LogUtils.d(TAG, Integer.toString(getProgress()));
// 提交100%确定事件
if ((getProgress() == 100) && (mnTo > TO_MIN_VALUE)) {
//LogUtils.d(TAG, "Commit mnTo is " + Integer.toString(mnTo));
mOnOHPCListener.onOHPCommit();
//resetView();
//return true;
}
// 重置控件状态
setProgress(0);
isStartSeek = false;
resetView();
return false;
}
return true;
//LogUtils.d(TAG, "dispatchTouchEvent End");
return super.dispatchTouchEvent(event);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
//int height = MeasureSpec.getSize(heightMeasureSpec);
//LogUtils.d(TAG, String.format("width %d height %d", width, height));
// 获取SeekBar的图标宽度
Drawable thumbDrawable = getThumb();
if (thumbDrawable != null) {
// 获取图标宽度
thumbWidth = thumbDrawable.getIntrinsicWidth();
}
// 获取进度条宽度
progressBarWidth = width;
//LogUtils.d(TAG, String.format("thumbWidth %d progressBarWidth %d", thumbWidth, progressBarWidth));
// 设置图标位置
setThumbOffset(0);
// 设置进度条刻度
setMax(progressBarWidth);
// 重置控件状态
//
void resetView() {
setProgress(0);
mnTo = 0;
mIsStartTo = false;
}
}

View File

@@ -1,143 +0,0 @@
package cc.winboll.studio.libaes.winboll;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/01/20 14:19:02
* @Describe 应用信息类
*/
import cc.winboll.studio.libaes.R;
import java.io.Serializable;
public class APPInfo implements Serializable {
public static final String TAG = "APPInfo";
// 应用名称
String appName;
// 应用图标
int appIcon;
// 应用描述
String appDescription;
// 应用Git仓库地址
String appGitName;
// 应用Git仓库拥有者
String appGitOwner;
// 应用Git仓库分支
String appGitAPPBranch;
// 应用Git仓库子项目文件夹
String appGitAPPSubProjectFolder;
// 应用主页
String appHomePage;
// 应用包名称
String appAPKName;
// 应用包存储文件夹名称
String appAPKFolderName;
public APPInfo(String appName, int appIcon, String appDescription, String appGitName, String appGitOwner, String appGitAPPBranch, String appGitAPPSubProjectFolder, String appHomePage, String appAPKName, String appAPKFolderName) {
this.appName = appName;
this.appIcon = appIcon;
this.appDescription = appDescription;
this.appGitName = appGitName;
this.appGitOwner = appGitOwner;
this.appGitAPPBranch = appGitAPPBranch;
this.appGitAPPSubProjectFolder = appGitAPPSubProjectFolder;
this.appHomePage = appHomePage;
this.appAPKName = appAPKName;
this.appAPKFolderName = appAPKFolderName;
}
public APPInfo() {
String szBranchName = "app";
this.appName = "APP";
this.appIcon = R.drawable.ic_launcher;
this.appDescription = "APP Description";
this.appGitName = "APP";
this.appGitOwner = "Studio";
this.appGitAPPBranch = szBranchName;
this.appGitAPPSubProjectFolder = szBranchName;
this.appHomePage = "https://www.winboll.cc/studio/details.php?app=APP";
this.appAPKName = "APP";
this.appAPKFolderName = "APP";
}
public void setAppGitOwner(String appGitOwner) {
this.appGitOwner = appGitOwner;
}
public String getAppGitOwner() {
return appGitOwner;
}
public void setAppGitAPPBranch(String appGitAPPBranch) {
this.appGitAPPBranch = appGitAPPBranch;
}
public String getAppGitAPPBranch() {
return appGitAPPBranch;
}
public void setAppGitAPPSubProjectFolder(String appGitAPPSubProjectFolder) {
this.appGitAPPSubProjectFolder = appGitAPPSubProjectFolder;
}
public String getAppGitAPPSubProjectFolder() {
return appGitAPPSubProjectFolder;
}
public void setAppIcon(int appIcon) {
this.appIcon = appIcon;
}
public int getAppIcon() {
return appIcon;
}
public void setAppDescription(String appDescription) {
this.appDescription = appDescription;
}
public String getAppDescription() {
return appDescription;
}
public void setAppAPKFolderName(String appAPKFolderName) {
this.appAPKFolderName = appAPKFolderName;
}
public String getAppAPKFolderName() {
return appAPKFolderName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public String getAppName() {
return appName;
}
public void setAppGitName(String appGitName) {
this.appGitName = appGitName;
}
public String getAppGitName() {
return appGitName;
}
public void setAppHomePage(String appHomePage) {
this.appHomePage = appHomePage;
}
public String getAppHomePage() {
return appHomePage;
}
public void setAppAPKName(String appAPKName) {
this.appAPKName = appAPKName;
}
public String getAppAPKName() {
return appAPKName;
}
}

View File

@@ -1,392 +0,0 @@
package cc.winboll.studio.libaes.winboll;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/24 15:08:52
* @Describe WinBoll应用介绍视图
*/
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.TypedArray;
import android.net.Uri;
import android.os.Message;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.utils.AppVersionUtils;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.dialogs.YesNoAlertDialog;
import cc.winboll.studio.libapputils.utils.PrefUtils;
import com.hjq.toast.ToastUtils;
import java.io.IOException;
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;
public class AboutView extends LinearLayout {
public static final String TAG = "AboutView";
public static final int MSG_APPUPDATE_CHECKED = 0;
Context mContext;
APPInfo mAPPInfo;
WinBollServiceStatusView mWinBollServiceStatusView;
OnRequestDevUserInfoAutofillListener mOnRequestDevUserInfoAutofillListener;
String mszAppName = "";
String mszAppAPKFolderName = "";
String mszAppAPKName = "";
String mszAppGitName = "";
String mszAppVersionName = "";
String mszCurrentAppPackageName = "";
volatile String mszNewestAppPackageName = "";
String mszAppDescription = "";
String mszHomePage = "";
String mszGitea = "";
int mnAppIcon = 0;
String mszWinBollServerHost;
String mszReleaseAPKName;
EditText metDevUserName;
EditText metDevUserPassword;
public AboutView(Context context, APPInfo appInfo) {
super(context);
mContext = context;
setAPPInfo(appInfo);
initView(context);
}
public AboutView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
initView(context, attrs);
}
public void setAPPInfo(APPInfo appInfo) {
mAPPInfo = appInfo;
}
APPInfo createAppInfo(Context context, AttributeSet attrs) {
APPInfo appInfo = new APPInfo();
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AboutView);
appInfo.setAppName(typedArray.getString(R.styleable.AboutView_app_name));
appInfo.setAppAPKFolderName(typedArray.getString(R.styleable.AboutView_app_apkfoldername));
appInfo.setAppAPKName(typedArray.getString(R.styleable.AboutView_app_apkname));
appInfo.setAppGitName(typedArray.getString(R.styleable.AboutView_app_gitname));
appInfo.setAppGitOwner(typedArray.getString(R.styleable.AboutView_app_gitowner));
appInfo.setAppGitAPPBranch(typedArray.getString(R.styleable.AboutView_app_gitappbranch));
appInfo.setAppGitAPPSubProjectFolder(typedArray.getString(R.styleable.AboutView_app_gitappsubprojectfolder));
appInfo.setAppDescription(typedArray.getString(R.styleable.AboutView_appdescription));
appInfo.setAppIcon(typedArray.getResourceId(R.styleable.AboutView_appicon, R.drawable.ic_winboll));
// 返回一个绑定资源结束的信号给资源
typedArray.recycle();
return appInfo;
}
void initView(Context context) {
mszAppName = mAPPInfo.getAppName();
mszAppAPKFolderName = mAPPInfo.getAppAPKFolderName();
mszAppAPKName = mAPPInfo.getAppAPKName();
mszAppGitName = mAPPInfo.getAppGitName();
mszAppDescription = mAPPInfo.getAppDescription();
mnAppIcon = mAPPInfo.getAppIcon();
mszWinBollServerHost = 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));
// LinearLayout llMain = findViewById(R.id.viewaboutLinearLayout1);
// llMain.addView(createAboutPage());
// 就读取正式版应用包版本号,设置 Release 应用包文件名
String szReleaseAppVersionName = "";
try {
//LogUtils.d(TAG, String.format("mContext.getPackageName() %s", mContext.getPackageName()));
String szSubBetaSuffix = subBetaSuffix(mContext.getPackageName());
//LogUtils.d(TAG, String.format("szSubBetaSuffix : %s", szSubBetaSuffix));
szReleaseAppVersionName = mContext.getPackageManager().getPackageInfo(szSubBetaSuffix, 0).versionName;
} catch (PackageManager.NameNotFoundException e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
mszReleaseAPKName = mszAppAPKName + "_" + szReleaseAppVersionName + ".apk";
}
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);
// }
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);
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) {
//ToastUtils.show("mAppDebugOnClickListener");
setApp2DebugMode(mContext);
}
};
View.OnClickListener mAppNormalOnClickListener = new View.OnClickListener(){
@Override
public void onClick(View view) {
//ToastUtils.show("mAppNormalOnClickListener");
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(true);
GlobalApplication.getWinBollActivityManager().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(false);
GlobalApplication.getWinBollActivityManager().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());
} else {
credential = Credentials.basic("WinBoll", "WinBollPowerByZhanGSKen");
}
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 File

@@ -1,96 +0,0 @@
package cc.winboll.studio.libaes.winboll;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 19:12:12
* @Describe 应用主要服务组件类守护进程服务组件类
*/
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import cc.winboll.studio.libaes.winboll.WinBollClientService;
import cc.winboll.studio.libappbase.utils.ServiceUtils;
public class AssistantService extends Service {
public final static String TAG = "AssistantService";
WinBollClientServiceBean mWinBollServiceBean;
MyServiceConnection mMyServiceConnection;
volatile boolean mIsServiceRunning;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
mWinBollServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(this);
if (mMyServiceConnection == null) {
mMyServiceConnection = new MyServiceConnection();
}
// 设置运行参数
mIsServiceRunning = false;
run();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
run();
return START_STICKY;
}
@Override
public void onDestroy() {
mIsServiceRunning = false;
super.onDestroy();
}
//
// 运行服务内容
//
void run() {
mWinBollServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(this);
if (mWinBollServiceBean.isEnable()) {
if (mIsServiceRunning == false) {
// 设置运行状态
mIsServiceRunning = true;
// 唤醒和绑定主进程
wakeupAndBindMain();
}
}
}
//
// 唤醒和绑定主进程
//
void wakeupAndBindMain() {
if (ServiceUtils.isServiceRunning(getApplicationContext(), WinBollClientService.class.getName()) == false) {
startForegroundService(new Intent(AssistantService.this, WinBollClientService.class));
}
bindService(new Intent(AssistantService.this, WinBollClientService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
}
//
// 主进程与守护进程连接时需要用到此类
//
class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
mWinBollServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(AssistantService.this);
if (mWinBollServiceBean.isEnable()) {
wakeupAndBindMain();
}
}
}
}

View File

@@ -1,35 +0,0 @@
package cc.winboll.studio.libaes.winboll;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 19:11:27
* @Describe WinBoll UI 状态图标枚举
*/
import cc.winboll.studio.libaes.R;
public enum EWUIStatusIconDrawable {
NORMAL(0),
NEWS(1)
;
static final String TAG = "WUIStatusIconDrawable";
static String[] _mlistCNName = { "正常", "新的消息" };
private int value = 0;
private EWUIStatusIconDrawable(int value) { //必须是private的否则编译错误
this.value = value;
}
public static int getIconDrawableId(EWUIStatusIconDrawable drawableId) {
int res;
switch(drawableId){
case NEWS :
res = R.drawable.ic_winbollbeta;
break;
default :
res = R.drawable.ic_winboll;
}
return res;
}
}

View File

@@ -1,17 +0,0 @@
package cc.winboll.studio.libaes.winboll;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 19:08:45
* @Describe WinBollService 服务 Binder。
*/
import android.graphics.drawable.Drawable;
public interface IWinBollClientServiceBinder {
public static final String TAG = "IWinBollClientServiceBinder";
public WinBollClientService getService();
public Drawable getCurrentStatusIconDrawable();
}

View File

@@ -1,192 +0,0 @@
package cc.winboll.studio.libaes.winboll;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 19:06:54
* @Describe WinBoll 客户端服务
*/
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.drawable.Drawable;
import android.os.IBinder;
import cc.winboll.studio.libaes.winboll.AssistantService;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.utils.ServiceUtils;
import cc.winboll.studio.libapputils.utils.PrefUtils;
import com.hjq.toast.ToastUtils;
public class WinBollClientService extends Service implements IWinBollClientServiceBinder {
public static final String TAG = "WinBollClientService";
WinBollClientServiceBean mWinBollClientServiceBean;
MyServiceConnection mMyServiceConnection;
volatile boolean mIsWinBollClientThreadRunning;
volatile boolean mIsEnableService;
volatile WinBollClientThread mWinBollClientThread;
public boolean isWinBollClientThreadRunning() {
return mIsWinBollClientThreadRunning;
}
@Override
public WinBollClientService getService() {
return WinBollClientService.this;
}
@Override
public Drawable getCurrentStatusIconDrawable() {
return mIsWinBollClientThreadRunning ?
getDrawable(EWUIStatusIconDrawable.getIconDrawableId(EWUIStatusIconDrawable.NORMAL))
: getDrawable(EWUIStatusIconDrawable.getIconDrawableId(EWUIStatusIconDrawable.NEWS));
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
//ToastUtils.show("onCreate");
super.onCreate();
mWinBollClientThread = null;
mWinBollClientServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(this);
mIsEnableService = mWinBollClientServiceBean.isEnable();
if (mMyServiceConnection == null) {
mMyServiceConnection = new MyServiceConnection();
}
// 由系统启动时,应用可以通过下面函数实例化实际服务进程。
runMainThread();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//ToastUtils.show("onStartCommand");
// 由应用 Intent 启动时,应用可以通过下面函数实例化实际服务进程。
runMainThread();
// 返回运行参数持久化存储后,服务状态控制参数
// 无论 Intent 传入如何,服务状态一直以持久化存储后的参数控制,
// PS: 另外当然可以通过 Intent 传入的指标来修改 mWinBollServiceBean
// 不过本服务的应用方向会变得繁琐,
// 现阶段只要满足手机端启动与停止本服务WinBoll 客户端实例运行在手机端就可以了。
return mIsEnableService ? Service.START_STICKY: super.onStartCommand(intent, flags, startId);
}
synchronized void runMainThread() {
if (mWinBollClientThread == null) {
//ToastUtils.show("runMainThread()");
mWinBollClientThread = new WinBollClientThread();
mWinBollClientThread.start();
}
}
void syncWinBollClientThreadStatus() {
mWinBollClientServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(this);
mIsEnableService = mWinBollClientServiceBean.isEnable();
LogUtils.d(TAG, String.format("mIsEnableService %s", mIsEnableService));
}
// 唤醒和绑定守护进程
//
void wakeupAndBindAssistant() {
if (ServiceUtils.isServiceRunning(getApplicationContext(), AssistantService.class.getName()) == false) {
startService(new Intent(WinBollClientService.this, AssistantService.class));
//LogUtils.d(TAG, "call wakeupAndBindAssistant() : Binding... AssistantService");
bindService(new Intent(WinBollClientService.this, AssistantService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
}
}
// 主进程与守护进程连接时需要用到此类
//
private class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
mWinBollClientServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(WinBollClientService.this);
if (mWinBollClientServiceBean.isEnable()) {
// 唤醒守护进程
wakeupAndBindAssistant();
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
//ToastUtils.show("onDestroy");
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
void setWinBollServiceEnableStatus(boolean isEnable) {
WinBollClientServiceBean bean = WinBollClientServiceBean.loadWinBollClientServiceBean(this);
bean.setIsEnable(isEnable);
WinBollClientServiceBean.saveWinBollServiceBean(this, bean);
}
boolean getWinBollServiceEnableStatus(Context context) {
mWinBollClientServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(context);
return mWinBollClientServiceBean.isEnable();
}
/*public interface OnServiceStatusChangeListener {
void onServerStatusChange(boolean isServiceAlive);
}
public void setOnServerStatusChangeListener(OnServiceStatusChangeListener l) {
mOnServerStatusChangeListener = l;
}*/
class WinBollClientThread extends Thread {
@Override
public void run() {
super.run();
LogUtils.d(TAG, "run syncWinBollClientThreadStatus");
syncWinBollClientThreadStatus();
if (mIsEnableService) {
if (mIsWinBollClientThreadRunning == false) {
// 设置运行状态
mIsWinBollClientThreadRunning = true;
LogUtils.d(TAG, "WinBollClientThread run()");
// 唤醒守护进程
//wakeupAndBindAssistant();
while (mIsEnableService) {
// 显示运行状态
WinBollServiceStatusView.startConnection();
LogUtils.d(TAG, String.format("while mIsEnableService is %s", mIsEnableService));
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
syncWinBollClientThreadStatus();
}
// 服务进程退出, 重置进程运行状态
WinBollServiceStatusView.stopConnection();
mIsWinBollClientThreadRunning = false;
mWinBollClientThread = null;
}
}
}
}
}

View File

@@ -1,78 +0,0 @@
package cc.winboll.studio.libaes.winboll;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 19:05:15
* @Describe WinBollService 运行参数配置
*/
import android.content.Context;
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException;
public class WinBollClientServiceBean extends BaseBean {
public static final String TAG = "WinBollClientServiceBean";
volatile boolean isEnable;
public WinBollClientServiceBean() {
isEnable = false;
}
public void setIsEnable(boolean isEnable) {
this.isEnable = isEnable;
}
public boolean isEnable() {
return isEnable;
}
@Override
public String getName() {
return WinBollClientServiceBean.class.getName();
}
@Override
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
super.writeThisToJsonWriter(jsonWriter);
WinBollClientServiceBean bean = this;
jsonWriter.name("isEnable").value(bean.isEnable());
}
@Override
public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
if (name.equals("isEnable")) {
setIsEnable(jsonReader.nextBoolean());
} else {
return false;
}
}
return true;
}
@Override
public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException {
jsonReader.beginObject();
while (jsonReader.hasNext()) {
String name = jsonReader.nextName();
if (!initObjectsFromJsonReader(jsonReader, name)) {
jsonReader.skipValue();
}
}
// 结束 JSON 对象
jsonReader.endObject();
return this;
}
public static WinBollClientServiceBean loadWinBollClientServiceBean(Context context) {
WinBollClientServiceBean bean = WinBollClientServiceBean.loadBean(context, WinBollClientServiceBean.class);
return bean == null ? new WinBollClientServiceBean() : bean;
}
public static boolean saveWinBollServiceBean(WinBollClientService service, WinBollClientServiceBean bean) {
return WinBollClientServiceBean.saveBean(service, bean);
}
}

View File

@@ -1,22 +0,0 @@
package cc.winboll.studio.libaes.winboll;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 19:13:20
* @Describe WinBoll 邮件服务
*/
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class WinBollMail extends Service {
public static final String TAG = "WinBollMail";
@Override
public IBinder onBind(Intent intent) {
return null;
}
}

View File

@@ -1,106 +0,0 @@
package cc.winboll.studio.libaes.winboll;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/29 15:57:28
* @Describe WinBoll 服务器服务情况测试访问进程。
*/
import cc.winboll.studio.libappbase.LogUtils;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Credentials;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
// 新增自定义回调接口
interface TextCallback {
void onSuccess(String text);
void onFailure(Exception e);
}
public class WinBollServerConnectionThread extends Thread {
public static final String TAG = "WinBollClientService";
private final String url;
private final String username;
private final String password;
private final int connectTimeout;
private final int readTimeout;
private final int maxRetries;
private final TextCallback callback; // 新增回调成员变量
// 新增带回调的构造函数
public WinBollServerConnectionThread(String url, String username, String password, TextCallback callback) {
this(url, username, password, 10000, 10000, 5, callback);
}
// 修改原有构造函数,添加回调参数
public WinBollServerConnectionThread(String url, String username, String password,
int connectTimeout, int readTimeout, int maxRetries, TextCallback callback) {
this.url = url;
this.username = username;
this.password = password;
this.connectTimeout = connectTimeout;
this.readTimeout = readTimeout;
this.maxRetries = maxRetries;
this.callback = callback;
}
@Override
public void run() {
LogUtils.d(TAG, String.format("run() url %s\nusername %s\npassword %s", url, username, password));
String credential = Credentials.basic(username, password);
LogUtils.d(TAG, String.format("credential %s", credential));
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.header("Accept", "text/plain")
.header("Authorization", credential)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// 优先调用自定义回调
if (callback != null) {
callback.onFailure(e);
} else {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (!response.isSuccessful()) {
if (callback != null) {
callback.onFailure(new Exception("Unexpected code " + response));
} else {
LogUtils.d(TAG, "Unexpected code " + response, Thread.currentThread().getStackTrace());
}
return;
}
try {
String text = response.body().string();
// 优先调用自定义回调
if (callback != null) {
callback.onSuccess(text);
} else {
LogUtils.d(TAG, text);
}
} catch (Exception e) {
if (callback != null) {
callback.onFailure(e);
} else {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
}
}
});
}
}

View File

@@ -1,472 +0,0 @@
package cc.winboll.studio.libaes.winboll;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 17:41:55
* @Describe WinBoll 服务主机连接状态视图
*/
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import cc.winboll.studio.libaes.winboll.WinBollClientService;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libapputils.R;
import cc.winboll.studio.libapputils.utils.PrefUtils;
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;
public class WinBollServiceStatusView extends LinearLayout {
public static final String TAG = "WinBollServiceStatusView";
public static final int MSG_CONNECTION_INFO = 0;
public static final int MSG_UPDATE_CONNECTION_STATUS = 1;
static WinBollServiceStatusView _WinBollServiceStatusView;
Context mContext;
//boolean mIsConnected;
volatile ConnectionThread mConnectionThread;
String mszServerHost;
WinBollClientService mWinBollService;
ImageView mImageView;
TextView mTextView;
WinBollServiceViewHandler mWinBollServiceViewHandler;
//WebView mWebView;
static volatile ConnectionStatus mConnectionStatus;
View.OnClickListener mViewOnClickListener;
static String _mUserName;
static String _mPassword;
static enum ConnectionStatus {
DISCONNECTED,
START_CONNECT,
CONNECTING,
CONNECTED;
};
boolean isBound = false;
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IWinBollClientServiceBinder binder = (IWinBollClientServiceBinder) service;
mWinBollService = binder.getService();
isBound = true;
// 可以在这里调用Service的方法进行通信比如获取数据
mImageView.setBackgroundDrawable(mWinBollService.getCurrentStatusIconDrawable());
}
@Override
public void onServiceDisconnected(ComponentName name) {
isBound = false;
}
};
public WinBollServiceStatusView(Context context) {
super(context);
mContext = context;
initView();
}
public WinBollServiceStatusView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
initView();
}
public WinBollServiceStatusView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
initView();
}
public WinBollServiceStatusView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mContext = context;
initView();
}
ConnectionStatus getConnectionStatus() {
return false ?
ConnectionStatus.CONNECTED
: ConnectionStatus.DISCONNECTED;
}
void initView() {
_WinBollServiceStatusView = this;
mImageView = new ImageView(mContext);
setImageViewByConnection(mImageView, false);
mConnectionStatus = getConnectionStatus();
//mIsConnected = false;
//mWinBollServerHostConnectionStatus = WinBollServerHostConnectionStatus.DISCONNECTED;
//ToastUtils.show("initView()");
mViewOnClickListener = new View.OnClickListener(){
@Override
public void onClick(View v) {
LogUtils.d(TAG, "onClick()");
if (mConnectionStatus == ConnectionStatus.CONNECTED) {
LogUtils.d(TAG, "Click to stop service.");
WinBollClientServiceBean bean = WinBollClientServiceBean.loadWinBollClientServiceBean(mContext);
bean.setIsEnable(false);
WinBollClientServiceBean.saveBean(mContext, bean);
Intent intent = new Intent(mContext, WinBollClientService.class);
mContext.stopService(intent);
//stopConnectionThread();
mTextView.setText("");
setImageViewByConnection(mImageView, false);
mConnectionStatus = ConnectionStatus.DISCONNECTED;
} else if (mConnectionStatus == ConnectionStatus.DISCONNECTED) {
LogUtils.d(TAG, "Click to start service.");
WinBollClientServiceBean bean = WinBollClientServiceBean.loadWinBollClientServiceBean(mContext);
bean.setIsEnable(true);
WinBollClientServiceBean.saveBean(mContext, bean);
Intent intent = new Intent(mContext, WinBollClientService.class);
mContext.startService(intent);
//startConnectionThread();
}
}
};
setOnClickListener(mViewOnClickListener);
addView(mImageView);
mTextView = new TextView(mContext);
mWinBollServiceViewHandler = new WinBollServiceViewHandler(this);
addView(mTextView);
/*mWebView = new WebView(mContext);
mWebView.setWebViewClient(new WebViewClient() {
@Override
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
// 弹出系统基本HTTP验证窗口
handler.proceed("username", "password");
}
});
addView(mWebView);*/
}
void checkWinBollServerStatusAndUpdateCurrentView() {
LogUtils.d(TAG, "checkWinBollServerStatusAndUpdateCurrentView()");
/*if (getConnectionStatus() == ConnectionStatus.CONNECTED) {
mConnectionStatus = ConnectionStatus.CONNECTED;
} else {
mConnectionStatus = ConnectionStatus.DISCONNECTED;
}*/
}
public void setServerHost(String szWinBollServerHost) {
mszServerHost = szWinBollServerHost;
}
public void setAuthInfo(String username, String password) {
_mUserName = username;
_mPassword = password;
}
void setImageViewByConnection(ImageView imageView, boolean isConnected) {
//mIsConnected = isConnected;
// 获取vector drawable
Drawable drawable = mContext.getDrawable(isConnected ? R.drawable.ic_dev_connected : R.drawable.ic_dev_disconnected);
if (drawable != null) {
imageView.setImageDrawable(drawable);
}
}
TextCallback apiTextCallback = new TextCallback() {
@Override
public void onSuccess(String text) {
// 处理成功响应
LogUtils.d(TAG, text);
}
@Override
public void onFailure(Exception e) {
// 处理失败情况
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
};
TextCallback cipTextCallback = new TextCallback() {
@Override
public void onSuccess(String text) {
// 处理成功响应
LogUtils.d(TAG, text);
LogUtils.d(TAG, "Develop Host Connection IP is : " + text);
mConnectionStatus = ConnectionStatus.CONNECTED;
// 获取当前时间
LocalDateTime now = LocalDateTime.now();
// 定义时间格式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
// 按照指定格式格式化时间并输出
String formattedDateTime = now.format(formatter);
String msg = "ClientIP<" + formattedDateTime + ">: " + text;
mWinBollServiceViewHandler.postMessageText(msg);
mWinBollServiceViewHandler.postMessageConnectionStatus(true);
}
@Override
public void onFailure(Exception e) {
// 处理失败情况
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
// 处理网络请求失败
setImageViewByConnection(mImageView, false);
mWinBollServiceViewHandler.postMessageText(e.getMessage());
mWinBollServiceViewHandler.postMessageConnectionStatus(false);
}
};
public void requestAPIWithBasicAuth() {
String targetUrl = "https://" + (GlobalApplication.isDebuging() ?"dev.winboll": "winboll") + ".cc/api/"; // 替换为实际测试的URL
requestWithBasicAuth(targetUrl, apiTextCallback);
}
public void requestCIPWithBasicAuth() {
String targetUrl = mszServerHost + "/cip/?simple=true";
requestWithBasicAuth(targetUrl, cipTextCallback);
}
public void requestWithBasicAuth(String targetUrl, TextCallback callback) {
String username = "";
String password = "";
if (GlobalApplication.isDebuging()) {
username = PrefUtils.getString(mContext, "metDevUserName", "");
password = PrefUtils.getString(mContext, "metDevUserPassword", "");
} else {
username = "WinBoll";
password = "WinBollPowerByZhanGSKen";
}
LogUtils.d(TAG, String.format("Connection Start. targetUrl %s", targetUrl));
WinBollServerConnectionThread thread = new WinBollServerConnectionThread(
targetUrl,
username,
password,
cipTextCallback
);
thread.start();
}
/*void requestWithBasicAuth(final WinBollServiceViewHandler textViewHandler, String targetUrl, final String username, final String password) {
// 用户名和密码,替换为实际的认证信息
//String username = "your_username";
//String password = "your_password";
LogUtils.d(TAG, "requestWithBasicAuth(...)");
LogUtils.d(TAG, String.format("targetUrl %s", targetUrl));
// 构建包含认证信息的请求
String credential = Credentials.basic(username, password);
LogUtils.d(TAG, String.format("credential %s", credential));
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(targetUrl)
.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) {
// 处理网络请求失败
setImageViewByConnection(mImageView, false);
textViewHandler.postMessageText(e.getMessage());
textViewHandler.postMessageConnectionStatus(false);
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
//String sz = "请求失败,状态码: " + response.code();
//setImageViewByConnection(mImageView, false);
//LogUtils.d(TAG, sz);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (!response.isSuccessful()) {
setImageViewByConnection(mImageView, false);
textViewHandler.postMessageText("Unexpected code " + response);
textViewHandler.postMessageConnectionStatus(false);
LogUtils.d(TAG, "Unexpected code " + response, Thread.currentThread().getStackTrace());
return;
}
try {
// 读取响应体作为字符串,注意这里可能需要解码
String text = response.body().string();
LogUtils.d(TAG, "Develop Host Connection IP is : " + text);
mConnectionStatus = ConnectionStatus.CONNECTED;
// 获取当前时间
LocalDateTime now = LocalDateTime.now();
// 定义时间格式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
// 按照指定格式格式化时间并输出
String formattedDateTime = now.format(formatter);
textViewHandler.postMessageText("ClientIP<" + formattedDateTime + ">: " + text);
textViewHandler.postMessageConnectionStatus(true);
//org.jsoup.nodes.Document doc = org.jsoup.Jsoup.parse(text);
//LogUtils.d(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));
//System.out.println(response.body().string());
// mConnectionStatus = ConnectionStatus.CONNECTED;
// // 获取当前时间
// 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);
} catch (Exception e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
}
});
}*/
class WinBollServiceViewHandler extends Handler {
WinBollServiceStatusView mDevelopHostConnectionStatusView;
public WinBollServiceViewHandler(WinBollServiceStatusView view) {
mDevelopHostConnectionStatusView = view;
}
@Override
public void handleMessage(Message msg) {
if (msg.what == MSG_CONNECTION_INFO) {
mDevelopHostConnectionStatusView.mTextView.setText((String)msg.obj);
} else if (msg.what == MSG_UPDATE_CONNECTION_STATUS) {
mDevelopHostConnectionStatusView.setImageViewByConnection(mImageView, (boolean)msg.obj);
mDevelopHostConnectionStatusView.mConnectionStatus = ((boolean)msg.obj) ? ConnectionStatus.CONNECTED : ConnectionStatus.DISCONNECTED;
}
super.handleMessage(msg);
}
void postMessageText(String szMSG) {
Message msg = new Message();
msg.what = MSG_CONNECTION_INFO;
msg.obj = szMSG;
sendMessage(msg);
}
void postMessageConnectionStatus(boolean isConnected) {
Message msg = new Message();
msg.what = MSG_UPDATE_CONNECTION_STATUS;
msg.obj = isConnected;
sendMessage(msg);
}
}
public static void startConnection() {
if (_WinBollServiceStatusView != null) {
_WinBollServiceStatusView.startConnectionThread();
}
}
public static void stopConnection() {
if (_WinBollServiceStatusView != null) {
_WinBollServiceStatusView.stopConnectionThread();
}
}
void startConnectionThread() {
if (mConnectionStatus == ConnectionStatus.DISCONNECTED) {
mConnectionStatus = ConnectionStatus.START_CONNECT;
LogUtils.d(TAG, "startConnectionThread");
if (mConnectionThread != null) {
LogUtils.d(TAG, "mConnectionThread != null");
mConnectionThread.mIsExist = true;
}
mConnectionThread = new ConnectionThread();
mConnectionThread.start();
} else if (mConnectionStatus == ConnectionStatus.CONNECTING) {
//LogUtils.d(TAG, "mConnectionStatus == ConnectionStatus.CONNECTING");
} else if (mConnectionStatus == ConnectionStatus.CONNECTED) {
//LogUtils.d(TAG, "mConnectionStatus == ConnectionStatus.CONNECTED");
} else {
LogUtils.d(TAG, String.format("Unknow mConnectionStatus %s, can not start ConnectionThread.", mConnectionStatus));
}
}
void stopConnectionThread() {
LogUtils.d(TAG, "stopConnectionThread");
if (mConnectionThread != null) {
LogUtils.d(TAG, "mConnectionThread != null");
mConnectionThread.mIsExist = true;
mConnectionThread = null;
}
}
class ConnectionThread extends Thread {
public volatile boolean mIsExist;
//DevelopHostConnectionStatusViewHandler mDevelopHostConnectionStatusViewHandler;
//public ConnectionThread(DevelopHostConnectionStatusViewHandler developHostConnectionStatusViewHandler) {
//mDevelopHostConnectionStatusViewHandler = developHostConnectionStatusViewHandler;
//}
public ConnectionThread() {
mIsExist = false;
}
@Override
public void run() {
super.run();
while (mIsExist == false) {
if (mConnectionStatus == ConnectionStatus.START_CONNECT) {
mConnectionStatus = ConnectionStatus.CONNECTING;
//requestAPIWithBasicAuth();
requestCIPWithBasicAuth();
} else if (mConnectionStatus == ConnectionStatus.CONNECTED
|| mConnectionStatus == ConnectionStatus.DISCONNECTED) {
//ToastUtils.show("mWinBollServerHostConnectionStatus " + mConnectionStatus);
LogUtils.d(TAG, String.format("mConnectionStatus done %s", mConnectionStatus));
} else {
LogUtils.d(TAG, String.format("mConnectionStatus unknow %s", mConnectionStatus));
}
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
}
//ToastUtils.show("ConnectionThread exit.");
LogUtils.d(TAG, "ConnectionThread exit.");
}
}
/*WinBollService.OnServiceStatusChangeListener mOnServerStatusChangeListener = new WinBollService.OnServiceStatusChangeListener(){
@Override
public void onServerStatusChange(boolean isServiceAlive) {
}
};*/
}

View File

@@ -1,41 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 阴影部分 -->
<!-- 个人觉得更形象的表达top代表下边的阴影高度left代表右边的阴影宽度。其实也就是相对应的offsetsolid中的颜色是阴影的颜色也可以设置角度等等 -->
<item
android:left="2dp"
android:top="2dp"
android:right="2dp"
android:bottom="2dp">
<shape android:shape="rectangle" >
<gradient
android:angle="270"
android:endColor="#0F000000"
android:startColor="#0F000000" />
<corners
android:bottomLeftRadius="6dip"
android:bottomRightRadius="6dip"
android:topLeftRadius="6dip"
android:topRightRadius="6dip" />
</shape>
</item>
<!-- 背景部分 -->
<!-- 形象的表达bottom代表背景部分在上边缘超出阴影的高度right代表背景部分在左边超出阴影的宽度相对应的offset -->
<item
android:left="3dp"
android:top="3dp"
android:right="3dp"
android:bottom="5dp">
<shape android:shape="rectangle" >
<gradient
android:angle="270"
android:endColor="@color/colorAccent"
android:startColor="@color/colorAccent" />
<corners
android:bottomLeftRadius="6dip"
android:bottomRightRadius="6dip"
android:topLeftRadius="6dip"
android:topRightRadius="6dip" />
</shape>
</item>
</layer-list>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#ff000000"
android:pathData="M6.62,10.79C8.06,13.62 10.38,15.94 13.21,17.38L15.41,15.18C15.69,14.9 16.08,14.82 16.43,14.93C17.55,15.3 18.75,15.5 20,15.5A1,1 0,0 1,21 16.5V20A1,1 0,0 1,20 21A17,17 0,0 1,3 4A1,1 0,0 1,4 3H7.5A1,1 0,0 1,8.5 4C8.5,5.25 8.7,6.45 9.07,7.57C9.18,7.92 9.1,8.31 8.82,8.59L6.62,10.79Z"/>
</vector>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#ff000000"
android:pathData="M4,1C2.89,1 2,1.89 2,3V7C2,8.11 2.89,9 4,9H1V11H13V9H10C11.11,9 12,8.11 12,7V3C12,1.89 11.11,1 10,1H4M4,3H10V7H4V3M3,12V14H5V12H3M14,13C12.89,13 12,13.89 12,15V19C12,20.11 12.89,21 14,21H11V23H23V21H20C21.11,21 22,20.11 22,19V15C22,13.89 21.11,13 20,13H14M3,15V17H5V15H3M14,15H20V19H14V15M3,18V20H5V18H3M6,18V20H8V18H6M9,18V20H11V18H9Z"/>
</vector>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#ff000000"
android:pathData="M4,1C2.89,1 2,1.89 2,3V7C2,8.11 2.89,9 4,9H1V11H13V9H10C11.11,9 12,8.11 12,7V3C12,1.89 11.11,1 10,1H4M4,3H10V7H4V3M14,13C12.89,13 12,13.89 12,15V19C12,20.11 12.89,21 14,21H11V23H23V21H20C21.11,21 22,20.11 22,19V15C22,13.89 21.11,13 20,13H14M3.88,13.46L2.46,14.88L4.59,17L2.46,19.12L3.88,20.54L6,18.41L8.12,20.54L9.54,19.12L7.41,17L9.54,14.88L8.12,13.46L6,15.59L3.88,13.46M14,15H20V19H14V15Z"/>
</vector>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#ff000000"
android:pathData="M22,6C22,4.9 21.1,4 20,4H4C2.9,4 2,4.9 2,6V18C2,19.1 2.9,20 4,20H20C21.1,20 22,19.1 22,18V6M20,6L12,11L4,6H20M20,18H4V8L12,13L20,8V18Z"/>
</vector>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#ff000000"
android:pathData="M24,7H22V13H24V7M24,15H22V17H24V15M20,6C20,4.9 19.1,4 18,4H2C0.9,4 0,4.9 0,6V18C0,19.1 0.9,20 2,20H18C19.1,20 20,19.1 20,18V6M18,6L10,11L2,6H18M18,18H2V8L10,13L18,8V18Z"/>
</vector>

View File

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

View File

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

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M16.61,15.15C16.15,15.15 15.77,14.78 15.77,14.32S16.15,13.5 16.61,13.5H16.61C17.07,13.5 17.45,13.86 17.45,14.32C17.45,14.78 17.07,15.15 16.61,15.15M7.41,15.15C6.95,15.15 6.57,14.78 6.57,14.32C6.57,13.86 6.95,13.5 7.41,13.5H7.41C7.87,13.5 8.24,13.86 8.24,14.32C8.24,14.78 7.87,15.15 7.41,15.15M16.91,10.14L18.58,7.26C18.67,7.09 18.61,6.88 18.45,6.79C18.28,6.69 18.07,6.75 18,6.92L16.29,9.83C14.95,9.22 13.5,8.9 12,8.91C10.47,8.91 9,9.24 7.73,9.82L6.04,6.91C5.95,6.74 5.74,6.68 5.57,6.78C5.4,6.87 5.35,7.08 5.44,7.25L7.1,10.13C4.25,11.69 2.29,14.58 2,18H22C21.72,14.59 19.77,11.7 16.91,10.14H16.91Z"/>
</vector>

View File

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

View File

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

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="180"
android:endColor="#FFFFFFFF"
android:startColor="#FFFFFFFF"
android:type="linear" />
<corners android:radius="10dp" />
</shape>

View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="1dp"
android:color="#000000" /> <!-- 这里可调整边框宽度和颜色 -->
<solid android:color="@android:color/transparent" />
</shape>

View File

@@ -1,27 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:fillColor="#FF1E9B54"
android:strokeColor="#FFF8E733"
android:strokeWidth="20.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M254.63 35.45C374.95 35.45 473.38 133.89 473.38 254.2 473.38 374.51 374.95 472.95 254.63 472.95 134.32 472.95 35.88 374.51 35.88 254.2 35.88 133.89 134.32 35.45 254.63 35.45"/>
<path
android:fillColor="#FF000000"
android:strokeColor="#FF000000"
android:strokeWidth="1.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M257.28 361.25C266.56 361.25 274.14 368.84 274.14 378.11 274.14 387.39 266.56 394.98 257.28 394.98 248.01 394.98 240.42 387.39 240.42 378.11 240.42 368.84 248.01 361.25 257.28 361.25"/>
<path
android:fillColor="#00000000"
android:strokeColor="#FF000000"
android:strokeWidth="30.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M182.16 214.09C181.42 199.71 182.42 177.87 207.64 155.49 213.64 150.16 220.13 146.12 226.28 143.08 238.64 136.97 249.62 134.91 252.55 134.56 252.7 134.54 252.83 134.53 252.94 134.52 253.05 134.51 253.14 134.5 253.2 134.5 255.01 134.48 294.9 136.66 313.05 160.43 332.29 185.63 344.82 221.3 300.07 263.56 263.08 298.49 258.36 318 258.54 317.72"/>
</vector>

View File

@@ -1,48 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:fillColor="#FF1E9B54"
android:strokeColor="#FFF8E733"
android:strokeWidth="20.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M254.63 35.45C374.95 35.45 473.38 133.89 473.38 254.2 473.38 374.51 374.95 472.95 254.63 472.95 134.32 472.95 35.88 374.51 35.88 254.2 35.88 133.89 134.32 35.45 254.63 35.45"/>
<path
android:fillColor="#FFFFFFFF"
android:strokeColor="#FFFFFFFF"
android:strokeWidth="1.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M257.28 361.25C266.56 361.25 274.14 368.84 274.14 378.11 274.14 387.39 266.56 394.98 257.28 394.98 248.01 394.98 240.42 387.39 240.42 378.11 240.42 368.84 248.01 361.25 257.28 361.25"/>
<path
android:fillColor="#00000000"
android:strokeColor="#FF000000"
android:strokeWidth="30.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M182.16 214.09C181.42 199.71 182.42 177.87 207.64 155.49 213.64 150.16 220.13 146.12 226.28 143.08 238.64 136.97 249.62 134.91 252.55 134.56 252.7 134.54 252.83 134.53 252.94 134.52 253.05 134.51 253.14 134.5 253.2 134.5 255.01 134.48 294.9 136.66 313.05 160.43 332.29 185.63 344.82 221.3 300.07 263.56 263.08 298.49 258.36 318 258.54 317.72"/>
<path
android:fillColor="#00000000"
android:strokeColor="#FFFFFFFF"
android:strokeWidth="30.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M103.77 307.45C103.02 293.07 104.03 271.24 129.24 248.85 135.25 243.52 141.74 239.48 147.89 236.44 160.24 230.34 171.23 228.28 174.15 227.92 174.31 227.9 174.44 227.89 174.55 227.88 174.66 227.87 174.75 227.86 174.81 227.86 176.62 227.85 216.5 230.02 234.65 253.79 253.9 278.99 266.43 314.66 221.67 356.93 184.69 391.85 179.97 411.36 180.15 411.08"/>
<path
android:fillColor="#00000000"
android:strokeColor="#FFFFFFFF"
android:strokeWidth="30.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M248.17 309.83C247.43 295.45 248.43 273.62 273.64 251.23 279.65 245.9 286.14 241.86 292.29 238.82 304.65 232.72 315.63 230.65 318.55 230.3 318.71 230.28 318.84 230.27 318.95 230.26 319.06 230.25 319.15 230.24 319.21 230.24 321.02 230.22 360.9 232.4 379.06 256.17 398.3 281.37 410.83 317.04 366.08 359.31 329.09 394.23 324.37 413.74 324.55 413.46"/>
<path
android:fillColor="#00000000"
android:strokeColor="#FFFFFFFF"
android:strokeWidth="30.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M182.16 214.09C181.42 199.71 182.42 177.87 207.64 155.49 213.64 150.16 220.13 146.12 226.28 143.08 238.64 136.97 249.62 134.91 252.55 134.56 252.7 134.54 252.83 134.53 252.94 134.52 253.05 134.51 253.14 134.5 253.2 134.5 255.01 134.48 294.9 136.66 313.05 160.43 332.29 185.63 344.82 221.3 300.07 263.56 263.08 298.49 258.36 318 258.54 317.72"/>
</vector>

View File

@@ -1,20 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:fillColor="#FF1E9B54"
android:strokeColor="#FFF8E733"
android:strokeWidth="20.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M254.63 35.45C374.95 35.45 473.38 133.89 473.38 254.2 473.38 374.51 374.95 472.95 254.63 472.95 134.32 472.95 35.88 374.51 35.88 254.2 35.88 133.89 134.32 35.45 254.63 35.45"/>
<path
android:fillColor="#FFFFFFFF"
android:strokeColor="#FFFFFFFF"
android:strokeWidth="1.0"
android:strokeLineCap="round"
android:strokeMiterLimit="10"
android:pathData="M257.28 361.25C266.56 361.25 274.14 368.84 274.14 378.11 274.14 387.39 266.56 394.98 257.28 394.98 248.01 394.98 240.42 387.39 240.42 378.11 240.42 368.84 248.01 361.25 257.28 361.25"/>
</vector>

View File

@@ -1,11 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/aboutroot_ll">
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/activitylibraryFrameLayout1"/>
</LinearLayout>

View File

@@ -2,7 +2,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical">
@@ -12,49 +12,49 @@
android:layout_height="wrap_content"
android:text="AOHPCTCSeekBar"/>
<androidx.viewpager.widget.ViewPager
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0"
android:id="@+id/fragmentviewpageViewPager1"/>
<cc.winboll.studio.libaes.views.AOHPCTCSeekBar
android:layout_width="300dp"
android:layout_height="wrap_content"
android:id="@+id/fragmentviewpageAOHPCTCSeekBar1"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal"
android:gravity="center"
android:id="@+id/fragmentviewpageLinearLayout1">
<androidx.viewpager.widget.ViewPager
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0"
android:id="@+id/fragmentviewpageViewPager1"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
tools:ignore="ContentDescription"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal"
android:gravity="center"
android:id="@+id/fragmentviewpageLinearLayout1">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
tools:ignore="ContentDescription"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
tools:ignore="ContentDescription"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
tools:ignore="ContentDescription"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
tools:ignore="ContentDescription"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
tools:ignore="ContentDescription"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
tools:ignore="ContentDescription"/>
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
tools:ignore="ContentDescription"/>
<cc.winboll.studio.libappbase.LogView
android:layout_width="match_parent"
android:layout_height="300dp"
android:id="@+id/logview"/>
</LinearLayout>
</LinearLayout>

View File

@@ -1,64 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/viewaboutdevLinearLayout1">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView
android:layout_width="180dp"
android:layout_height="wrap_content"
android:text="DevelopUserName :"/>
<EditText
android:layout_width="0dp"
android:ems="10"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:id="@+id/viewaboutdevEditText1"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView
android:layout_width="180dp"
android:layout_height="wrap_content"
android:text="DevelopUserPassword :"/>
<EditText
android:layout_width="0dp"
android:inputType="textPassword"
android:layout_height="wrap_content"
android:ems="10"
android:layout_weight="1.0"
android:id="@+id/viewaboutdevEditText2"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
<cc.winboll.studio.libaes.winboll.WinBollServiceStatusView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/viewaboutdevWinBollServiceStatusView1"/>
</LinearLayout>
</LinearLayout>

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/viewaboutwwwLinearLayout1">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
<cc.winboll.studio.libaes.winboll.WinBollServiceStatusView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/viewaboutwwwWinBollServiceStatusView1"/>
</LinearLayout>
</LinearLayout>

View File

@@ -11,25 +11,6 @@
android:layout_height="wrap_content"
android:text="AOHPCTCSeekBar"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<cc.winboll.studio.libaes.views.AOHPCTCSeekBar
android:layout_width="300dp"
android:layout_height="wrap_content"
android:id="@+id/fragmentviewpageAOHPCTCSeekBar1"
android:padding="10dp"/>
<cc.winboll.studio.libaes.views.AOHPCTCSeekBar
android:layout_width="300dp"
android:layout_height="wrap_content"
android:id="@+id/fragmentviewpageAOHPCTCSeekBar2"
android:padding="10dp"/>
</LinearLayout>
</LinearLayout>

View File

@@ -9,9 +9,6 @@
android:title="TestAppCrash"/>
</menu>
</item>
<item
android:id="@+id/item_log"
android:title="Log"/>
<item
android:id="@+id/item_about"
android:title="About"/>

View File

@@ -13,7 +13,7 @@
<item
android:id="@+id/item_localfileselectdialog"
android:title="LocalFileSelectDialog"/>
<item
android:id="@+id/item_atoolbar"
android:title="Test AToolbar"/>

View File

@@ -32,13 +32,6 @@
<attr name="attrASupportToolbarEndColor"/>
</declare-styleable>
<declare-styleable name="AButton">
<attr name="attrAButtonTextColor" format="color" />
<attr name="attrAButtonPrimary" format="color" />
<attr name="attrAButtonPrimaryDark" format="color" />
<attr name="attrAButtonAccent" format="color" />
</declare-styleable>
<attr name="ActionSheetList" format="reference"/>
<!--<declare-styleable name="AToolbarStyle">
<attr name="attrAToolbarStartColor" format="color" />

View File

@@ -1,12 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 默认方案 -->
<color name="colorPrimary">#FF03AB4E</color>
<color name="colorPrimaryDark">#FF027C39</color>
<color name="colorAccent">#FF3DDC84</color>
<color name="colorText">#FFFFFB8D</color>
<color name="colorToastFrame">#FFA9A9A9</color>
<color name="colorToastFrame">#FFA9A9A9</color>
<color name="colorToastShadow">#FF000000</color>
<color name="colorToastBackgroung">#FFFFFFFF</color>
<color name="colorAToolbarStartColor">#FF7D3F12</color>
@@ -16,16 +14,16 @@
<color name="colorACardShadow">@color/colorPrimaryDark</color>
<color name="colorACardFrame">@color/colorPrimary</color>
<color name="colorACardBackgroung">@color/colorAccent</color>
<color name="colorATickProgressBarBackgroung">@color/colorAccent</color>
<color name="colorATickProgressBarProgress">@color/colorPrimary</color>
<color name="colorOHPCTSBackground">@color/colorAccent</color>
<color name="colorOHPCTSSecondaryProgress">@color/colorPrimary</color>
<color name="colorOHPCTSProgress">@color/colorPrimaryDark</color>
<!-- -->
<!-- 调试方案
<color name="colorPrimary">#FF727272</color>
<color name="colorPrimaryDark">#FF444444</color>
@@ -41,5 +39,5 @@
<color name="colorATickProgressBarBackgroung">#FF6DC4E2</color>
<color name="colorATickProgressBarProgress">#FF22B0E1</color>
-->
-->
</resources>

View File

@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AESTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorTextColor">#FF000000</item>
<item name="colorPrimary">#FF03AB4E</item>
<item name="colorPrimaryDark">#FF027C39</item>
<item name="colorAccent">#FF3DDC84</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColor">#FF000000</item>
<item name="aToolbar">@style/AESAToolbar</item>
<item name="aSupportToolbar">@style/AESASupportToolbar</item>
@@ -23,196 +24,158 @@
<item name="attrASupportToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrASupportToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="DepthAESTheme" parent="AESTheme">
<style name="DefaultAESTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorTextColor">#FF000000</item>
<item name="colorPrimary">#FF03AB4E</item>
<item name="colorPrimaryDark">#FF027C39</item>
<item name="colorAccent">#FF3DDC84</item>
<item name="android:textColor">#FF000000</item>
<item name="aToolbar">@style/DefaultAToolbar</item>
<item name="aSupportToolbar">@style/DefaultASupportToolbar</item>
</style>
<style name="DefaultAToolbar">
<item name="attrAToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrAToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrAToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrAToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="DefaultASupportToolbar">
<item name="attrASupportToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrASupportToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrASupportToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrASupportToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="DepthAESTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorTextColor">#FF000000</item>
<item name="colorPrimary">#FF2566FE</item>
<item name="colorPrimaryDark">#FF1359FF</item>
<item name="colorAccent">#FF8BAEFF</item>
<item name="android:textColor">#FF000000</item>
<item name="aToolbar">@style/DepthAToolbar</item>
<item name="aSupportToolbar">@style/DepthASupportToolbar</item>
</style>
<style name="SkyAESTheme" parent="AESTheme">
<style name="DepthAToolbar">
<item name="attrAToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrAToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrAToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrAToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="DepthASupportToolbar">
<item name="attrASupportToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrASupportToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrASupportToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrASupportToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="SkyAESTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorTextColor">#FF000000</item>
<item name="colorPrimary">#FF1E98D4</item>
<item name="colorPrimaryDark">#FF046A9C</item>
<item name="colorAccent">#FF8CD9FF</item>
<item name="android:textColor">#FF000000</item>
<item name="aToolbar">@style/SkyAToolbar</item>
<item name="aSupportToolbar">@style/SkyASupportToolbar</item>
</style>
<style name="GoldenAESTheme" parent="AESTheme">
<style name="SkyAToolbar">
<item name="attrAToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrAToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrAToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrAToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="SkyASupportToolbar">
<item name="attrASupportToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrASupportToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrASupportToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrASupportToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="GoldenAESTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorTextColor">#FF000000</item>
<item name="colorPrimary">#FFFFE22A</item>
<item name="colorPrimaryDark">#FFAE9600</item>
<item name="colorAccent">#FFFFED78</item>
<item name="android:textColor">#FF000000</item>
<item name="aToolbar">@style/GoldenAToolbar</item>
<item name="aSupportToolbar">@style/GoldenASupportToolbar</item>
</style>
<style name="MemorAESTheme" parent="AESTheme">
<style name="GoldenAToolbar">
<item name="attrAToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrAToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrAToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrAToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="GoldenASupportToolbar">
<item name="attrASupportToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrASupportToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrASupportToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrASupportToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="MemorAESTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorTextColor">#FF000000</item>
<item name="colorPrimary">#FFCE1ED4</item>
<item name="colorPrimaryDark">#FFB500BC</item>
<item name="colorAccent">#FFE653EB</item>
<item name="android:textColor">#FF000000</item>
<item name="aToolbar">@style/MemorAToolbar</item>
<item name="aSupportToolbar">@style/MemorASupportToolbar</item>
</style>
<style name="TaoAESTheme" parent="AESTheme">
<style name="MemorAToolbar">
<item name="attrAToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrAToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrAToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrAToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="MemorASupportToolbar">
<item name="attrASupportToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrASupportToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrASupportToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrASupportToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="TaoAESTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorTextColor">#FF000000</item>
<item name="colorPrimary">#FF9F9F9F</item>
<item name="colorPrimaryDark">#FF5E5E5E</item>
<item name="colorAccent">#FFD9D9D9</item>
<item name="android:textColor">#FF000000</item>
</style>
<!--<style name="AESTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorTextColor">#FF000000</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColor">#FF000000</item>
<item name="aToolbar">@style/AESAToolbar</item>
<item name="aSupportToolbar">@style/AESASupportToolbar</item>
</style>
<style name="AESAToolbar">
<item name="attrAToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrAToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrAToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrAToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="AESASupportToolbar">
<item name="attrASupportToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrASupportToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrASupportToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrASupportToolbarEndColor">?attr/colorAccent</item>
</style>-->
<!--<style name="DepthAESTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorTextColor">#FF000000</item>
<item name="colorPrimary">#FF2566FE</item>
<item name="colorPrimaryDark">#FF1359FF</item>
<item name="colorAccent">#FF8BAEFF</item>
<item name="android:textColor">#FF000000</item>
<item name="aToolbar">@style/DepthAToolbar</item>
<item name="aSupportToolbar">@style/DepthASupportToolbar</item>
</style>
<style name="DepthAToolbar">
<item name="attrAToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrAToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrAToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrAToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="DepthASupportToolbar">
<item name="attrASupportToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrASupportToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrASupportToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrASupportToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="SkyAESTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorTextColor">#FF000000</item>
<item name="colorPrimary">#FF1E98D4</item>
<item name="colorPrimaryDark">#FF046A9C</item>
<item name="colorAccent">#FF8CD9FF</item>
<item name="android:textColor">#FF000000</item>
<item name="aToolbar">@style/SkyAToolbar</item>
<item name="aSupportToolbar">@style/SkyASupportToolbar</item>
</style>
<style name="SkyAToolbar">
<item name="attrAToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrAToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrAToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrAToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="SkyASupportToolbar">
<item name="attrASupportToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrASupportToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrASupportToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrASupportToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="GoldenAESTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorTextColor">#FF000000</item>
<item name="colorPrimary">#FFFFE22A</item>
<item name="colorPrimaryDark">#FFAE9600</item>
<item name="colorAccent">#FFFFED78</item>
<item name="android:textColor">#FF000000</item>
<item name="aToolbar">@style/GoldenAToolbar</item>
<item name="aSupportToolbar">@style/GoldenASupportToolbar</item>
</style>
<style name="GoldenAToolbar">
<item name="attrAToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrAToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrAToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrAToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="GoldenASupportToolbar">
<item name="attrASupportToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrASupportToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrASupportToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrASupportToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="MemorAESTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorTextColor">#FF000000</item>
<item name="colorPrimary">#FFCE1ED4</item>
<item name="colorPrimaryDark">#FFB500BC</item>
<item name="colorAccent">#FFE653EB</item>
<item name="android:textColor">#FF000000</item>
<item name="aToolbar">@style/MemorAToolbar</item>
<item name="aSupportToolbar">@style/MemorASupportToolbar</item>
</style>
<style name="MemorAToolbar">
<item name="attrAToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrAToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrAToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrAToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="MemorASupportToolbar">
<item name="attrASupportToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrASupportToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrASupportToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrASupportToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="TaoAESTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorTextColor">#FF000000</item>
<item name="colorPrimary">#FF9F9F9F</item>
<item name="colorPrimaryDark">#FF5E5E5E</item>
<item name="colorAccent">#FFD9D9D9</item>
<item name="android:textColor">#FF000000</item>
<item name="aToolbar">@style/TaoAToolbar</item>
<item name="aSupportToolbar">@style/TaoASupportToolbar</item>
<item name="aToolbar">@style/TaoAToolbar</item>
<item name="aSupportToolbar">@style/TaoASupportToolbar</item>
</style>
<style name="TaoAToolbar">
<item name="attrAToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrAToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrAToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrAToolbarEndColor">?attr/colorAccent</item>
<item name="attrAToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrAToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrAToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrAToolbarEndColor">?attr/colorAccent</item>
</style>
<style name="TaoASupportToolbar">
<item name="attrASupportToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrASupportToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrASupportToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrASupportToolbarEndColor">?attr/colorAccent</item>
</style>-->
<item name="attrASupportToolbarTitleTextColor">?attr/colorTextColor</item>
<item name="attrASupportToolbarStartColor">?attr/colorPrimaryDark</item>
<item name="attrASupportToolbarCenterColor">?attr/colorPrimary</item>
<item name="attrASupportToolbarEndColor">?attr/colorAccent</item>
</style>
<!--<style name="AToolbar">
<item name="attrAToolbarTitleTextColor">#FF2DDA27</item>
<item name="attrAToolbarStartColor">#FF2DDA27</item>
<item name="attrAToolbarCenterColor">#FF2DDA27</item>
<item name="attrAToolbarEndColor">#FF2DDA27</item>
<item name="attrAToolbarTitleTextColor">#FF2DDA27</item>
<item name="attrAToolbarStartColor">#FF2DDA27</item>
<item name="attrAToolbarCenterColor">#FF2DDA27</item>
<item name="attrAToolbarEndColor">#FF2DDA27</item>
</style>-->
<!--对话框的样式-->

View File

@@ -24,13 +24,9 @@ dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
// Android 类库
//api 'com.android.support:appcompat-v7:28.0.0'
api('com.android.support:appcompat-v7:28.0.0'){
//exclude group: "com.android.support", module: "support-vector-drawable"
exclude group: "com.android.support:animated-vector-drawable:28.0.0"
}
api 'com.android.support:appcompat-v7:28.0.0' // 包含 AppCompatActivity
// https://mvnrepository.com/artifact/com.android.support/support-compat
//api 'com.android.support:support-compat:28.0.0' // 保留原有依赖(可选)
api 'com.android.support:support-compat:28.0.0' // 保留原有依赖(可选)
// https://mvnrepository.com/artifact/com.android.support/support-v4
api 'com.android.support:support-v4:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/support-media-compat

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Sat Mar 29 11:27:54 HKT 2025
stageCount=3
#Thu Mar 27 10:59:31 GMT 2025
stageCount=1
libraryProject=libappbase
baseVersion=15.2
publishVersion=15.2.2
buildCount=0
baseBetaVersion=15.2.3
baseVersion=15.1
publishVersion=15.1.0
buildCount=130
baseBetaVersion=15.1.1

View File

@@ -9,16 +9,12 @@
<!-- 发送持久广播 -->
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
<!-- 对正在运行的应用重新排序 -->
<uses-permission android:name="android.permission.REORDER_TASKS"/>
<application>
<activity
android:name=".CrashHandler$CrashActivity"
android:label="CrashActivity"
android:launchMode="singleInstance"
android:process=":CrashActivity"/>
android:launchMode="standard"/>
<activity
android:name=".GlobalCrashActivity"
@@ -27,8 +23,7 @@
android:process=":GlobalCrashActivity"/>
<activity
android:name=".winboll.LogActivity"
android:label="LogActivity"
android:name="cc.winboll.studio.libappbase.winboll.LogActivity"
android:resizeableActivity="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:exported="true"
@@ -47,8 +42,7 @@
android:name=".services.TestService"
android:exported="true"/>
<receiver
android:name=".receiver.MyBroadcastReceiver"
<receiver android:name=".receiver.MyBroadcastReceiver"
android:exported="true">
<intent-filter>
@@ -91,8 +85,7 @@
<service android:name="cc.winboll.studio.libappbase.sos.SOSCenter"/>
<receiver
android:name="cc.winboll.studio.libappbase.sos.SOSCenterServiceReceiver"
<receiver android:name="cc.winboll.studio.libappbase.sos.SOSCenterServiceReceiver"
android:exported="true">
<intent-filter>

View File

@@ -339,7 +339,6 @@ public final class CrashHandler {
int padding = dp2px(16);
message.setPadding(padding, padding, padding, padding);
message.setText(mLog);
message.setTextColor(Color.BLACK);
message.setTextIsSelectable(true);
}
hw.addView(message);

View File

@@ -19,18 +19,28 @@ public class GlobalApplication extends Application {
public static final String TAG = "GlobalApplication";
final static String PREFS = GlobalApplication.class.getName() + "PREFS";
final static String PREFS_ISDEBUGING = "PREFS_ISDEBUGING";
private static Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
volatile static GlobalApplication _GlobalApplication;
// 是否处于调试状态
volatile static boolean isDebuging = false;
MyActivityLifecycleCallbacks mMyActivityLifecycleCallbacks;
public static void setIsDebuging(boolean isDebuging) {
GlobalApplication.isDebuging = isDebuging;
}
public static void saveDebugStatus() {
if (_GlobalApplication != null) {
APPBaseModel.saveBeanToFile(getAPPBaseModelFilePath(), new APPBaseModel(GlobalApplication.isDebuging));
GlobalApplication.isDebuging = isDebuging;
APPBaseModel.saveBeanToFile(getAPPBaseModelFilePath(), new APPBaseModel(isDebuging));
// 获取SharedPreferences实例
// SharedPreferences sharedPreferences = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
// // 获取编辑器
// SharedPreferences.Editor editor = sharedPreferences.edit();
// // 保存数据
// editor.putBoolean(PREFS_ISDEBUGING, GlobalApplication.isDebuging);
// // 提交更改
// editor.apply();
}
}
@@ -46,39 +56,57 @@ public class GlobalApplication extends Application {
return isDebuging;
}
public static WinBollActivityManager getWinBollActivityManager() {
return WinBollActivityManager.getInstance(_GlobalApplication);
@Override
public Context getApplicationContext() {
return super.getApplicationContext();
}
public Application getApplication() {
return this;
}
@Override
public void onCreate() {
super.onCreate();
// 保存初始实例
_GlobalApplication = this;
setIsDebuging(true);
// 添加日志模块
// _GlobalApplication 取值调试部分
//
boolean is_GlobalApplicationNull = false;
if (_GlobalApplication == null) {
is_GlobalApplicationNull = true;
_GlobalApplication = this;
} else {
is_GlobalApplicationNull = false;
_GlobalApplication = this;
}
// 设置应用调试标志
APPBaseModel appBaseModel = APPBaseModel.loadBeanFromFile(getAPPBaseModelFilePath(), APPBaseModel.class);
if (appBaseModel == null) {
setIsDebuging(false);
} else {
setIsDebuging(appBaseModel.isDebuging());
}
LogUtils.init(this);
//LogUtils.setLogLevel(LogUtils.LOG_LEVEL.Debug);
//LogUtils.setTAGListEnable(GlobalApplication.TAG, true);
//LogUtils.setALlTAGListEnable(true);
//LogUtils.d(TAG, "LogUtils init");
// 设置应用异常处理窗口
CrashHandler.init(this);
// 初始化 Toast 框架
ToastUtils.init(this);
// 应用保存的调试标志
APPBaseModel appBaseModel = APPBaseModel.loadBeanFromFile(getAPPBaseModelFilePath(), APPBaseModel.class);
if (appBaseModel == null) {
setIsDebuging(false);
saveDebugStatus();
} else {
setIsDebuging(appBaseModel.isDebuging());
}
getWinBollActivityManager().setWinBollUI_TYPE(WinBollActivityManager.WinBollUI_TYPE.Service);
// 注册窗口回调监听
// _GlobalApplication 取值调试部分
//
LogUtils.d(TAG, String.format("is_GlobalApplicationNull is %s", is_GlobalApplicationNull));
WinBollActivityManager.getInstance(_GlobalApplication);
WinBollActivityManager.getInstance(_GlobalApplication).setWinBollUI_TYPE(WinBollActivityManager.WinBollUI_TYPE.Service);
// 注册回调
mMyActivityLifecycleCallbacks = new MyActivityLifecycleCallbacks();
registerActivityLifecycleCallbacks(mMyActivityLifecycleCallbacks);
}
@@ -87,6 +115,7 @@ public class GlobalApplication extends Application {
@Override
public void onTerminate() {
super.onTerminate();
_GlobalApplication = null;
// 注销回调(非必须,但建议释放资源)
unregisterActivityLifecycleCallbacks(mMyActivityLifecycleCallbacks);
}

View File

@@ -4,20 +4,26 @@ package cc.winboll.studio.libappbase;
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/11 00:14:05
*/
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import cc.winboll.studio.libappbase.R;
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;
@@ -39,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
@@ -92,4 +98,20 @@ public final class GlobalCrashActivity extends AppCompatActivity implements Menu
mGlobalCrashReportView.updateMenuStyle();
return true;
}
void joinQQGroup(String key) {
// 创建Intent
Intent intent = new Intent();
// 设置动作
intent.setAction("android.intent.action.VIEW");
// 设置数据为网址的URI
Uri content_url = Uri.parse("https://www.winboll.cc");
intent.setData(content_url);
// 添加标志
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 设置类名和活动名
intent.setClassName("com.android.browser", "com.android.browser.BrowserActivity");
// 启动Activity
startActivity(intent);
}
}

View File

@@ -8,7 +8,6 @@ package cc.winboll.studio.libappbase;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.support.v7.widget.Toolbar;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
@@ -17,6 +16,7 @@ import android.view.MenuItem;
import android.widget.LinearLayout;
import android.widget.TextView;
import cc.winboll.studio.libappbase.R;
import android.widget.Toolbar;
public class GlobalCrashReportView extends LinearLayout {

View File

@@ -220,17 +220,7 @@ public class LogUtils {
}
static boolean isLoggable(String tag, LOG_LEVEL logLevel) {
if (!_IsInited) {
return false;
}
if (mapTAGList.get(tag) == null
|| !mapTAGList.get(tag)) {
return false;
}
if (!isInTheLevel(logLevel)) {
return false;
}
return true;
return _IsInited && mapTAGList.get(tag) && isInTheLevel(logLevel);
}
static boolean isInTheLevel(LOG_LEVEL logLevel) {

View File

@@ -1,60 +0,0 @@
package cc.winboll.studio.libappbase.dialogs;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 17:40:47
* @Date 2024/08/12 14:46:25
* @Describe 询问用户确定与否的选择框
*/
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
public class YesNoAlertDialog {
public static final String TAG = "YesNoAlertDialog";
public static void show(Context context, String szTitle, String szMessage, final OnDialogResultListener listener) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
context);
// set title
alertDialogBuilder.setTitle(szTitle);
// set dialog message
alertDialogBuilder
.setMessage(szMessage)
.setCancelable(true)
.setOnCancelListener(new DialogInterface.OnCancelListener(){
@Override
public void onCancel(DialogInterface dialog) {
listener.onNo();
}
})
.setPositiveButton("YES", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, close
// current activity
listener.onYes();
}
})
.setNegativeButton("NO", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, just close
// the dialog box and do nothing
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
public interface OnDialogResultListener {
abstract void onYes();
abstract void onNo();
}
}

View File

@@ -8,17 +8,24 @@ import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.os.Bundle;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
public class MyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
public static final String TAG = "MyActivityLifecycleCallbacks";
public String mInfo = "";
public MyActivityLifecycleCallbacks() {
}
WinBollActivityManager getWinBollActivityManager() {
return WinBollActivityManager.getInstance(GlobalApplication.getInstance());
}
void createActivityeInfo(Activity activity) {
@@ -47,7 +54,7 @@ public class MyActivityLifecycleCallbacks implements Application.ActivityLifecyc
}
public void showActivityeInfo() {
//ToastUtils.show("ActivityeInfo : " + mInfo);
ToastUtils.show("ActivityeInfo : " + mInfo);
LogUtils.d(TAG, "ActivityeInfo : " + mInfo);
}
@@ -57,6 +64,7 @@ public class MyActivityLifecycleCallbacks implements Application.ActivityLifecyc
//System.out.println(activity.getLocalClassName() + " was created");
LogUtils.d(TAG, activity.getLocalClassName() + " was created");
createActivityeInfo(activity);
getWinBollActivityManager().add((IWinBollActivity)activity);
}
@Override
@@ -94,5 +102,6 @@ public class MyActivityLifecycleCallbacks implements Application.ActivityLifecyc
public void onActivityDestroyed(Activity activity) {
//System.out.println(activity.getLocalClassName() + " was destroyed");
LogUtils.d(TAG, activity.getLocalClassName() + " was destroyed");
getWinBollActivityManager().registeRemove((IWinBollActivity)activity);
}
}

View File

@@ -12,7 +12,6 @@ import android.app.ActivityManager;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import java.util.HashMap;
@@ -30,25 +29,27 @@ public class WinBollActivityManager {
};
// 应用类型标志
static volatile WinBollUI_TYPE _mWinBollUI_TYPE = WinBollUI_TYPE.Service;
volatile static WinBollUI_TYPE _mWinBollUI_TYPE = WinBollUI_TYPE.Service;
GlobalApplication mGlobalApplication;
static volatile WinBollActivityManager _Instance;
Context mContext;
MyActivityLifecycleCallbacks mMyActivityLifecycleCallbacks;
static volatile WinBollActivityManager _mWinBollActivityManager;
static volatile Map<String, IWinBollActivity> _mapIWinBollList;
volatile IWinBollActivity mFirstIWinBollActivity;
static volatile IWinBollActivity firstIWinBollActivity;
WinBollActivityManager(GlobalApplication application) {
mGlobalApplication = application;
public WinBollActivityManager(Context context) {
mContext = context;
LogUtils.d(TAG, "WinBollActivityManager()");
_mapIWinBollList = new HashMap<String, IWinBollActivity>();
}
public static synchronized WinBollActivityManager getInstance(GlobalApplication application) {
public static synchronized WinBollActivityManager getInstance(Context context) {
LogUtils.d(TAG, "getInstance");
if (_Instance == null) {
LogUtils.d(TAG, "_Instance == null");
_Instance = new WinBollActivityManager(application);
if (_mWinBollActivityManager == null) {
LogUtils.d(TAG, "_mWinBollActivityManager == null");
_mWinBollActivityManager = new WinBollActivityManager(context);
}
return _Instance;
return _mWinBollActivityManager;
}
//
@@ -72,12 +73,11 @@ public class WinBollActivityManager {
String tag = ((IWinBollActivity)iWinBoll).getTag();
LogUtils.d(TAG, String.format("add(T iWinBoll) tag is %s", tag));
if (isActive(tag)) {
LogUtils.d(TAG, String.format("isActive(tag) is true, tag : %s.", tag));
LogUtils.d(TAG, String.format("add(...) %s is active.", iWinBoll.getTag()));
} else {
// 设置起始活动窗口,以便最后退出时提问
if (mFirstIWinBollActivity == null && _mapIWinBollList.size() == 0) {
LogUtils.d(TAG, "Set firstIWinBollActivity, iWinBoll.getTag() is %s" + iWinBoll.getTag());
mFirstIWinBollActivity = iWinBoll;
if (firstIWinBollActivity == null && _mapIWinBollList.size() == 0) {
firstIWinBollActivity = iWinBoll;
}
// 添加到活动窗口列表
@@ -102,7 +102,7 @@ public class WinBollActivityManager {
resumeActivity(context, tag);
return;
}
//ToastUtils.show("startWinBollActivity(Context context, Class<T> clazz)");
ToastUtils.show("startWinBollActivity(Context context, Class<T> clazz)");
// 新建一个任务窗口
Intent intent = new Intent(context, clazz);
@@ -168,7 +168,7 @@ public class WinBollActivityManager {
}
public boolean isFirstIWinBollActivity(IWinBollActivity iWinBollActivity) {
return mFirstIWinBollActivity != null && mFirstIWinBollActivity == iWinBollActivity;
return firstIWinBollActivity != null && firstIWinBollActivity == iWinBollActivity;
}
//
@@ -220,10 +220,10 @@ public class WinBollActivityManager {
//
public <T extends IWinBollActivity> void resumeActivity(Context context, T iWinBoll) {
LogUtils.d(TAG, "resumeActivity(Context context, T iWinBoll)");
ActivityManager am = (ActivityManager) mGlobalApplication.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
//返回启动它的根任务home 或者 MainActivity
Intent intent = new Intent(mGlobalApplication, iWinBoll.getClass());
TaskStackBuilder stackBuilder = TaskStackBuilder.create(mGlobalApplication);
Intent intent = new Intent(mContext, iWinBoll.getClass());
TaskStackBuilder stackBuilder = TaskStackBuilder.create(mContext);
stackBuilder.addNextIntentWithParentStack(intent);
stackBuilder.startActivities();
//moveTaskToFront(YourTaskId, 0);
@@ -287,7 +287,7 @@ public class WinBollActivityManager {
IWinBollActivity preIWinBoll = getPreIWinBoll(iWinBoll);
iWinBoll.getActivity().finish();
if (preIWinBoll != null) {
resumeActivity(mGlobalApplication, preIWinBoll);
resumeActivity(mContext, preIWinBoll);
}
}

View File

@@ -7,9 +7,9 @@
android:layout_height="match_parent"
android:id="@+id/viewglobalcrashreportLinearLayout1">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
<android.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/viewglobalcrashreportToolbar1"/>
<ScrollView

1
ollama/.gitignore vendored Normal file
View File

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

View File

73
ollama/build.gradle Normal file
View File

@@ -0,0 +1,73 @@
apply plugin: 'com.android.application'
apply from: '../.winboll/winboll_app_build.gradle'
apply from: '../.winboll/winboll_lint_build.gradle'
def genVersionName(def versionName){
// 检查编译标志位配置
assert (winbollBuildProps['stageCount'] != null)
assert (winbollBuildProps['baseVersion'] != null)
// 保存基础版本号
winbollBuildProps.setProperty("baseVersion", "${versionName}");
//保存编译标志配置
FileOutputStream fos = new FileOutputStream(winbollBuildPropsFile)
winbollBuildProps.store(fos, "${winbollBuildPropsDesc}");
fos.close();
// 返回编译版本号
return "${versionName}." + winbollBuildProps['stageCount']
}
android {
compileSdkVersion 32
buildToolsVersion "32.0.0"
defaultConfig {
applicationId "cc.winboll.studio.ollama"
minSdkVersion 26
targetSdkVersion 29
versionCode 1
// versionName 更新后需要手动设置
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
versionName "15.0"
if(true) {
versionName = genVersionName("${versionName}")
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
api 'com.squareup.okhttp3:okhttp:4.4.1'
// 吐司类库
api 'com.github.getActivity:ToastUtils:10.5'
// Android 类库
api 'com.android.support:appcompat-v7:28.0.0' // 包含 AppCompatActivity
// https://mvnrepository.com/artifact/com.android.support/support-compat
api 'com.android.support:support-compat:28.0.0' // 保留原有依赖(可选)
// https://mvnrepository.com/artifact/com.android.support/support-v4
api 'com.android.support:support-v4:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/support-media-compat
api 'com.android.support:support-media-compat:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/support-core-utils
api 'com.android.support:support-core-utils:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/support-core-ui
api 'com.android.support:support-core-ui:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/support-fragment
api 'com.android.support:support-fragment:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/recyclerview-v7
api 'com.android.support:recyclerview-v7:28.0.0'
api 'cc.winboll.studio:libappbase:15.0.9'
api 'cc.winboll.studio:libapputils:15.0.11'
}

8
ollama/build.properties Normal file
View File

@@ -0,0 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Fri Mar 28 05:09:21 HKT 2025
stageCount=1
libraryProject=
baseVersion=15.0
publishVersion=15.0.0
buildCount=0
baseBetaVersion=15.0.1

21
ollama/proguard-rules.pro vendored Normal file
View 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

View 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>

View File

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

View File

@@ -0,0 +1,41 @@
<?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.ollama">
<!-- 拥有完全的网络访问权限 -->
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/MyAppTheme"
android:resizeableActivity="true"
android:name=".App"
android:networkSecurityConfig="@xml/network_security_config">
<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>

View File

@@ -0,0 +1,334 @@
package cc.winboll.studio.ollama;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.res.Resources;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import cc.winboll.studio.libappbase.GlobalApplication;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
public class App extends GlobalApplication {
private static Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
@Override
public void onCreate() {
super.onCreate();
//CrashHandler.getInstance().registerGlobal(this);
//CrashHandler.getInstance().registerPart(this);
}
public static void write(InputStream input, OutputStream output) throws IOException {
byte[] buf = new byte[1024 * 8];
int len;
while ((len = input.read(buf)) != -1) {
output.write(buf, 0, len);
}
}
public static void write(File file, byte[] data) throws IOException {
File parent = file.getParentFile();
if (parent != null && !parent.exists()) parent.mkdirs();
ByteArrayInputStream input = new ByteArrayInputStream(data);
FileOutputStream output = new FileOutputStream(file);
try {
write(input, output);
} finally {
closeIO(input, output);
}
}
public static String toString(InputStream input) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
write(input, output);
try {
return output.toString("UTF-8");
} finally {
closeIO(input, output);
}
}
public static void closeIO(Closeable... closeables) {
for (Closeable closeable : closeables) {
try {
if (closeable != null) closeable.close();
} catch (IOException ignored) {}
}
}
public static class CrashHandler {
public static final UncaughtExceptionHandler DEFAULT_UNCAUGHT_EXCEPTION_HANDLER = Thread.getDefaultUncaughtExceptionHandler();
private static CrashHandler sInstance;
private PartCrashHandler mPartCrashHandler;
public static CrashHandler getInstance() {
if (sInstance == null) {
sInstance = new CrashHandler();
}
return sInstance;
}
public void registerGlobal(Context context) {
registerGlobal(context, null);
}
public void registerGlobal(Context context, String crashDir) {
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandlerImpl(context.getApplicationContext(), crashDir));
}
public void unregister() {
Thread.setDefaultUncaughtExceptionHandler(DEFAULT_UNCAUGHT_EXCEPTION_HANDLER);
}
public void registerPart(Context context) {
unregisterPart(context);
mPartCrashHandler = new PartCrashHandler(context.getApplicationContext());
MAIN_HANDLER.postAtFrontOfQueue(mPartCrashHandler);
}
public void unregisterPart(Context context) {
if (mPartCrashHandler != null) {
mPartCrashHandler.isRunning.set(false);
mPartCrashHandler = null;
}
}
private static class PartCrashHandler implements Runnable {
private final Context mContext;
public AtomicBoolean isRunning = new AtomicBoolean(true);
public PartCrashHandler(Context context) {
this.mContext = context;
}
@Override
public void run() {
while (isRunning.get()) {
try {
Looper.loop();
} catch (final Throwable e) {
e.printStackTrace();
if (isRunning.get()) {
MAIN_HANDLER.post(new Runnable(){
@Override
public void run() {
Toast.makeText(mContext, e.toString(), Toast.LENGTH_LONG).show();
}
});
} else {
if (e instanceof RuntimeException) {
throw (RuntimeException)e;
} else {
throw new RuntimeException(e);
}
}
}
}
}
}
private static class UncaughtExceptionHandlerImpl implements UncaughtExceptionHandler {
private static DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss");
private final Context mContext;
private final File mCrashDir;
public UncaughtExceptionHandlerImpl(Context context, String crashDir) {
this.mContext = context;
this.mCrashDir = TextUtils.isEmpty(crashDir) ? new File(mContext.getExternalCacheDir(), "crash") : new File(crashDir);
}
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
try {
String log = buildLog(throwable);
writeLog(log);
try {
Intent intent = new Intent(mContext, CrashActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_TEXT, log);
mContext.startActivity(intent);
} catch (Throwable e) {
e.printStackTrace();
writeLog(e.toString());
}
throwable.printStackTrace();
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
} catch (Throwable e) {
if (DEFAULT_UNCAUGHT_EXCEPTION_HANDLER != null) DEFAULT_UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(thread, throwable);
}
}
private String buildLog(Throwable throwable) {
String time = DATE_FORMAT.format(new Date());
String versionName = "unknown";
long versionCode = 0;
try {
PackageInfo packageInfo = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0);
versionName = packageInfo.versionName;
versionCode = Build.VERSION.SDK_INT >= 28 ? packageInfo.getLongVersionCode() : packageInfo.versionCode;
} catch (Throwable ignored) {}
LinkedHashMap<String, String> head = new LinkedHashMap<String, String>();
head.put("Time Of Crash", time);
head.put("Device", String.format("%s, %s", Build.MANUFACTURER, Build.MODEL));
head.put("Android Version", String.format("%s (%d)", Build.VERSION.RELEASE, Build.VERSION.SDK_INT));
head.put("App Version", String.format("%s (%d)", versionName, versionCode));
head.put("Kernel", getKernel());
head.put("Support Abis", Build.VERSION.SDK_INT >= 21 && Build.SUPPORTED_ABIS != null ? Arrays.toString(Build.SUPPORTED_ABIS): "unknown");
head.put("Fingerprint", Build.FINGERPRINT);
StringBuilder builder = new StringBuilder();
for (String key : head.keySet()) {
if (builder.length() != 0) builder.append("\n");
builder.append(key);
builder.append(" : ");
builder.append(head.get(key));
}
builder.append("\n\n");
builder.append(Log.getStackTraceString(throwable));
return builder.toString();
}
private void writeLog(String log) {
String time = DATE_FORMAT.format(new Date());
File file = new File(mCrashDir, "crash_" + time + ".txt");
try {
write(file, log.getBytes("UTF-8"));
} catch (Throwable e) {
e.printStackTrace();
}
}
private static String getKernel() {
try {
return App.toString(new FileInputStream("/proc/version")).trim();
} catch (Throwable e) {
return e.getMessage();
}
}
}
}
public static final class CrashActivity extends Activity {
private String mLog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(android.R.style.Theme_DeviceDefault);
setTitle("App Crash");
mLog = getIntent().getStringExtra(Intent.EXTRA_TEXT);
ScrollView contentView = new ScrollView(this);
contentView.setFillViewport(true);
HorizontalScrollView horizontalScrollView = new HorizontalScrollView(this);
TextView textView = new TextView(this);
int padding = dp2px(16);
textView.setPadding(padding, padding, padding, padding);
textView.setText(mLog);
textView.setTextIsSelectable(true);
textView.setTypeface(Typeface.DEFAULT);
textView.setLinksClickable(true);
horizontalScrollView.addView(textView);
contentView.addView(horizontalScrollView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
setContentView(contentView);
}
private void restart() {
Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
if (intent != null) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
finish();
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
}
private static int dp2px(float dpValue) {
final float scale = Resources.getSystem().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, android.R.id.copy, 0, android.R.string.copy)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.copy:
ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
cm.setPrimaryClip(ClipData.newPlainText(getPackageName(), mLog));
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
restart();
}
}
}

View File

@@ -0,0 +1,88 @@
package cc.winboll.studio.ollama;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
public final static int MSG_APPEND = 0;
private Handler _Handler = new Handler(Looper.getMainLooper());
private TextView mtvMessage;
private EditText metAsk;
private Button mbtSend;
private ScrollView msvMessage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mtvMessage = (TextView) findViewById(R.id.message_tv);
metAsk = (EditText) findViewById(R.id.ask_et);
mbtSend = (Button) findViewById(R.id.send_bt);
msvMessage = findViewById(R.id.message_sv);
mbtSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendQuestion();
}
});
}
//
// 设置输入框获得焦点的类
//
// static class MyHandler extends Handler {
// WeakReference<MainActivity> mActivity;
// MyHandler(MainActivity activity) {
// mActivity = new WeakReference<MainActivity>(activity);
// }
// public void handleMessage(Message msg) {
// MainActivity theActivity = mActivity.get();
// switch (msg.what) {
// case MSG_APPEND:
// theActivity.mtvMessage.append((String)msg.obj);
// break;
// default:
// break;
// }
// super.handleMessage(msg);
// }
// }
private void sendQuestion() {
final String question = metAsk.getText().toString().trim();
if (!question.equals("")) {
mtvMessage.append("\n\nI " + metAsk.getText().toString() + "\nOllama : ");
metAsk.setText("");
new OllamaClient.SyncAskThread(question, new OllamaClient.OnAnswerCallback() {
@Override
public void onAnswer(final String answer) {
_Handler.post(new Runnable() {
@Override
public void run() {
mtvMessage.append(answer);
msvMessage.post(new Runnable(){
@Override
public void run() {
msvMessage.fullScroll(View.FOCUS_DOWN);
}
});
}
});
}
}).start();
}
}
}

View File

@@ -0,0 +1,223 @@
package cc.winboll.studio.ollama;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/27 19:55:28
* @Describe 简单Http协议访问客户端
*/
import cc.winboll.studio.libappbase.LogUtils;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.Source;
import org.json.JSONException;
import org.json.JSONObject;
public class OllamaClient {
public static final String TAG = "OllamaClient";
private static final String API_BASE_URL = "https://ollama-api.winboll.cc";
//private static final String API_BASE_URL = "http://10.8.0.10:11434";
//private static final OkHttpClient client = new OkHttpClient();
private static final OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.build();
// 1. 生成文本示例
// static void generateText(String prompt, String model) {
// String url = API_BASE_URL + "/api/generate";
// try {
// JSONObject payload = new JSONObject()
// .put("model", model)
// .put("prompt", prompt)
// .put("temperature", 0.7)
// .put("max_tokens", 200);
//
// Request request = new Request.Builder()
// .url(url)
// .post(RequestBody.create(payload.toString(), MediaType.get("application/json")))
// .build();
//
// Response response = client.newCall(request).execute();
// if (response.isSuccessful()) {
// String result = response.body().string();
// String formattedStream = OllamaResponseFormatter.formatStreamingResponse(result);
//
// // 输出示例:
//// [2025-03-27T19:34:29.274955439Z] [llama3.1:8b] It looks like you might have miss
//// [2025-03-27T19:34:30.482553089Z] [llama3.1:8b] pelled the word "Ollama" or perhaps said something that is not a standard word in the English language. However, I'm here to provide information and assistance on various topics, so please let me know what you meant by "Ollama." Was it related to a name, place, movie, game, or something else?
//
// LogUtils.d(TAG, formattedStream);
//// JSONObject json = new JSONObject(result);
//// LogUtils.d(TAG, "生成结果: " + json.getString("response"));
// //System.out.println("生成结果: " + json.getString("response"));
// } else {
// LogUtils.d(TAG, "请求失败: " + response.code());
// //System.out.println("请求失败: " + response.code() + " " + response.message());
// }
// } catch (JSONException|IOException e) {
// LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
// }
// }
// 实时输出流式响应的函数
static void generateTextStream(String prompt, String model, final OnAnswerCallback callback) {
String url = API_BASE_URL + "/api/generate";
try {
JSONObject payload = new JSONObject()
.put("model", model)
.put("prompt", prompt)
.put("temperature", 0.7)
.put("max_tokens", 200)
.put("stream", true); // 启用流式响应
Request request = new Request.Builder()
.url(url)
.post(RequestBody.create(payload.toString(), MediaType.get("application/json")))
.build();
LogUtils.d(TAG, "Request request");
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
LogUtils.d(TAG, "请求失败: " + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (!response.isSuccessful()) {
LogUtils.d(TAG, "请求失败: " + response.code());
return;
}
try (ResponseBody body = response.body()) {
if (body == null) return;
// 实时流式解析
LogUtils.d(TAG, "实时流式解析");
Source source = body.source();
Buffer buffer = new Buffer();
StringBuilder fullResponse = new StringBuilder();
boolean isDone = false;
while (!isDone && source.read(buffer, 1024) != -1) {
//LogUtils.d(TAG, "!isDone");
String chunk = buffer.readUtf8();
String[] lines = chunk.split("\n");
for (String line : lines) {
LogUtils.d(TAG, line);
if (line.trim().startsWith("{\"model\":")) {
LogUtils.d(TAG, line);
String jsonStr = line;
if (jsonStr.equals("[DONE]")) {
isDone = true;
LogUtils.d(TAG, "流式生成完成");
break;
}
try {
//LogUtils.d(TAG, jsonStr);
JSONObject json = new JSONObject(jsonStr);
//LogUtils.d(TAG, json.toString());
String responseText = json.getString("response");
//LogUtils.d(TAG, responseText);
fullResponse.append(responseText);
// 实时输出
callback.onAnswer(responseText);
LogUtils.d(TAG, "实时响应: " + responseText);
// 处理完成状态
if (json.getBoolean("done")) {
isDone = true;
String doneReason = json.optString("done_reason", "unknown");
LogUtils.d(TAG, "生成完成 (原因: " + doneReason + ")");
LogUtils.d(TAG, "完整回答: " + fullResponse.toString());
}
} catch (JSONException e) {
LogUtils.d(TAG, "JSON解析错误: " + e.getMessage());
}
}
}
}
}
}
});
} catch (JSONException e) {
LogUtils.d(TAG, "JSON格式错误: " + e.getMessage());
}
}
// 2. 获取模型列表示例
static void getModelList() {
String url = API_BASE_URL + "/v1/models";
LogUtils.d(TAG, "url : " + url);
Request request = new Request.Builder().url(url).build();
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
LogUtils.d(TAG, response.body().string());
// JSONArray models = new JSONArray(response.body().string());
// //System.out.println("可用模型列表:");
// LogUtils.d(TAG, "可用模型列表:");
// for (int i = 0; i < models.length(); i++) {
// JSONObject model = models.getJSONObject(i);
// LogUtils.d(TAG, "- " + model.getString("name") + " (" + model.getString("size") + ")");
// //System.out.println("- " + model.getString("name") + " (" + model.getString("size") + ")");
// }
} else {
LogUtils.d(TAG, "获取模型列表失败: " + response.code());
//System.out.println("获取模型列表失败: " + response.code());
}
} catch (IOException e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
}
static void unittest(String ask, OnAnswerCallback callback) {
// 获取模型列表
getModelList();
// 生成文本
generateTextStream(ask, "llama3.1:8b", callback);
}
public static class SyncAskThread extends Thread {
private String ask;
private OnAnswerCallback callback;
public SyncAskThread(String ask, OnAnswerCallback callback) {
this.ask = ask;
this.callback = callback;
}
@Override
public void run() {
super.run();
LogUtils.d(TAG, "run() start.");
unittest(ask, callback);
LogUtils.d(TAG, "run() end.");
}
}
public interface OnAnswerCallback {
void onAnswer(String answer);
}
}

View File

@@ -0,0 +1,72 @@
package cc.winboll.studio.ollama;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 03:38:50
*/
import org.json.JSONArray;
import org.json.JSONObject;
public class OllamaResponseFormatter {
public static final String TAG = "OllamaResponseFormatter";
// 处理模型列表响应
public static String formatModelList(String jsonResponse) {
try {
JSONObject json = new JSONObject(jsonResponse);
JSONArray models = json.getJSONArray("data");
StringBuilder sb = new StringBuilder();
sb.append("可用模型列表:\n");
for (int i = 0; i < models.length(); i++) {
JSONObject model = models.getJSONObject(i);
String modelId = model.getString("id");
sb.append(String.format("-%d. %s\n", i + 1, modelId));
}
return sb.toString();
} catch (Exception e) {
return "格式解析错误: " + e.getMessage();
}
}
// 处理流式生成文本响应
public static String formatStreamingResponse(String jsonResponse) {
try {
JSONObject json = new JSONObject(jsonResponse);
StringBuilder sb = new StringBuilder();
String responseText = json.getString("response");
boolean isDone = json.getBoolean("done");
// 添加时间戳和模型标识
String timestamp = json.getString("created_at");
String modelName = json.getString("model");
sb.append(String.format("[%s] [%s] ", timestamp, modelName));
// 处理响应内容
if (responseText.isEmpty() && isDone) {
sb.append("生成完成\n");
} else {
sb.append(responseText);
if (isDone) {
String doneReason = json.optString("done_reason", "unknown");
sb.append(String.format(" (完成原因: %s)\n", doneReason));
}
}
return sb.toString();
} catch (Exception e) {
return "格式解析错误: " + e.getMessage();
}
}
// 使用示例
public static void main(String[] args) {
// 模型列表测试
String modelListJson = "{\"object\":\"list\",\"data\":[{...}]}";
System.out.println(formatModelList(modelListJson));
// 流式响应测试
String streamingJson = "{\"model\":\"llama3.1:8b\",\"created_at\":\"2025-03-27T19:34:29.274955439Z\",\"response\":\"It\",\"done\":false}";
System.out.println(formatStreamingResponse(streamingJson));
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@@ -0,0 +1,69 @@
<?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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:gravity="center_vertical|center_horizontal"
android:layout_weight="1.0"
android:orientation="vertical">
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0"
android:id="@+id/message_sv">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Asking Ollama ..."
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/message_tv"/>
</ScrollView>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<EditText
android:layout_width="0dp"
android:ems="10"
android:layout_height="wrap_content"
android:id="@+id/ask_et"
android:layout_weight="1.0"
android:text="Hello, World!"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send"
android:id="@+id/send_bt"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0">
<cc.winboll.studio.libappbase.LogView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Text"
android:id="@+id/logview"/>
</LinearLayout>
</LinearLayout>

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