调试代码,加入AES转移模块。

This commit is contained in:
ZhanGSKen
2025-09-28 21:13:38 +08:00
parent ce131235c1
commit 1ee069afca
42 changed files with 1117 additions and 110 deletions

View File

@@ -45,6 +45,8 @@ android {
dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
api 'com.google.code.gson:gson:2.10.1'
// SSH
api 'com.jcraft:jsch:0.1.55'
@@ -67,7 +69,7 @@ dependencies {
//api 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
//api 'androidx.fragment:fragment:1.1.0'
api 'cc.winboll.studio:libaes:15.8.0'
api 'cc.winboll.studio:libapputils:15.8.2'
api 'cc.winboll.studio:libappbase:15.8.2'
api 'cc.winboll.studio:libaes:15.10.0'
api 'cc.winboll.studio:libapputils:15.10.0'
api 'cc.winboll.studio:libappbase:15.10.9'
}

View File

@@ -0,0 +1,97 @@
package cc.winboll.studio.libaes.winboll;
/**
* @Author ZhanGSKen<zhangsken@qq.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.models.WinBoLLClientServiceBean;
import cc.winboll.studio.libaes.winboll.AssistantService;
import cc.winboll.studio.libapputils.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.isServiceAlive(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

@@ -0,0 +1,35 @@
package cc.winboll.studio.libaes.winboll;
/**
* @Author ZhanGSKen<zhangsken@qq.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

@@ -10,7 +10,7 @@ public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainActivity";
LogView mLogView;
private TerminalView mTerminalView;
//private TerminalView mTerminalView;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -37,10 +37,10 @@ public class MainActivity extends AppCompatActivity {
mLogView = findViewById(R.id.logview);
mTerminalView = findViewById(R.id.terminalView);
/*mTerminalView = findViewById(R.id.terminalView);
// 示例:模拟用户输入 "ls" 命令
mTerminalView.sendInput("ls");
mTerminalView.sendInput("ls");*/
}
@Override

View File

@@ -1,14 +1,15 @@
package cc.winboll.studio.appbase;
package cc.winboll.studio.winboll;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
* @Date 2025/02/13 19:30:10
*/
import android.content.Context;
import cc.winboll.studio.winboll.R;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import cc.winboll.studio.appbase.models.MainServiceBean;
import cc.winboll.studio.appbase.services.MainService;
import cc.winboll.studio.winboll.models.MainServiceBean;
import cc.winboll.studio.winboll.services.MainService;
public class MyTileService extends TileService {
public static final String TAG = "MyTileService";

View File

@@ -0,0 +1,40 @@
package cc.winboll.studio.libaes.winboll;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
* @Date 2025/05/10 10:13
* @Describe WinBoLL 系列应用通用管理类
*/
import android.content.Context;
import android.content.Intent;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libaes.models.WinBoLLModel;
public class WinBoLL {
public static final String TAG = "WinBoLL";
public static final String ACTION_BIND = WinBoLL.class.getName() + ".ACTION_BIND";
public static final String EXTRA_WINBOLLMODEL = "EXTRA_WINBOLLMODEL";
public static void bindToAPPBase(Context context, String appMainService) {
LogUtils.d(TAG, "bindToAPPBase(...)");
String toPackage = "cc.winboll.studio.appbase";
startBind(context, toPackage, appMainService);
}
public static void bindToAPPBaseBeta(Context context, String appMainService) {
LogUtils.d(TAG, "bindToAPPBaseBeta(...)");
String toPackage = "cc.winboll.studio.appbase.beta";
startBind(context, toPackage, appMainService);
}
static void startBind(Context context, String toPackage, String appMainService) {
Intent intent = new Intent(ACTION_BIND);
intent.putExtra(EXTRA_WINBOLLMODEL, (new WinBoLLModel(toPackage, appMainService)).toString());
intent.setPackage(toPackage);
LogUtils.d(TAG, String.format("ACTION_BIND :\nTo Package : %s\nAPP Main Service : %s", toPackage, appMainService));
context.sendBroadcast(intent);
}
}

View File

@@ -0,0 +1,21 @@
package cc.winboll.studio.libaes.winboll;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
/**
* @Author ZhanGSKen
* @Date 2025/05/03 19:28
*/
public class WinBoLLClientService extends Service {
public static final String TAG = "WinBoLLClientService";
@Override
public IBinder onBind(Intent intent) {
return null;
}
}

View File

@@ -0,0 +1,38 @@
package cc.winboll.studio.libaes.winboll;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;
/**
* @Author ZhanGSKen
* @Date 2025/05/03 19:14
*/
public class WinBoLLServiceStatusView extends LinearLayout {
public static final String TAG = "WinBoLLServiceStatusView";
public WinBoLLServiceStatusView(Context context) {
super(context);
}
public WinBoLLServiceStatusView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WinBoLLServiceStatusView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public WinBoLLServiceStatusView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
void setServerHost(String szWinBoLLServerHost) {
}
void setAuthInfo(String szDevUserName, String szDevUserPassword) {
}
}

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.libappbase.activities;
package cc.winboll.studio.winboll.activities;
import android.app.Activity;
import android.os.Bundle;
@@ -7,14 +7,14 @@ import android.widget.RadioButton;
import cc.winboll.studio.libappbase.BuildConfig;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.LogView;
import cc.winboll.studio.libappbase.R;
import cc.winboll.studio.libappbase.models.UserInfoModel;
import cc.winboll.studio.libappbase.utils.RSAUtils;
import cc.winboll.studio.libappbase.utils.YunUtils;
import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity;
import cc.winboll.studio.winboll.R;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import cc.winboll.studio.winboll.utils.YunUtils;
import cc.winboll.studio.winboll.models.UserInfoModel;
import cc.winboll.studio.winboll.utils.RSAUtils;
import cc.winboll.studio.libaes.winboll.IWinBoLLActivity;
/**
* @Author ZhanGSKen<zhangsken@qq.com>

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.appbase.activities;
package cc.winboll.studio.winboll.activities;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
@@ -11,9 +11,10 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toolbar;
import cc.winboll.studio.appbase.R;
import cc.winboll.studio.winboll.R;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity;
import cc.winboll.studio.libaes.winboll.IWinBoLLActivity;
import cc.winboll.studio.libaes.winboll.WinBoLLActivityManager;
public class New2Activity extends WinBoLLActivity implements IWinBoLLActivity {
@@ -51,15 +52,15 @@ public class New2Activity extends WinBoLLActivity implements IWinBoLLActivity {
}
public void onCloseThisActivity(View view) {
GlobalApplication.getWinBoLLActivityManager().finish(this);
WinBoLLActivityManager.getInstance().finish(this);
}
public void onCloseAllActivity(View view) {
GlobalApplication.getWinBoLLActivityManager().finishAll();
WinBoLLActivityManager.getInstance().finishAll();
}
public void onNewActivity(View view) {
GlobalApplication.getWinBoLLActivityManager().startWinBoLLActivity(this, NewActivity.class);
WinBoLLActivityManager.getInstance().startWinBoLLActivity(this, NewActivity.class);
}

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.appbase.activities;
package cc.winboll.studio.winboll.activities;
/**
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
@@ -11,9 +11,10 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toolbar;
import cc.winboll.studio.appbase.R;
import cc.winboll.studio.winboll.R;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity;
import cc.winboll.studio.libaes.winboll.WinBoLLActivityManager;
import cc.winboll.studio.libaes.winboll.IWinBoLLActivity;
public class NewActivity extends WinBoLLActivity implements IWinBoLLActivity {
@@ -50,15 +51,15 @@ public class NewActivity extends WinBoLLActivity implements IWinBoLLActivity {
}
public void onCloseThisActivity(View view) {
GlobalApplication.getWinBoLLActivityManager().finish(this);
WinBoLLActivityManager.getInstance().finish(this);
}
public void onCloseAllActivity(View view) {
GlobalApplication.getWinBoLLActivityManager().finishAll();
WinBoLLActivityManager.getInstance().finishAll();
}
public void onNew2Activity(View view) {
GlobalApplication.getWinBoLLActivityManager().startWinBoLLActivity(this, New2Activity.class);
WinBoLLActivityManager.getInstance().startWinBoLLActivity(this, New2Activity.class);
}

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.appbase.activities;
package cc.winboll.studio.winboll.activities;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
@@ -6,13 +6,15 @@ package cc.winboll.studio.appbase.activities;
* @Describe WinBoLL 窗口基础类
*/
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.MenuItem;
import cc.winboll.studio.appbase.MainActivity;
import cc.winboll.studio.appbase.R;
import cc.winboll.studio.libaes.winboll.IWinBoLLActivity;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity;
import cc.winboll.studio.winboll.MainActivity;
import cc.winboll.studio.winboll.R;
import cc.winboll.studio.libaes.winboll.WinBoLLActivityManager;
public class WinBoLLActivity extends Activity implements IWinBoLLActivity {
@@ -37,10 +39,10 @@ public class WinBoLLActivity extends Activity implements IWinBoLLActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.item_log) {
GlobalApplication.getWinBoLLActivityManager().startLogActivity(this);
WinBoLLActivityManager.getInstance().startLogActivity(this);
return true;
} else if (item.getItemId() == R.id.item_home) {
GlobalApplication.getWinBoLLActivityManager().startWinBoLLActivity(getApplicationContext(), MainActivity.class);
startActivity(new Intent(this, MainActivity.class));
return true;
}
// 在switch语句中处理每个ID并在处理完后返回true未处理的情况返回false。
@@ -50,12 +52,12 @@ public class WinBoLLActivity extends Activity implements IWinBoLLActivity {
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
GlobalApplication.getWinBoLLActivityManager().add(this);
WinBoLLActivityManager.getInstance().add(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
GlobalApplication.getWinBoLLActivityManager().registeRemove(this);
WinBoLLActivityManager.getInstance().registeRemove(this);
}
}

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.appbase;
package cc.winboll.studio.winboll.activities;
import android.app.Activity;
import android.content.ComponentName;
@@ -9,12 +9,19 @@ import android.view.MenuItem;
import android.view.View;
import android.widget.CheckBox;
import android.widget.Toolbar;
import cc.winboll.studio.appbase.R;
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.utils.ToastUtils;
import cc.winboll.studio.winboll.App;
import cc.winboll.studio.winboll.R;
import cc.winboll.studio.winboll.services.MainService;
import cc.winboll.studio.winboll.services.TestDemoBindService;
import cc.winboll.studio.winboll.services.TestDemoService;
import cc.winboll.studio.winboll.sos.SOS;
import cc.winboll.studio.winboll.widgets.StatusWidget;
import cc.winboll.studio.libaes.winboll.WinBoLLActivityManager;
public class WinBoLLUnitTestActivity extends Activity {
@@ -44,9 +51,9 @@ public class WinBoLLUnitTestActivity extends Activity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.item_yun) {
GlobalApplication.getWinBoLLActivityManager().startWinBoLLActivity(this, cc.winboll.studio.libappbase.activities.YunActivity.class);
WinBoLLActivityManager.getInstance().startWinBoLLActivity(this, cc.winboll.studio.libappbase.activities.YunActivity.class);
} else if(item.getItemId() == R.id.item_logon) {
GlobalApplication.getWinBoLLActivityManager().startWinBoLLActivity(this, cc.winboll.studio.libappbase.activities.LogonActivity.class);
WinBoLLActivityManager.getInstance().startWinBoLLActivity(this, cc.winboll.studio.libappbase.activities.LogonActivity.class);
}
// 在switch语句中处理每个ID并在处理完后返回true未处理的情况返回false。
return super.onOptionsItemSelected(item);
@@ -63,7 +70,7 @@ public class WinBoLLUnitTestActivity extends Activity {
public void onSwitchDebugMode(View view) {
boolean isDebuging = ((CheckBox)view).isChecked();
GlobalApplication.setIsDebuging(isDebuging);
GlobalApplication.saveDebugStatus();
GlobalApplication.saveDebugStatus(this);
}
public void onPreviewGlobalCrashActivity(View view) {
@@ -152,7 +159,7 @@ public class WinBoLLUnitTestActivity extends Activity {
}
public void onTestOpenNewActivity(View view) {
GlobalApplication.getWinBoLLActivityManager().startWinBoLLActivity(this, NewActivity.class);
WinBoLLActivityManager.getInstance().startWinBoLLActivity(this, NewActivity.class);
}
@Override

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.libappbase.activities;
package cc.winboll.studio.winboll.activities;
import android.app.Activity;
import android.os.Bundle;

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.appbase.handlers;
package cc.winboll.studio.winboll.handlers;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
@@ -6,8 +6,8 @@ package cc.winboll.studio.appbase.handlers;
*/
import android.os.Handler;
import android.os.Message;
import cc.winboll.studio.appbase.services.MainService;
import java.lang.ref.WeakReference;
import cc.winboll.studio.winboll.services.MainService;
public class MainServiceHandler extends Handler {
public static final String TAG = "MainServiceHandler";

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.appbase.models;
package cc.winboll.studio.winboll.models;
/**
* @Author ZhanGSKen<zhangsken@qq.com>

View File

@@ -0,0 +1,53 @@
package cc.winboll.studio.winboll.models;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
* @Date 2025/06/05 11:26
*/
public class ResponseData {
public static final String STATUS_SUCCESS = "success";
public static final String STATUS_ERROR = "error";
private String status;
private String message;
private UserInfoModel data;
public ResponseData() {
this.status = "";
this.message = "";
this.data = new UserInfoModel();
}
public ResponseData(String status, String message, UserInfoModel data) {
this.status = status;
this.message = message;
this.data = data;
}
public void setStatus(String status) {
this.status = status;
}
public String getStatus() {
return status;
}
public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setData(UserInfoModel data) {
this.data = data;
}
public UserInfoModel getData() {
return data;
}
}

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.appbase.models;
package cc.winboll.studio.winboll.models;
/**
* @Author ZhanGSKen<zhangsken@qq.com>

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.appbase.models;
package cc.winboll.studio.winboll.models;
/**
* @Author ZhanGSKen<zhangsken@qq.com>

View File

@@ -0,0 +1,92 @@
package cc.winboll.studio.winboll.models;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
* @Date 2025/06/04 19:14
*/
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException;
public class UserInfoModel extends BaseBean {
public static final String TAG = "UserInfoModel";
String username;
String password;
String token;
public UserInfoModel() {
this.username = "";
this.password = "";
this.token = "";
}
public void setUsername(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
public void setPassword(String password) {
this.password = password;
}
public String getPassword() {
return password;
}
public void setToken(String token) {
this.token = token;
}
public String getToken() {
return token;
}
@Override
public String getName() {
return UserInfoModel.class.getName();
}
@Override
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
super.writeThisToJsonWriter(jsonWriter);
jsonWriter.name("username").value(getUsername());
jsonWriter.name("password").value(getPassword());
jsonWriter.name("token").value(getToken());
}
@Override
public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
if (name.equals("username")) {
setUsername(jsonReader.nextString());
} else if (name.equals("password")) {
setPassword(jsonReader.nextString());
} else if (name.equals("token")) {
setToken(jsonReader.nextString());
} 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;
}
}

View File

@@ -0,0 +1,92 @@
package cc.winboll.studio.winboll.models;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
* @Date 2025/05/10 10:16
* @Describe WinBoLLModel
*/
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException;
import cc.winboll.studio.libappbase.APPModel;
public class WinBoLLModel extends BaseBean {
public static final String TAG = "WinBoLLModel";
String appPackageName;
String appMainServiveName;
public WinBoLLModel() {
this.appPackageName = "";
this.appMainServiveName = "";
}
public WinBoLLModel(boolean isDebuging, String appPackageName, String appMainServiveName) {
this.appPackageName = appPackageName;
this.appMainServiveName = appMainServiveName;
}
public WinBoLLModel(String appPackageName, String appMainServiveName) {
this.appPackageName = appPackageName;
this.appMainServiveName = appMainServiveName;
}
public void setAppPackageName(String appPackageName) {
this.appPackageName = appPackageName;
}
public String getAppPackageName() {
return appPackageName;
}
public void setAppMainServiveName(String appMainServiveName) {
this.appMainServiveName = appMainServiveName;
}
public String getAppMainServiveName() {
return appMainServiveName;
}
@Override
public String getName() {
return APPModel.class.getName();
}
@Override
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
super.writeThisToJsonWriter(jsonWriter);
jsonWriter.name("appPackageName").value(getAppPackageName());
jsonWriter.name("appMainServiveName").value(getAppMainServiveName());
}
@Override
public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
if (name.equals("appPackageName")) {
setAppPackageName(jsonReader.nextString());
} else if (name.equals("appMainServiveName")) {
setAppMainServiveName(jsonReader.nextString());
} 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;
}
}

View File

@@ -1,14 +1,15 @@
package cc.winboll.studio.libappbase.models;
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException;
package cc.winboll.studio.winboll.models;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
* @Date 2025/05/10 09:36
* @Describe WinBoLL 应用消息数据模型
*/
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException;
public class WinBoLLNewsBean extends BaseBean {
public static final String TAG = "WinBoLLNewsBean";

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.appbase.receivers;
package cc.winboll.studio.winboll.receivers;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
@@ -7,8 +7,8 @@ package cc.winboll.studio.appbase.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import cc.winboll.studio.appbase.widgets.APPNewsWidget;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.winboll.widgets.APPNewsWidget;
public class APPNewsWidgetClickListener extends BroadcastReceiver {

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.appbase.receivers;
package cc.winboll.studio.winboll.receivers;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
@@ -10,14 +10,17 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import cc.winboll.studio.appbase.services.MainService;
import cc.winboll.studio.appbase.widgets.APPNewsWidget;
import cc.winboll.studio.libaes.winboll.IWinBoLLActivity;
import cc.winboll.studio.libaes.winboll.WinBoLL;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.models.WinBoLLModel;
import cc.winboll.studio.libappbase.models.WinBoLLNewsBean;
import cc.winboll.studio.libappbase.sos.SOS;
import cc.winboll.studio.libappbase.sos.SOSObject;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import cc.winboll.studio.libappbase.ToastUtils;
import cc.winboll.studio.libapputils.utils.AppUtils;
import cc.winboll.studio.winboll.models.WinBoLLModel;
import cc.winboll.studio.winboll.models.WinBoLLNewsBean;
import cc.winboll.studio.winboll.services.MainService;
import cc.winboll.studio.winboll.sos.SOS;
import cc.winboll.studio.winboll.sos.SOSObject;
import cc.winboll.studio.winboll.widgets.APPNewsWidget;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.appbase.services;
package cc.winboll.studio.winboll.services;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
@@ -11,11 +11,9 @@ import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import cc.winboll.studio.appbase.models.MainServiceBean;
import cc.winboll.studio.appbase.services.AssistantService;
import cc.winboll.studio.appbase.services.MainService;
import cc.winboll.studio.libappbase.LogUtils;
import android.os.Binder;
import cc.winboll.studio.winboll.models.MainServiceBean;
public class AssistantService extends Service {

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.appbase.services;
package cc.winboll.studio.winboll.services;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
@@ -17,16 +17,15 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import cc.winboll.studio.appbase.MyTileService;
import cc.winboll.studio.appbase.handlers.MainServiceHandler;
import cc.winboll.studio.appbase.models.MainServiceBean;
import cc.winboll.studio.appbase.receivers.MainReceiver;
import cc.winboll.studio.appbase.services.AssistantService;
import cc.winboll.studio.appbase.threads.MainServiceThread;
import cc.winboll.studio.appbase.widgets.APPNewsWidget;
import cc.winboll.studio.libaes.models.WinBoLLModel;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.models.APPModel;
import cc.winboll.studio.libappbase.models.WinBoLLModel;
import cc.winboll.studio.winboll.MyTileService;
import cc.winboll.studio.winboll.handlers.MainServiceHandler;
import cc.winboll.studio.winboll.models.MainServiceBean;
import cc.winboll.studio.winboll.receivers.MainReceiver;
import cc.winboll.studio.winboll.services.AssistantService;
import cc.winboll.studio.winboll.threads.MainServiceThread;
import cc.winboll.studio.winboll.widgets.APPNewsWidget;
import java.util.ArrayList;
public class MainService extends Service {

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.appbase.services;
package cc.winboll.studio.winboll.services;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
@@ -10,12 +10,12 @@ import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import cc.winboll.studio.appbase.App;
import cc.winboll.studio.appbase.models.TestDemoBindServiceBean;
import cc.winboll.studio.appbase.services.TestDemoBindService;
import cc.winboll.studio.libaes.winboll.WinBoLL;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.sos.SOS;
import cc.winboll.studio.libappbase.winboll.WinBoLL;
import cc.winboll.studio.winboll.App;
import cc.winboll.studio.winboll.models.TestDemoBindServiceBean;
import cc.winboll.studio.winboll.services.TestDemoBindService;
import cc.winboll.studio.winboll.sos.SOS;
public class TestDemoBindService extends Service {

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.appbase.services;
package cc.winboll.studio.winboll.services;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
@@ -10,8 +10,9 @@ import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import cc.winboll.studio.appbase.models.TestDemoServiceBean;
import cc.winboll.studio.winboll.models.TestDemoServiceBean;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.winboll.models.TestDemoServiceBean;
public class TestDemoService extends Service {

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.libappbase.sos;
package cc.winboll.studio.winboll.sos;
/**
* @Author ZhanGSKen<zhangsken@qq.com>

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.libappbase.sos;
package cc.winboll.studio.winboll.sos;
/**
* @Author ZhanGSKen<zhangsken@qq.com>

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.libappbase.sos;
package cc.winboll.studio.winboll.sos;
/**
* @Author ZhanGSKen<zhangsken@qq.com>

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.libappbase.sos;
package cc.winboll.studio.winboll.sos;
/**
* @Author ZhanGSKen<zhangsken@qq.com>

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.libappbase.sos;
package cc.winboll.studio.winboll.sos;
/**
* @Author ZhanGSKen<zhangsken@qq.com>

View File

@@ -1,11 +1,11 @@
package cc.winboll.studio.appbase.threads;
package cc.winboll.studio.winboll.threads;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
* @Date 2025/02/14 03:46:44
*/
import android.content.Context;
import cc.winboll.studio.appbase.handlers.MainServiceHandler;
import cc.winboll.studio.winboll.handlers.MainServiceHandler;
import cc.winboll.studio.libappbase.LogUtils;
import java.lang.ref.WeakReference;

View File

@@ -0,0 +1,222 @@
package cc.winboll.studio.winboll.utils;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
* @Date 2025/06/04 13:36
* @Describe RSA加密工具
*/
import android.content.Context;
import android.util.Base64;
import cc.winboll.studio.libappbase.LogUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;
import javax.crypto.Cipher;
public class RSAUtils {
private static final String TAG = "RSAUtils";
private static final int KEY_SIZE = 2048;
private static final String KEY_ALGORITHM = "RSA";
private static final String PUBLIC_KEY_FILE = "public.key";
private static final String PRIVATE_KEY_FILE = "private.key";
private static final String CIPHER_ALGORITHM = KEY_ALGORITHM + "/ECB/PKCS1Padding"; // 保留原加密方式
private final String keyPath;
private static volatile RSAUtils INSTANCE;
/**
* 构造方法:初始化密钥存储路径(内部存储)
*/
private RSAUtils(Context context) {
keyPath = context.getFilesDir() + File.separator + "keys" + File.separator; // 修正路径格式
}
/**
* 获取单例实例
*/
public static synchronized RSAUtils getInstance(Context context) {
if (INSTANCE == null) {
INSTANCE = new RSAUtils(context);
}
return INSTANCE;
}
/**
* 检查密钥文件是否存在
*/
public boolean keysExist() {
File publicKeyFile = new File(keyPath + PUBLIC_KEY_FILE);
File privateKeyFile = new File(keyPath + PRIVATE_KEY_FILE);
return publicKeyFile.exists() && privateKeyFile.exists();
}
/**
* 生成密钥对并保存到文件
*/
public void generateAndSaveKeys() throws Exception {
LogUtils.d(TAG, "开始生成 RSA 密钥对2048位");
KeyPairGenerator generator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
generator.initialize(KEY_SIZE);
KeyPair keyPair = generator.generateKeyPair();
saveKey(PUBLIC_KEY_FILE, keyPair.getPublic().getEncoded());
saveKey(PRIVATE_KEY_FILE, keyPair.getPrivate().getEncoded());
LogUtils.d(TAG, "密钥对生成并保存成功");
}
/**
* 获取或生成密钥对(线程安全)
*/
public KeyPair getOrGenerateKeys() throws Exception {
if (!keysExist()) {
synchronized (RSAUtils.class) { // 双重检查锁,避免多线程重复生成
if (!keysExist()) {
generateAndSaveKeys();
}
}
}
return readKeysFromFile();
}
/**
* 从文件读取密钥对
*/
private KeyPair readKeysFromFile() throws Exception {
LogUtils.d(TAG, "读取密钥对文件");
try {
byte[] publicKeyBytes = readFileToBytes(keyPath + PUBLIC_KEY_FILE);
byte[] privateKeyBytes = readFileToBytes(keyPath + PRIVATE_KEY_FILE);
X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(publicKeyBytes);
PKCS8EncodedKeySpec privateSpec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey publicKey = factory.generatePublic(publicSpec);
PrivateKey privateKey = factory.generatePrivate(privateSpec);
return new KeyPair(publicKey, privateKey);
} catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException e) {
LogUtils.e(TAG, "密钥文件读取失败:" + e.getMessage());
throw new Exception("密钥文件损坏或格式错误", e);
}
}
/**
* 保存密钥到文件(通用方法)
*/
private void saveKey(String fileName, byte[] keyBytes) throws IOException {
Objects.requireNonNull(keyBytes, "密钥字节数据不可为空");
File dir = new File(keyPath);
if (!dir.exists() && !dir.mkdirs()) {
throw new IOException("创建密钥目录失败:" + keyPath);
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(keyPath + fileName);
fos.write(keyBytes);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
LogUtils.e(TAG, "关闭文件流失败:" + e.getMessage());
}
}
}
}
/**
* 读取文件为字节数组Java 7 兼容)
*/
private byte[] readFileToBytes(String filePath) throws IOException {
File file = new File(filePath);
if (!file.exists() || file.isDirectory()) {
throw new IOException("文件不存在或为目录:" + filePath);
}
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
byte[] data = new byte[(int) file.length()];
int bytesRead = fis.read(data);
if (bytesRead != data.length) {
throw new IOException("文件读取不完整");
}
return data;
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
LogUtils.e(TAG, "关闭文件流失败:" + e.getMessage());
}
}
}
}
/**
* 公钥加密(带参数校验)
*/
public byte[] encryptWithPublicKey(String plainText, PublicKey publicKey) throws Exception {
Objects.requireNonNull(plainText, "明文不可为空");
Objects.requireNonNull(publicKey, "公钥不可为空");
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 检查数据长度是否超过 RSA 限制2048位密钥最大明文为 214字节PKCS1Padding
int maxPlainTextSize = cipher.getBlockSize() - 11; // PKCS1Padding 固定填充长度
if (plainText.getBytes("UTF-8").length > maxPlainTextSize) {
throw new IllegalArgumentException("明文过长,最大支持 " + maxPlainTextSize + " 字节");
}
return cipher.doFinal(plainText.getBytes("UTF-8"));
}
/**
* 私钥解密(带参数校验)
*/
public String decryptWithPrivateKey(byte[] encryptedData, PrivateKey privateKey) throws Exception {
Objects.requireNonNull(encryptedData, "密文不可为空");
Objects.requireNonNull(privateKey, "私钥不可为空");
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedBytes = cipher.doFinal(encryptedData);
return new String(decryptedBytes, "UTF-8");
}
/**
* 将 HTTP 传输的 Base64 字符串还原为加密字节数组Java 7 兼容)
* @param httpString Base64 字符串(非 null
* @return 加密字节数组
* @throws IllegalArgumentException 解码失败时抛出
*/
public byte[] httpStringToEncryptBytes(String httpString) {
Objects.requireNonNull(httpString, "HTTP 字符串不可为空");
// 计算缺失的填充符数量Java 7 不支持 repeat(),手动拼接)
int pad = httpString.length() % 4;
StringBuilder paddedString = new StringBuilder(httpString);
if (pad != 0) {
for (int i = 0; i < pad; i++) {
paddedString.append('='); // 补全 '='
}
}
// 使用 Base64 解码Android 原生 Base64 类兼容 Java 7
return Base64.decode(paddedString.toString(), Base64.URL_SAFE);
}
}

View File

@@ -5,13 +5,15 @@ package cc.winboll.studio.winboll.utils;
* @Date 2025/06/08 09:05
* @Describe Termux 应用操作工具集
*/
import android.content.Intent;
public abstract class TermuxUtils {
public static final String TAG = "TermuxUtils";
private void runTermuxCommand(String command) {
// 1. 创建 Intent指定 Termux 的 RunCommandService
Intent intent = new Intent("com.termux.RUN_COMMAND");
/*Intent intent = new Intent("com.termux.RUN_COMMAND");
intent.setPackage("com.termux"); // Termux 应用的包名
// 2. 传递命令参数(必填)
@@ -26,6 +28,6 @@ public abstract class TermuxUtils {
getApplicationContext().startService(intent);
} catch (Exception e) {
e.printStackTrace();
}
}*/
}
}

View File

@@ -0,0 +1,282 @@
package cc.winboll.studio.winboll.utils;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
* @Date 2025/06/04 17:21
* @Describe 应用登录与接口工具
*/
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import cc.winboll.studio.libappbase.LogUtils;
import com.google.gson.Gson;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
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 cc.winboll.studio.winboll.models.UserInfoModel;
import cc.winboll.studio.winboll.models.ResponseData;
import cc.winboll.studio.libapputils.utils.FileUtils;
public class YunUtils {
public static final String TAG = "YunUtils";
// 私有静态实例,类加载时创建
private static volatile YunUtils INSTANCE;
Context mContext;
UserInfoModel mUserInfoModel;
String token = "";
String mDataFolderPath = "";
String mUserInfoModelPath = "";
private static final int CONNECT_TIMEOUT = 15; // 连接超时时间(秒)
private static final int READ_TIMEOUT = 20; // 读取超时时间(秒)
private static volatile YunUtils instance;
private OkHttpClient okHttpClient;
private Handler mainHandler; // 主线程 Handler
// 私有构造方法,防止外部实例化
private YunUtils(Context context) {
LogUtils.d(TAG, "YunUtils");
mContext = context;
mDataFolderPath = mContext.getExternalFilesDir(TAG).toString();
File fTest = new File(mDataFolderPath);
if (!fTest.exists()) {
fTest.mkdirs();
}
mUserInfoModelPath = mDataFolderPath + File.separator + "UserInfoModel.rsajson";
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
.build();
mainHandler = new Handler(Looper.getMainLooper()); // 获取主线程 Looper
}
// 公共静态方法,返回唯一实例
public static synchronized YunUtils getInstance(Context context) {
LogUtils.d(TAG, "getInstance");
if (INSTANCE == null) {
INSTANCE = new YunUtils(context);
}
return INSTANCE;
}
public void checkLoginStatus() {
String token = getLocalToken();
LogUtils.d(TAG, String.format("checkLoginStatus token is %s", token));
}
String getLocalToken() {
UserInfoModel userInfoModel = loadUserInfoModel();
return (userInfoModel == null) ?"": userInfoModel.getToken();
}
public void login(String host, UserInfoModel userInfoModel) {
LogUtils.d(TAG, "login");
// 发送 POST 请求
String apiUrl = host + "/login/index.php";
// 序列化对象为JSON
Gson gson = new Gson();
String jsonData = gson.toJson(userInfoModel); // 自动生成标准JSON
//String jsonData = userInfoModel.toString();
LogUtils.d(TAG, "要发送的数据 : " + jsonData);
sendPostRequest(apiUrl, jsonData, new OnResponseListener() {
// 成功回调(主线程)
@Override
public void onSuccess(String responseBody) {
LogUtils.d(TAG, "onSuccess");
LogUtils.d(TAG, String.format("responseBody %s", responseBody));
Gson gson = new Gson();
ResponseData result = gson.fromJson(responseBody, ResponseData.class); // 转为 Result 实例
if(result.getStatus().equals(ResponseData.STATUS_SUCCESS)) {
UserInfoModel userInfoModel = result.getData();
if (userInfoModel != null) {
LogUtils.d(TAG, "收到网站 UserInfoModel");
String token = userInfoModel.getToken();
saveLocalToken(token);
checkLoginStatus();
}
} else if(result.getStatus().equals(ResponseData.STATUS_ERROR)) {
try {
String decodedMessage = URLDecoder.decode(result.getMessage(), "UTF-8");
LogUtils.d(TAG, "服务器返回信息: " + decodedMessage);
} catch (UnsupportedEncodingException e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
}
}
// 失败回调(主线程)
@Override
public void onFailure(String errorMsg) {
LogUtils.d(TAG, errorMsg);
// 处理错误
}
});
}
public void saveLocalToken(String token) {
UserInfoModel userInfoModel = new UserInfoModel();
userInfoModel.setToken(token);
saveUserInfoModel(userInfoModel);
}
UserInfoModel loadUserInfoModel() {
LogUtils.d(TAG, "loadUserInfoModel");
if (new File(mUserInfoModelPath).exists()) {
try {
// 加载加密后的模型数据
byte[] encryptedData = FileUtils.readByteArrayFromFile(mUserInfoModelPath);
// 加载 RSA 工具
RSAUtils utils = RSAUtils.getInstance(mContext);
KeyPair keyPair = utils.getOrGenerateKeys();
//PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 私钥解密模型数据
String szInfo = utils.decryptWithPrivateKey(encryptedData, keyPair.getPrivate());
LogUtils.d(TAG, String.format("szInfo %s", szInfo));
mUserInfoModel = UserInfoModel.parseStringToBean(szInfo, UserInfoModel.class);
if (mUserInfoModel == null) {
LogUtils.d(TAG, "模型数据解析为空数据。");
}
LogUtils.d(TAG, "UserInfoModel 解密加载结束。");
} catch (Exception e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
} else {
LogUtils.d(TAG, "云服务登录信息不存在。");
mUserInfoModel = null;
}
return mUserInfoModel;
}
void saveUserInfoModel(UserInfoModel userInfoModel) {
LogUtils.d(TAG, "saveUserInfoModel");
try {
String szInfo = userInfoModel.toString();
LogUtils.d(TAG, "原始数据: " + szInfo);
RSAUtils utils = RSAUtils.getInstance(mContext);
KeyPair keyPair = utils.getOrGenerateKeys();
PublicKey publicKey = keyPair.getPublic();
// 公钥加密(传入字节数组,避免中间字符串转换)
byte[] encryptedData = utils.encryptWithPublicKey(szInfo, publicKey);
// 保存加密字节数组到文件(直接操作字节,无需转字符串)
FileUtils.writeByteArrayToFile(encryptedData, mUserInfoModelPath);
LogUtils.d(TAG, "加密数据已保存");
// 测试解密(仅调试用)
String szInfo2 = utils.decryptWithPrivateKey(encryptedData, keyPair.getPrivate());
LogUtils.d(TAG, "解密结果: " + szInfo2);
mUserInfoModel = UserInfoModel.parseStringToBean(szInfo2, UserInfoModel.class);
if (mUserInfoModel == null) {
LogUtils.d(TAG, "模型解析失败");
}
} catch (Exception e) {
LogUtils.d(TAG, "加密/解密失败: " + e.getMessage());
}
}
// 发送 POST 请求JSON 数据)
public void sendPostRequest(String url, String data, OnResponseListener listener) {
RequestBody requestBody = RequestBody.create(
MediaType.parse("application/json; charset=utf-8"), // 关键头信息
data.getBytes(StandardCharsets.UTF_8)
);
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.addHeader("Content-Type", "application/json") // 显式添加头
.build();
executeRequest(request, listener);
}
// 发送 GET 请求
public void sendGetRequest(String url, OnResponseListener listener) {
Request request = new Request.Builder()
.url(url)
.get()
.build();
executeRequest(request, listener);
}
// 执行请求(子线程处理)
private void executeRequest(final Request request, final OnResponseListener listener) {
okHttpClient.newCall(request).enqueue(new Callback() {
// 响应成功(子线程)
@Override
public void onResponse(Call call, Response response) throws IOException {
try {
if (!response.isSuccessful()) {
postFailure(listener, "响应码错误:" + response.code());
return;
}
String responseBody = response.body().string();
postSuccess(listener, responseBody);
} catch (Exception e) {
postFailure(listener, "解析失败:" + e.getMessage());
}
}
// 响应失败(子线程)
@Override
public void onFailure(Call call, IOException e) {
postFailure(listener, "网络失败:" + e.getMessage());
}
// 主线程回调(使用 Handler
private void postSuccess(final OnResponseListener listener, final String msg) {
mainHandler.post(new Runnable() {
@Override
public void run() {
listener.onSuccess(msg);
}
});
}
private void postFailure(final OnResponseListener listener, final String msg) {
mainHandler.post(new Runnable() {
@Override
public void run() {
listener.onFailure(msg);
}
});
}
});
}
public interface OnResponseListener {
/**
* 成功响应(主线程回调)
* @param responseBody 响应体字符串
*/
void onSuccess(String responseBody);
/**
* 失败回调(包含错误信息)
* @param errorMsg 错误描述
*/
void onFailure(String errorMsg);
}
}

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.appbase.widgets;
package cc.winboll.studio.winboll.widgets;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
* @Date 2025/02/15 14:41:25
@@ -11,18 +11,17 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;
import cc.winboll.studio.appbase.R;
import cc.winboll.studio.appbase.receivers.APPNewsWidgetClickListener;
import cc.winboll.studio.libappbase.AppUtils;
import cc.winboll.studio.libaes.models.WinBoLLModel;
import cc.winboll.studio.libaes.winboll.WinBoLL;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.models.APPModel;
import cc.winboll.studio.libappbase.models.WinBoLLNewsBean;
import cc.winboll.studio.libappbase.winboll.WinBoLL;
import cc.winboll.studio.libapputils.utils.AppUtils;
import cc.winboll.studio.winboll.R;
import cc.winboll.studio.winboll.models.WinBoLLNewsBean;
import cc.winboll.studio.winboll.receivers.APPNewsWidgetClickListener;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import cc.winboll.studio.libappbase.models.WinBoLLModel;
public class APPNewsWidget extends AppWidgetProvider {

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.appbase.widgets;
package cc.winboll.studio.winboll.widgets;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
@@ -11,12 +11,8 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.R;
import cc.winboll.studio.libappbase.utils.ServiceUtils;
import android.content.ServiceConnection;
import android.os.IBinder;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import cc.winboll.studio.winboll.R;
import cc.winboll.studio.libappbase.ToastUtils;
public class StatusWidget extends AppWidgetProvider {

View File

@@ -1,4 +1,4 @@
package cc.winboll.studio.libappbase.widgets;
package cc.winboll.studio.winboll.widgets;
/**
* @Author ZhanGSKen<zhangsken@qq.com>
@@ -9,7 +9,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import cc.winboll.studio.libappbase.ToastUtils;
public class StatusWidgetClickListener extends BroadcastReceiver {

View File

@@ -0,0 +1,11 @@
<?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.5,20Q4.22,20 2.61,18.43 1,16.85 1,14.58 1,12.63 2.17,11.1 3.35,9.57 5.25,9.15 5.88,6.85 7.75,5.43 9.63,4 12,4 14.93,4 16.96,6.04 19,8.07 19,11 20.73,11.2 21.86,12.5 23,13.78 23,15.5 23,17.38 21.69,18.69 20.38,20 18.5,20Z"/>
</vector>

View File

@@ -0,0 +1,11 @@
<?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.5,20Q4.22,20 2.61,18.43 1,16.85 1,14.58 1,12.63 2.17,11.1 3.35,9.57 5.25,9.15 5.88,6.85 7.75,5.43 9.63,4 12,4 14.93,4 16.96,6.04 19,8.07 19,11 20.73,11.2 21.86,12.5 23,13.78 23,15.5 23,17.38 21.69,18.69 20.38,20 18.5,20M6.5,18H18.5Q19.55,18 20.27,17.27 21,16.55 21,15.5 21,14.45 20.27,13.73 19.55,13 18.5,13H17V11Q17,8.93 15.54,7.46 14.08,6 12,6 9.93,6 8.46,7.46 7,8.93 7,11H6.5Q5.05,11 4.03,12.03 3,13.05 3,14.5 3,15.95 4.03,17 5.05,18 6.5,18M12,12Z"/>
</vector>