Compare commits
31 Commits
appbase-v1
...
appbase-v2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51acbb1f54 | ||
|
|
26fc0b4684 | ||
|
|
ecb67edec1 | ||
|
|
3b30acfdec | ||
|
|
c633e1663b | ||
|
|
40589ad879 | ||
|
|
0357fcf6b3 | ||
|
|
c56fdaf14d | ||
|
|
9b1264234e | ||
|
|
d207a9ea9b | ||
|
|
404239de23 | ||
|
|
c16b80ffae | ||
|
|
ca16a8677a | ||
|
|
bb089a4eb1 | ||
|
|
0c00ace869 | ||
|
|
e06b642b70 | ||
|
|
5e107028de | ||
|
|
3bcfc5a5da | ||
|
|
e849e54960 | ||
|
|
8b2866419c | ||
|
|
22a4a71203 | ||
|
|
292f7c553f | ||
|
|
df9970c6df | ||
|
|
0312ca50d2 | ||
|
|
56187b588f | ||
|
|
d91372af52 | ||
|
|
288725eca0 | ||
|
|
bd728b83a3 | ||
|
|
d4f9fc3561 | ||
|
|
e7c614ebec | ||
|
|
c226a92ffe |
@@ -18,18 +18,18 @@ def genVersionName(def versionName){
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 32
|
||||
buildToolsVersion "33.0.3"
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion "30.0.3"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "cc.winboll.studio.appbase"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
// versionName 更新后需要手动设置
|
||||
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
|
||||
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
|
||||
versionName "1.5"
|
||||
versionName "2.0"
|
||||
if(true) {
|
||||
versionName = genVersionName("${versionName}")
|
||||
}
|
||||
@@ -41,11 +41,6 @@ android {
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Mon Feb 17 12:09:50 HKT 2025
|
||||
#Tue Feb 25 16:51:09 HKT 2025
|
||||
stageCount=3
|
||||
libraryProject=libappbase
|
||||
baseVersion=1.5
|
||||
publishVersion=1.5.2
|
||||
baseVersion=2.0
|
||||
publishVersion=2.0.2
|
||||
buildCount=0
|
||||
baseBetaVersion=1.5.3
|
||||
baseBetaVersion=2.0.3
|
||||
|
||||
@@ -54,8 +54,34 @@
|
||||
<receiver android:name="cc.winboll.studio.appbase.receivers.MainReceiver">
|
||||
|
||||
<intent-filter>
|
||||
|
||||
<action android:name="cc.winboll.studio.appbase.receivers.MainReceiver"/>
|
||||
</intent-filter>
|
||||
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.SOSWidget"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="cc.winboll.studio.appbase.widgets.SOSWidget.ACTION_WAKEUP_SERVICE"/>
|
||||
<action android:name="cc.winboll.studio.appbase.widgets.SOSWidget.ACTION_RELOAD_REPORT"/>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_provider_info_sos"/>
|
||||
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".widgets.SOSWidgetClickListener">
|
||||
|
||||
<intent-filter>
|
||||
|
||||
<action android:name="cc.winboll.studio.appbase.widgets.SOSWidgetClickListener.ACTION_PRE"/>
|
||||
|
||||
<action android:name="cc.winboll.studio.appbase.widgets.SOSWidgetClickListener.ACTION_NEXT"/>
|
||||
|
||||
</intent-filter>
|
||||
|
||||
@@ -65,8 +91,6 @@
|
||||
android:name="android.max_aspect"
|
||||
android:value="4.0"/>
|
||||
|
||||
<service android:name="cc.winboll.studio.appbase.services.TestService"
|
||||
android:exported="true"/>
|
||||
|
||||
</application>
|
||||
|
||||
|
||||
@@ -9,15 +9,15 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import cc.winboll.studio.appbase.R;
|
||||
import cc.winboll.studio.appbase.services.MainService;
|
||||
import cc.winboll.studio.appbase.services.TestService;
|
||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.LogView;
|
||||
import cc.winboll.studio.libappbase.SOS;
|
||||
import cc.winboll.studio.libappbase.SimpleOperateSignalCenterService;
|
||||
import cc.winboll.studio.libappbase.widgets.APPSOSReportWidget;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import cc.winboll.studio.libappbase.bean.APPSOSBean;
|
||||
import cc.winboll.studio.libappbase.services.TestService;
|
||||
import cc.winboll.studio.libappbase.widgets.StatusWidget;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
@@ -41,6 +41,14 @@ public class MainActivity extends AppCompatActivity {
|
||||
if (GlobalApplication.isDebuging()) { mLogView.start(); }
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
Intent intentAPPWidget = new Intent(this, StatusWidget.class);
|
||||
intentAPPWidget.setAction(StatusWidget.ACTION_STATUS_UPDATE);
|
||||
sendBroadcast(intentAPPWidget);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
LogUtils.d(TAG, "onResume");
|
||||
@@ -83,39 +91,26 @@ public class MainActivity extends AppCompatActivity {
|
||||
Intent intent = new Intent(this, TestService.class);
|
||||
stopService(intent);
|
||||
SOS.sosWinBollService(this, new APPSOSBean(getPackageName(), TestService.class.getName()));
|
||||
|
||||
// Intent intentTimeWidget = new Intent(this, TimeWidget.class);
|
||||
// intentTimeWidget.setAction(TimeWidget.UPDATE_TIME_ACTION);
|
||||
// intentTimeWidget.putExtra("appName", "TestName");
|
||||
// sendBroadcast(intentTimeWidget);
|
||||
//
|
||||
}
|
||||
|
||||
// public void sos() {
|
||||
// // 创建Intent对象,指定广播的action
|
||||
// Intent intent = new Intent(SOSCSBroadcastReceiver.ACTION_SOS);
|
||||
// // 目标服务的包名和类名
|
||||
// String packageName = this.getPackageName();
|
||||
// String serviceClassName = SimpleOperateSignalCenterService.class.getName();
|
||||
// intent.putExtra(ISOSAPP.EXTRA_PACKAGE, packageName);
|
||||
// intent.putExtra(ISOSAPP.EXTRA_SERVICE, serviceClassName);
|
||||
// // 发送广播
|
||||
// sendBroadcast(intent);
|
||||
// LogUtils.d(TAG, "onSOS");
|
||||
// }
|
||||
//
|
||||
// public void sos2() {
|
||||
// // 创建Intent对象,指定广播的action
|
||||
// Intent intent = new Intent(SOSCSBroadcastReceiver.ACTION_SOS);
|
||||
// // 目标服务的包名和类名
|
||||
// String packageName = this.getPackageName();
|
||||
// String serviceClassName = SimpleOperateSignalCenterService.class.getName();
|
||||
// intent.putExtra(ISOSAPP.EXTRA_PACKAGE, packageName);
|
||||
// intent.putExtra(ISOSAPP.EXTRA_SERVICE, serviceClassName);
|
||||
// // 发送广播
|
||||
// sendBroadcast(intent);
|
||||
// LogUtils.d(TAG, "onSOS2");
|
||||
// }
|
||||
public void onStartTestService(View view) {
|
||||
Intent intent = new Intent(this, TestService.class);
|
||||
intent.setAction(SOS.ACTION_SERVICE_ENABLE);
|
||||
startService(intent);
|
||||
|
||||
}
|
||||
|
||||
public void onStopTestService(View view) {
|
||||
Intent intent = new Intent(this, TestService.class);
|
||||
intent.setAction(SOS.ACTION_SERVICE_DISABLE);
|
||||
startService(intent);
|
||||
|
||||
Intent intentStop = new Intent(this, TestService.class);
|
||||
stopService(intentStop);
|
||||
}
|
||||
|
||||
public void onStopTestServiceNoSettings(View view) {
|
||||
Intent intent = new Intent(this, TestService.class);
|
||||
stopService(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package cc.winboll.studio.libappbase.bean;
|
||||
package cc.winboll.studio.appbase.beans;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
@@ -10,17 +10,17 @@ import android.util.JsonWriter;
|
||||
import cc.winboll.studio.libappbase.BaseBean;
|
||||
import java.io.IOException;
|
||||
|
||||
public class APPSOSReportBean extends BaseBean {
|
||||
public class SOSReportBean extends BaseBean {
|
||||
|
||||
public static final String TAG = "APPSOSReportBean";
|
||||
|
||||
protected String sosReport;
|
||||
|
||||
public APPSOSReportBean() {
|
||||
public SOSReportBean() {
|
||||
this.sosReport = "";
|
||||
}
|
||||
|
||||
public APPSOSReportBean(String sosReport) {
|
||||
public SOSReportBean(String sosReport) {
|
||||
this.sosReport = sosReport;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public class APPSOSReportBean extends BaseBean {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return APPSOSReportBean.class.getName();
|
||||
return SOSReportBean.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -5,13 +5,24 @@ package cc.winboll.studio.appbase.receivers;
|
||||
* @Date 2025/02/13 06:58:04
|
||||
* @Describe 主要广播接收器
|
||||
*/
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import cc.winboll.studio.appbase.beans.SOSReportBean;
|
||||
import cc.winboll.studio.appbase.services.MainService;
|
||||
import cc.winboll.studio.appbase.widgets.SOSWidget;
|
||||
import cc.winboll.studio.libappbase.AppUtils;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.SOS;
|
||||
import cc.winboll.studio.libappbase.bean.APPSOSBean;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class MainReceiver extends BroadcastReceiver {
|
||||
|
||||
@@ -32,6 +43,75 @@ public class MainReceiver extends BroadcastReceiver {
|
||||
String szAction = intent.getAction();
|
||||
if (szAction.equals(ACTION_BOOT_COMPLETED)) {
|
||||
ToastUtils.show("ACTION_BOOT_COMPLETED");
|
||||
} else if (szAction.equals(SOS.ACTION_BIND)) {
|
||||
LogUtils.d(TAG, "ACTION_BIND");
|
||||
LogUtils.d(TAG, String.format("context.getPackageName() %s", context.getPackageName()));
|
||||
LogUtils.d(TAG, String.format("intent.getAction() %s", intent.getAction()));
|
||||
String SOS = intent.getStringExtra("SOS");
|
||||
LogUtils.d(TAG, String.format("SOS %s", SOS));
|
||||
if (SOS != null && SOS.equals("Service")) {
|
||||
String szAPPSOSBean = intent.getStringExtra("APPSOSBean");
|
||||
LogUtils.d(TAG, String.format("szAPPSOSBean %s", szAPPSOSBean));
|
||||
if (szAPPSOSBean != null && !szAPPSOSBean.equals("")) {
|
||||
try {
|
||||
APPSOSBean bean = APPSOSBean.parseStringToBean(szAPPSOSBean, APPSOSBean.class);
|
||||
if (bean != null) {
|
||||
String sosPackage = bean.getSosPackage();
|
||||
LogUtils.d(TAG, String.format("sosPackage %s", sosPackage));
|
||||
String sosClassName = bean.getSosClassName();
|
||||
LogUtils.d(TAG, String.format("sosClassName %s", sosClassName));
|
||||
mwrService.get().bindSOSConnection(bean);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (intent.getAction().equals(SOS.ACTION_SOS)) {
|
||||
LogUtils.d(TAG, "ACTION_SOS");
|
||||
LogUtils.d(TAG, String.format("context.getPackageName() %s", context.getPackageName()));
|
||||
LogUtils.d(TAG, String.format("intent.getAction() %s", intent.getAction()));
|
||||
String SOS = intent.getStringExtra("SOS");
|
||||
LogUtils.d(TAG, String.format("SOS %s", SOS));
|
||||
if (SOS != null && SOS.equals("Service")) {
|
||||
String szAPPSOSBean = intent.getStringExtra("APPSOSBean");
|
||||
LogUtils.d(TAG, String.format("szAPPSOSBean %s", szAPPSOSBean));
|
||||
if (szAPPSOSBean != null && !szAPPSOSBean.equals("")) {
|
||||
try {
|
||||
APPSOSBean bean = APPSOSBean.parseStringToBean(szAPPSOSBean, APPSOSBean.class);
|
||||
if (bean != null) {
|
||||
String sosPackage = bean.getSosPackage();
|
||||
LogUtils.d(TAG, String.format("sosPackage %s", sosPackage));
|
||||
String sosClassName = bean.getSosClassName();
|
||||
LogUtils.d(TAG, String.format("sosClassName %s", sosClassName));
|
||||
|
||||
Intent intentService = new Intent();
|
||||
intentService.setComponent(new ComponentName(sosPackage, sosClassName));
|
||||
context.startService(intentService);
|
||||
|
||||
String appName = AppUtils.getAppNameByPackageName(context, sosPackage);
|
||||
LogUtils.d(TAG, String.format("appName %s", appName));
|
||||
SOSReportBean appSOSReportBean = new SOSReportBean(appName);
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
|
||||
String currentTime = sdf.format(new Date());
|
||||
StringBuilder sbLine = new StringBuilder();
|
||||
sbLine.append("[");
|
||||
sbLine.append(currentTime);
|
||||
sbLine.append("] Power to ");
|
||||
sbLine.append(appName);
|
||||
appSOSReportBean.setSosReport(sbLine.toString());
|
||||
|
||||
SOSWidget.addAPPSOSReportBean(context, appSOSReportBean);
|
||||
|
||||
Intent intentWidget = new Intent(context, SOSWidget.class);
|
||||
intentWidget.setAction(SOSWidget.ACTION_RELOAD_REPORT);
|
||||
context.sendBroadcast(intentWidget);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ToastUtils.show(szAction);
|
||||
}
|
||||
@@ -39,10 +119,14 @@ public class MainReceiver extends BroadcastReceiver {
|
||||
|
||||
// 注册 Receiver
|
||||
//
|
||||
public void registerAction(Context context) {
|
||||
public void registerAction(MainService service) {
|
||||
IntentFilter filter=new IntentFilter();
|
||||
filter.addAction(ACTION_BOOT_COMPLETED);
|
||||
filter.addAction(SOS.ACTION_SOS);
|
||||
filter.addAction(SOS.ACTION_BIND);
|
||||
filter.addAction(SOS.ACTION_SERVICE_ENABLE);
|
||||
filter.addAction(SOS.ACTION_SERVICE_DISABLE);
|
||||
//filter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||
context.registerReceiver(this, filter);
|
||||
service.registerReceiver(this, filter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,10 @@ import cc.winboll.studio.appbase.handlers.MainServiceHandler;
|
||||
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.SOSWidget;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.widgets.APPSOSReportWidget;
|
||||
import cc.winboll.studio.libappbase.bean.APPSOSBean;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class MainService extends Service {
|
||||
|
||||
@@ -43,6 +45,7 @@ public class MainService extends Service {
|
||||
AssistantService mAssistantService;
|
||||
boolean isBound = false;
|
||||
MainReceiver mMainReceiver;
|
||||
ArrayList<SOSConnection> mSOSConnectionList;
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
@@ -57,6 +60,8 @@ public class MainService extends Service {
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
LogUtils.d(TAG, "onCreate()");
|
||||
mSOSConnectionList = new ArrayList<SOSConnection>();
|
||||
|
||||
_mControlCenterService = MainService.this;
|
||||
isServiceRunning = false;
|
||||
mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
|
||||
@@ -94,16 +99,16 @@ public class MainService extends Service {
|
||||
mMainReceiver = new MainReceiver(this);
|
||||
mMainReceiver.registerAction(this);
|
||||
}
|
||||
|
||||
|
||||
// 启动小部件
|
||||
Intent intentTimeWidget = new Intent(this, APPSOSReportWidget.class);
|
||||
intentTimeWidget.setAction(APPSOSReportWidget.ACTION_RELOAD_SOS_REPORT);
|
||||
Intent intentTimeWidget = new Intent(this, SOSWidget.class);
|
||||
intentTimeWidget.setAction(SOSWidget.ACTION_RELOAD_REPORT);
|
||||
this.sendBroadcast(intentTimeWidget);
|
||||
|
||||
|
||||
startMainServiceThread();
|
||||
|
||||
MyTileService.updateServiceIconStatus(this);
|
||||
|
||||
|
||||
LogUtils.i(TAG, "Main Service Is Start.");
|
||||
}
|
||||
}
|
||||
@@ -181,12 +186,73 @@ public class MainService extends Service {
|
||||
stopRemindThread();
|
||||
|
||||
MyTileService.updateServiceIconStatus(this);
|
||||
|
||||
|
||||
super.onDestroy();
|
||||
//LogUtils.d(TAG, "onDestroy done");
|
||||
}
|
||||
}
|
||||
|
||||
public void bindSOSConnection(APPSOSBean bean) {
|
||||
LogUtils.d(TAG, "bindSOSConnection(...)");
|
||||
// 清理旧的绑定链接
|
||||
for (int i = mSOSConnectionList.size() - 1; i > -1; i--) {
|
||||
SOSConnection item = mSOSConnectionList.get(i);
|
||||
if (item.isBindToAPPSOSBean(bean)) {
|
||||
LogUtils.d(TAG, "Bind Servive exist.");
|
||||
unbindService(item);
|
||||
mSOSConnectionList.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
// 绑定服务
|
||||
SOSConnection sosConnection = new SOSConnection();
|
||||
Intent intentService = new Intent();
|
||||
intentService.setComponent(new ComponentName(bean.getSosPackage(), bean.getSosClassName()));
|
||||
bindService(intentService, sosConnection, Context.BIND_IMPORTANT);
|
||||
mSOSConnectionList.add(sosConnection);
|
||||
|
||||
Intent intentWidget = new Intent(this, SOSWidget.class);
|
||||
intentWidget.setAction(SOSWidget.ACTION_WAKEUP_SERVICE);
|
||||
APPSOSBean appSOSBean = new APPSOSBean(bean.getSosPackage(), bean.getSosClassName());
|
||||
intentWidget.putExtra("APPSOSBean", appSOSBean.toString());
|
||||
sendBroadcast(intentWidget);
|
||||
}
|
||||
|
||||
public class SOSConnection implements ServiceConnection {
|
||||
|
||||
ComponentName mComponentName;
|
||||
|
||||
boolean isBindToAPPSOSBean(APPSOSBean bean) {
|
||||
return mComponentName != null
|
||||
&& mComponentName.getClassName().equals(bean.getSosClassName())
|
||||
&& mComponentName.getPackageName().equals(bean.getSosPackage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
LogUtils.d(TAG, "onServiceConnected(...)");
|
||||
mComponentName = name;
|
||||
LogUtils.d(TAG, String.format("onServiceConnected : \ngetClassName %s\ngetPackageName %s", name.getClassName(), name.getPackageName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
LogUtils.d(TAG, "onServiceDisconnected(...)");
|
||||
LogUtils.d(TAG, String.format("onServiceDisconnected : \ngetClassName %s\ngetPackageName %s", name.getClassName(), name.getPackageName()));
|
||||
|
||||
// 尝试无参数启动一下服务
|
||||
String sosPackage = mComponentName.getPackageName();
|
||||
LogUtils.d(TAG, String.format("sosPackage %s", sosPackage));
|
||||
String sosClassName = mComponentName.getClassName();
|
||||
LogUtils.d(TAG, String.format("sosClassName %s", sosClassName));
|
||||
|
||||
Intent intentService = new Intent();
|
||||
intentService.setComponent(new ComponentName(sosPackage, sosClassName));
|
||||
startService(intentService);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 主进程与守护进程连接时需要用到此类
|
||||
//
|
||||
private class MyServiceConnection implements ServiceConnection {
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package cc.winboll.studio.appbase.services;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/15 20:48:36
|
||||
* @Describe TestService
|
||||
*/
|
||||
public class TestService extends Service {
|
||||
|
||||
public static final String TAG = "TestService";
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
LogUtils.d(TAG, "onCreate()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
LogUtils.d(TAG, "onStartCommand(...)");
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
LogUtils.d(TAG, "onDestroy()");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
package cc.winboll.studio.appbase.widgets;
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/15 14:41:25
|
||||
* @Describe TimeWidget
|
||||
*/
|
||||
import android.app.PendingIntent;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
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.beans.SOSReportBean;
|
||||
import cc.winboll.studio.libappbase.AppUtils;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.bean.APPSOSBean;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
||||
public class SOSWidget extends AppWidgetProvider {
|
||||
|
||||
public static final String TAG = "SOSWidget";
|
||||
|
||||
public static final String ACTION_WAKEUP_SERVICE = "cc.winboll.studio.appbase.widgets.SOSWidget.ACTION_WAKEUP_SERVICE";
|
||||
public static final String ACTION_RELOAD_REPORT = "cc.winboll.studio.appbase.widgets.SOSWidget.ACTION_RELOAD_REPORT";
|
||||
|
||||
|
||||
volatile static ArrayList<SOSReportBean> _SOSReportBeanList;
|
||||
final static int _MAX_PAGES = 10;
|
||||
final static int _OnePageLinesCount = 5;
|
||||
volatile static int _CurrentPageIndex = 0;
|
||||
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||
initAPPSOSReportBeanList(context);
|
||||
for (int appWidgetId : appWidgetIds) {
|
||||
updateAppWidget(context, appWidgetManager, appWidgetId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
super.onReceive(context, intent);
|
||||
initAPPSOSReportBeanList(context);
|
||||
if (intent.getAction().equals(ACTION_RELOAD_REPORT)) {
|
||||
LogUtils.d(TAG, "ACTION_RELOAD_REPORT");
|
||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
|
||||
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, SOSWidget.class));
|
||||
for (int appWidgetId : appWidgetIds) {
|
||||
updateAppWidget(context, appWidgetManager, appWidgetId);
|
||||
}
|
||||
}else if (intent.getAction().equals(ACTION_WAKEUP_SERVICE)) {
|
||||
LogUtils.d(TAG, "ACTION_WAKEUP_SERVICE");
|
||||
String szAPPSOSBean = intent.getStringExtra("APPSOSBean");
|
||||
LogUtils.d(TAG, String.format("szAPPSOSBean %s", szAPPSOSBean));
|
||||
if (szAPPSOSBean != null && !szAPPSOSBean.equals("")) {
|
||||
try {
|
||||
APPSOSBean bean = APPSOSBean.parseStringToBean(szAPPSOSBean, APPSOSBean.class);
|
||||
if (bean != null) {
|
||||
String sosPackage = bean.getSosPackage();
|
||||
LogUtils.d(TAG, String.format("sosPackage %s", sosPackage));
|
||||
String sosClassName = bean.getSosClassName();
|
||||
LogUtils.d(TAG, String.format("sosClassName %s", sosClassName));
|
||||
|
||||
|
||||
String appName = AppUtils.getAppNameByPackageName(context, sosPackage);
|
||||
LogUtils.d(TAG, String.format("appName %s", appName));
|
||||
SOSReportBean appSOSReportBean = new SOSReportBean(appName);
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
|
||||
String currentTime = sdf.format(new Date());
|
||||
StringBuilder sbLine = new StringBuilder();
|
||||
sbLine.append("[");
|
||||
sbLine.append(currentTime);
|
||||
sbLine.append("] Wake up ");
|
||||
sbLine.append(appName);
|
||||
appSOSReportBean.setSosReport(sbLine.toString());
|
||||
|
||||
addAPPSOSReportBean(context, appSOSReportBean);
|
||||
|
||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
|
||||
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, SOSWidget.class));
|
||||
for (int appWidgetId : appWidgetIds) {
|
||||
updateAppWidget(context, appWidgetManager, appWidgetId);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 加入新报告信息
|
||||
//
|
||||
public synchronized static void addAPPSOSReportBean(Context context, SOSReportBean bean) {
|
||||
initAPPSOSReportBeanList(context);
|
||||
_SOSReportBeanList.add(0, bean);
|
||||
// 控制记录总数
|
||||
while (_SOSReportBeanList.size() > _MAX_PAGES * _OnePageLinesCount) {
|
||||
_SOSReportBeanList.remove(_SOSReportBeanList.size() - 1);
|
||||
}
|
||||
SOSReportBean.saveBeanList(context, _SOSReportBeanList, SOSReportBean.class);
|
||||
}
|
||||
|
||||
synchronized static void initAPPSOSReportBeanList(Context context) {
|
||||
if (_SOSReportBeanList == null) {
|
||||
_SOSReportBeanList = new ArrayList<SOSReportBean>();
|
||||
SOSReportBean.loadBeanList(context, _SOSReportBeanList, SOSReportBean.class);
|
||||
}
|
||||
if (_SOSReportBeanList == null) {
|
||||
_SOSReportBeanList = new ArrayList<SOSReportBean>();
|
||||
SOSReportBean.saveBeanList(context, _SOSReportBeanList, SOSReportBean.class);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
|
||||
LogUtils.d(TAG, "updateAppWidget(...)");
|
||||
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_sos);
|
||||
//设置按钮点击事件
|
||||
Intent intentPre = new Intent(context, SOSWidgetClickListener.class);
|
||||
intentPre.setAction(SOSWidgetClickListener.ACTION_PRE);
|
||||
PendingIntent pendingIntentPre = PendingIntent.getBroadcast(context, 0, intentPre, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
views.setOnClickPendingIntent(R.id.widget_button_pre, pendingIntentPre);
|
||||
Intent intentNext = new Intent(context, SOSWidgetClickListener.class);
|
||||
intentNext.setAction(SOSWidgetClickListener.ACTION_NEXT);
|
||||
PendingIntent pendingIntentNext = PendingIntent.getBroadcast(context, 0, intentNext, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
views.setOnClickPendingIntent(R.id.widget_button_next, pendingIntentNext);
|
||||
|
||||
views.setTextViewText(R.id.infoTextView, getPageInfo());
|
||||
views.setTextViewText(R.id.sosReportTextView, getMessage());
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views);
|
||||
}
|
||||
|
||||
public static String getMessage() {
|
||||
ArrayList<String> msgTemp = new ArrayList<String>();
|
||||
if (_SOSReportBeanList != null) {
|
||||
int start = _OnePageLinesCount * _CurrentPageIndex;
|
||||
start = _SOSReportBeanList.size() > start ? start : _SOSReportBeanList.size() - 1;
|
||||
for (int i = start, j = 0; i < _SOSReportBeanList.size() && j < _OnePageLinesCount && start > -1; i++, j++) {
|
||||
msgTemp.add(_SOSReportBeanList.get(i).getSosReport());
|
||||
}
|
||||
String message = String.join("\n", msgTemp);
|
||||
return message;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void prePage(Context context) {
|
||||
if (_SOSReportBeanList != null) {
|
||||
if (_CurrentPageIndex > 0) {
|
||||
_CurrentPageIndex = _CurrentPageIndex - 1;
|
||||
}
|
||||
Intent intentWidget = new Intent(context, SOSWidget.class);
|
||||
intentWidget.setAction(SOSWidget.ACTION_RELOAD_REPORT);
|
||||
context.sendBroadcast(intentWidget);
|
||||
}
|
||||
}
|
||||
|
||||
public static void nextPage(Context context) {
|
||||
if (_SOSReportBeanList != null) {
|
||||
if ((_CurrentPageIndex + 1) * _OnePageLinesCount < _SOSReportBeanList.size()) {
|
||||
_CurrentPageIndex = _CurrentPageIndex + 1;
|
||||
}
|
||||
Intent intentWidget = new Intent(context, SOSWidget.class);
|
||||
intentWidget.setAction(SOSWidget.ACTION_RELOAD_REPORT);
|
||||
context.sendBroadcast(intentWidget);
|
||||
}
|
||||
}
|
||||
|
||||
String getPageInfo() {
|
||||
if (_SOSReportBeanList == null) {
|
||||
return "0/0";
|
||||
}
|
||||
int leftCount = _SOSReportBeanList.size() % _OnePageLinesCount;
|
||||
int currentPageCount = _SOSReportBeanList.size() / _OnePageLinesCount + (leftCount == 0 ?0: 1);
|
||||
return String.format("%d/%d", _CurrentPageIndex + 1, currentPageCount);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package cc.winboll.studio.libappbase.widgets;
|
||||
package cc.winboll.studio.appbase.widgets;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
@@ -10,11 +10,11 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
|
||||
public class WidgetButtonClickListener extends BroadcastReceiver {
|
||||
public class SOSWidgetClickListener extends BroadcastReceiver {
|
||||
|
||||
public static final String TAG = "WidgetButtonClickListener";
|
||||
public static final String ACTION_PRE = "cc.winboll.studio.libappbase.widgets.WidgetButtonClickListener.ACTION_PRE";
|
||||
public static final String ACTION_NEXT = "cc.winboll.studio.libappbase.widgets.WidgetButtonClickListener.ACTION_NEXT";
|
||||
public static final String TAG = "SOSWidgetClickListener";
|
||||
public static final String ACTION_PRE = "cc.winboll.studio.appbase.widgets.SOSWidgetClickListener.ACTION_PRE";
|
||||
public static final String ACTION_NEXT = "cc.winboll.studio.appbase.widgets.SOSWidgetClickListener.ACTION_NEXT";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
@@ -25,10 +25,10 @@ public class WidgetButtonClickListener extends BroadcastReceiver {
|
||||
}
|
||||
if (action.equals(ACTION_PRE)) {
|
||||
LogUtils.d(TAG, "ACTION_PRE");
|
||||
APPSOSReportWidget.prePage(context);
|
||||
SOSWidget.prePage(context);
|
||||
} else if (action.equals(ACTION_NEXT)) {
|
||||
LogUtils.d(TAG, "ACTION_NEXT");
|
||||
APPSOSReportWidget.nextPage(context);
|
||||
SOSWidget.nextPage(context);
|
||||
} else {
|
||||
LogUtils.d(TAG, String.format("action %s", action));
|
||||
}
|
||||
@@ -24,6 +24,13 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello, WinBoll!"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
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,但可能需要注意兼容性和配置问题。"/>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
@@ -47,47 +54,88 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="right">
|
||||
android:layout_height="400dp">
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="StartCenter"
|
||||
android:textAllCaps="false"
|
||||
android:onClick="onStartCenter"/>
|
||||
android:gravity="right">
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="StopCenter"
|
||||
android:textAllCaps="false"
|
||||
android:onClick="onStopCenter"/>
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TestStopWithoutSettingEnable"
|
||||
android:textAllCaps="false"
|
||||
android:onClick="onTestStopWithoutSettingEnable"/>
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TestStartWithString"
|
||||
android:textAllCaps="false"
|
||||
android:onClick="onTestStartWithString"/>
|
||||
<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="SOS"
|
||||
android:onClick="onSOS"/>
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="StartTestService"
|
||||
android:textAllCaps="false"
|
||||
android:onClick="onStartTestService"/>
|
||||
|
||||
</LinearLayout>
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="StopTestService"
|
||||
android:textAllCaps="false"
|
||||
android:onClick="onStopTestService"/>
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="StopTestServiceNoSettings"
|
||||
android:textAllCaps="false"
|
||||
android:onClick="onStopTestServiceNoSettings"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
<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"/>
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TestStopWithoutSettingEnable"
|
||||
android:textAllCaps="false"
|
||||
android:onClick="onTestStopWithoutSettingEnable"/>
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TestStartWithString"
|
||||
android:textAllCaps="false"
|
||||
android:onClick="onTestStartWithString"/>
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SOS"
|
||||
android:textAllCaps="false"
|
||||
android:onClick="onSOS"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<cc.winboll.studio.libappbase.LogView
|
||||
android:layout_weight="1.0"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="AppTheme" parent="APPBaseTheme">
|
||||
<item name="attrColorPrimary">@color/colorPrimary</item>
|
||||
<item name="themeGlobalCrashActivity">@style/MyGlobalCrashActivityTheme</item>
|
||||
</style>
|
||||
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
android:minWidth="200dp"
|
||||
android:minHeight="100dp"
|
||||
android:updatePeriodMillis="1000"
|
||||
android:initialLayout="@layout/widget_layout">
|
||||
android:initialLayout="@layout/widget_sos">
|
||||
</appwidget-provider>
|
||||
40
build.gradle
@@ -1,8 +1,21 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
maven { url 'https://maven.aliyun.com/repository/public/' }
|
||||
maven { url 'https://maven.aliyun.com/repository/google/' }
|
||||
maven { url 'https://maven.aliyun.com/repository/gradle-plugin/' }
|
||||
maven { url 'https://dl.bintray.com/ppartisan/maven/' }
|
||||
maven { url "https://clojars.org/repo/" }
|
||||
maven { url "https://jitpack.io" }
|
||||
mavenCentral()
|
||||
google()
|
||||
mavenLocal()
|
||||
// Nexus Maven 库地址
|
||||
// "WinBoll Release"
|
||||
maven { url "https://nexus.winboll.cc/repository/maven-public/" }
|
||||
// "WinBoll Snapshot"
|
||||
maven { url "https://nexus.winboll.cc/repository/maven-snapshots/" }
|
||||
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.2.1'
|
||||
@@ -13,11 +26,12 @@ buildscript {
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
// Nexus Maven 库地址
|
||||
// "WinBoll Release"
|
||||
maven { url "https://nexus.winboll.cc/repository/maven-public/" }
|
||||
// "WinBoll Snapshot"
|
||||
maven { url "https://nexus.winboll.cc/repository/maven-snapshots/" }
|
||||
maven {
|
||||
url "https://mirrors.tencent.com/repository/maven/tencent_public/"
|
||||
}
|
||||
maven {
|
||||
url "https://mirrors.tencent.com/repository/maven/tencent_public_snapshots"
|
||||
}
|
||||
|
||||
maven { url 'https://maven.aliyun.com/repository/public/' }
|
||||
maven { url 'https://maven.aliyun.com/repository/google/' }
|
||||
@@ -28,6 +42,12 @@ allprojects {
|
||||
mavenCentral()
|
||||
google()
|
||||
mavenLocal()
|
||||
// Nexus Maven 库地址
|
||||
// "WinBoll Release"
|
||||
maven { url "https://nexus.winboll.cc/repository/maven-public/" }
|
||||
// "WinBoll Snapshot"
|
||||
maven { url "https://nexus.winboll.cc/repository/maven-snapshots/" }
|
||||
|
||||
}
|
||||
ext {
|
||||
// 定义全局变量,常用于版本管理
|
||||
@@ -69,6 +89,14 @@ allprojects {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subprojects {
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs << "-parameters"
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2048m
|
||||
org.gradle.jvmargs=-Xmx4096m
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
@@ -18,7 +18,9 @@ android.useAndroidX=true
|
||||
# Automatically convert third-party libraries to use AndroidX
|
||||
android.enableJetifier=true
|
||||
|
||||
#org.gradle.caching=true
|
||||
org.gradle.caching=true
|
||||
|
||||
android.disableAutomaticComponentCreation=true
|
||||
|
||||
android.injected.testOnly=false
|
||||
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl = https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||
distributionUrl = https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -4,14 +4,12 @@ apply from: '../.winboll/winboll_lib_build.gradle'
|
||||
apply from: '../.winboll/winboll_lint_build.gradle'
|
||||
|
||||
android {
|
||||
namespace 'cc.winboll.studio.libappbase'
|
||||
|
||||
compileSdkVersion 32
|
||||
buildToolsVersion "33.0.3"
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion "30.0.3"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 29
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
@@ -19,10 +17,6 @@ android {
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Mon Feb 17 12:09:50 HKT 2025
|
||||
#Tue Feb 25 16:51:09 HKT 2025
|
||||
stageCount=3
|
||||
libraryProject=libappbase
|
||||
baseVersion=1.5
|
||||
publishVersion=1.5.2
|
||||
baseVersion=2.0
|
||||
publishVersion=2.0.2
|
||||
buildCount=0
|
||||
baseBetaVersion=1.5.3
|
||||
baseBetaVersion=2.0.3
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
<!-- 拥有完全的网络访问权限 -->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<!-- 发送持久广播 -->
|
||||
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
|
||||
|
||||
<application>
|
||||
|
||||
<activity
|
||||
@@ -18,45 +21,58 @@
|
||||
android:label="GlobalCrashActivity"
|
||||
android:launchMode="standard"/>
|
||||
|
||||
<service android:name=".SimpleOperateSignalCenterService"
|
||||
android:exported="true">
|
||||
</service>
|
||||
|
||||
<activity android:name=".LogActivity"/>
|
||||
|
||||
<service
|
||||
android:name=".SimpleOperateSignalCenterService"
|
||||
android:exported="true">
|
||||
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name=".services.TestService"
|
||||
android:exported="true"/>
|
||||
|
||||
<receiver android:name=".receiver.MyBroadcastReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="cc.winboll.studio.libappbase.action.SOS" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name="cc.winboll.studio.libappbase.receiver.WinBollReceiver"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
|
||||
<action android:name="cc.winboll.studio.libappbase.WinBoll.ACTION_SOS"/>
|
||||
<action android:name="cc.winboll.studio.libappbase.action.SOS"/>
|
||||
|
||||
</intent-filter>
|
||||
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".widgets.APPSOSReportWidget"
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.StatusWidget"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
<action android:name="cc.winboll.studio.libappbase.widgets.APPSOSReportWidget.ACTION_ADD_SOS_REPORT" />
|
||||
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
||||
|
||||
<action android:name="cc.winboll.studio.libappbase.widgets.StatusWidget.ACTION_STATUS_UPDATE"/>
|
||||
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/appwidget_provider_info" />
|
||||
android:resource="@xml/widget_provider_info_status"/>
|
||||
|
||||
</receiver>
|
||||
<receiver android:name=".widgets.WidgetButtonClickListener">
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.StatusWidgetClickListener"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="cc.winboll.studio.libappbase.widgets.WidgetButtonClickListener.ACTION_PRE" />
|
||||
<action android:name="cc.winboll.studio.libappbase.widgets.WidgetButtonClickListener.ACTION_NEXT" />
|
||||
|
||||
<action android:name="cc.winboll.studio.libappbase.widgets.StatusWidgetClickListener.ACTION_IVAPP"/>
|
||||
|
||||
</intent-filter>
|
||||
|
||||
</receiver>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
@@ -118,7 +118,11 @@ public abstract class BaseBean<T extends BaseBean> {
|
||||
|
||||
public static <T extends BaseBean> boolean parseStringToBeanList(String szBeanList, ArrayList<T> beanList, Class<T> clazz) {
|
||||
try {
|
||||
beanList.clear();
|
||||
if(beanList == null) {
|
||||
beanList = new ArrayList<T>();
|
||||
} else {
|
||||
beanList.clear();
|
||||
}
|
||||
StringReader stringReader = new StringReader(szBeanList);
|
||||
JsonReader jsonReader = new JsonReader(stringReader);
|
||||
jsonReader.beginArray();
|
||||
|
||||
@@ -5,14 +5,22 @@ package cc.winboll.studio.libappbase;
|
||||
* @Date 2025/02/13 21:09:36
|
||||
* @Describe SOS 组件
|
||||
*/
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
import cc.winboll.studio.libappbase.bean.APPSOSBean;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class SOS {
|
||||
|
||||
public static final String TAG = "SOS";
|
||||
public static final String ACTION_SOS = "cc.winboll.studio.libappbase.WinBoll.ACTION_SOS";
|
||||
|
||||
public static final String ACTION_SOS = SOS.class.getName() + ".ACTION_SOS";
|
||||
public static final String ACTION_BIND = SOS.class.getName() + ".ACTION_BIND";
|
||||
public static final String ACTION_SERVICE_ENABLE = SOS.class.getName() + ".ACTION_SERVICE_ENABLE";
|
||||
public static final String ACTION_SERVICE_DISABLE = SOS.class.getName() + ".ACTION_SERVICE_DISENABLE";
|
||||
|
||||
public static void sosWinBollService(Context context, APPSOSBean bean) {
|
||||
Intent intent = new Intent(ACTION_SOS);
|
||||
@@ -27,8 +35,23 @@ public class SOS {
|
||||
intent.setPackage(szToPackage);
|
||||
context.sendBroadcast(intent);
|
||||
|
||||
LogUtils.d(TAG, String.format("SOS Send To WinBoll. (szToPackage : %s)", szToPackage));
|
||||
LogUtils.d(TAG, String.format("Send ACTION_SOS To WinBoll. (szToPackage : %s)", szToPackage));
|
||||
//ToastUtils.show("SOS Send To WinBoll");
|
||||
}
|
||||
|
||||
public static void bindToAPPService(Context context, APPSOSBean bean) {
|
||||
Intent intent = new Intent(ACTION_BIND);
|
||||
intent.putExtra("SOS", "Service");
|
||||
intent.putExtra("APPSOSBean", bean.toString());
|
||||
String szToPackage = "";
|
||||
if (GlobalApplication.isDebuging()) {
|
||||
szToPackage = "cc.winboll.studio.appbase.beta";
|
||||
} else {
|
||||
szToPackage = "cc.winboll.studio.appbase";
|
||||
}
|
||||
intent.setPackage(szToPackage);
|
||||
context.sendBroadcast(intent);
|
||||
LogUtils.d(TAG, String.format("Send ACTION_BIND To WinBoll. (szToPackage : %s)", szToPackage));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
package cc.winboll.studio.libappbase;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/15 12:14:45
|
||||
* @Describe WinBoll 类
|
||||
*/
|
||||
public class WinBoll {
|
||||
|
||||
public static final String TAG = "WinBoll";
|
||||
|
||||
public static final String ACTION_SOS = WinBoll.class.getName() + ".ACTION_SOS";
|
||||
|
||||
|
||||
}
|
||||
@@ -34,8 +34,7 @@ public class SimpleOperateSignalCenterServiceBean extends BaseBean {
|
||||
@Override
|
||||
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
|
||||
super.writeThisToJsonWriter(jsonWriter);
|
||||
SimpleOperateSignalCenterServiceBean bean = this;
|
||||
jsonWriter.name("isEnable").value(bean.isEnable());
|
||||
jsonWriter.name("isEnable").value(isEnable());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package cc.winboll.studio.libappbase.bean;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/19 13:34:52
|
||||
* @Describe TestServiceBean
|
||||
*/
|
||||
import android.util.JsonReader;
|
||||
import android.util.JsonWriter;
|
||||
import cc.winboll.studio.libappbase.BaseBean;
|
||||
import java.io.IOException;
|
||||
|
||||
public class TestServiceBean extends BaseBean {
|
||||
|
||||
public static final String TAG = "TestServiceBean";
|
||||
|
||||
boolean isEnable;
|
||||
|
||||
public TestServiceBean() {
|
||||
this.isEnable = false;
|
||||
}
|
||||
|
||||
public void setIsEnable(boolean isEnable) {
|
||||
this.isEnable = isEnable;
|
||||
}
|
||||
|
||||
public boolean isEnable() {
|
||||
return isEnable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return TestServiceBean.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
|
||||
super.writeThisToJsonWriter(jsonWriter);
|
||||
jsonWriter.name("isEnable").value(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;
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package cc.winboll.studio.libappbase.receiver;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.WinBoll;
|
||||
import cc.winboll.studio.libappbase.AppUtils;
|
||||
import cc.winboll.studio.libappbase.widgets.APPSOSReportWidget;
|
||||
import cc.winboll.studio.libappbase.bean.APPSOSBean;
|
||||
import java.io.IOException;
|
||||
import cc.winboll.studio.libappbase.bean.APPSOSReportBean;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/15 12:17:32
|
||||
* @Describe WinBollReceiver
|
||||
*/
|
||||
public class WinBollReceiver extends BroadcastReceiver {
|
||||
|
||||
public static final String TAG = "WinBollReceiver";
|
||||
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action.equals(WinBoll.ACTION_SOS)) {
|
||||
LogUtils.d(TAG, String.format("context.getPackageName() %s", context.getPackageName()));
|
||||
LogUtils.d(TAG, String.format("action %s", action));
|
||||
String SOS = intent.getStringExtra("SOS");
|
||||
LogUtils.d(TAG, String.format("SOS %s", SOS));
|
||||
if (SOS != null && SOS.equals("Service")) {
|
||||
String szAPPSOSBean = intent.getStringExtra("APPSOSBean");
|
||||
LogUtils.d(TAG, String.format("szAPPSOSBean %s", szAPPSOSBean));
|
||||
if (szAPPSOSBean != null && !szAPPSOSBean.equals("")) {
|
||||
try {
|
||||
APPSOSBean bean = APPSOSBean.parseStringToBean(szAPPSOSBean, APPSOSBean.class);
|
||||
if (bean != null) {
|
||||
String sosPackage = bean.getSosPackage();
|
||||
LogUtils.d(TAG, String.format("sosPackage %s", sosPackage));
|
||||
String sosClassName = bean.getSosClassName();
|
||||
LogUtils.d(TAG, String.format("sosClassName %s", sosClassName));
|
||||
|
||||
Intent intentService = new Intent();
|
||||
intentService.setComponent(new ComponentName(sosPackage, sosClassName));
|
||||
context.startService(intentService);
|
||||
|
||||
String appName = AppUtils.getAppNameByPackageName(context, sosPackage);
|
||||
LogUtils.d(TAG, String.format("appName %s", appName));
|
||||
APPSOSReportBean appSOSReportBean = new APPSOSReportBean(appName);
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
|
||||
String currentTime = sdf.format(new Date());
|
||||
StringBuilder sbLine = new StringBuilder();
|
||||
sbLine.append("[");
|
||||
sbLine.append(currentTime);
|
||||
sbLine.append("] Power to ");
|
||||
sbLine.append(appName);
|
||||
appSOSReportBean.setSosReport(sbLine.toString());
|
||||
|
||||
Intent intentAPPSOSReportWidget = new Intent(context, APPSOSReportWidget.class);
|
||||
intentAPPSOSReportWidget.setAction(APPSOSReportWidget.ACTION_ADD_SOS_REPORT);
|
||||
intentAPPSOSReportWidget.putExtra("APPSOSReportBean", appSOSReportBean.toString());
|
||||
context.sendBroadcast(intentAPPSOSReportWidget);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
LogUtils.d(TAG, String.format("action %s", action));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package cc.winboll.studio.libappbase.services;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/15 20:48:36
|
||||
* @Describe TestService
|
||||
*/
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.SOS;
|
||||
import cc.winboll.studio.libappbase.bean.APPSOSBean;
|
||||
import cc.winboll.studio.libappbase.bean.TestServiceBean;
|
||||
|
||||
public class TestService extends Service {
|
||||
|
||||
public static final String TAG = "TestService";
|
||||
|
||||
volatile static TestThread _TestThread;
|
||||
|
||||
volatile static boolean _IsRunning;
|
||||
|
||||
public synchronized static void setIsRunning(boolean isRunning) {
|
||||
_IsRunning = isRunning;
|
||||
}
|
||||
|
||||
public static boolean isRunning() {
|
||||
return _IsRunning;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return new MyBinder();
|
||||
}
|
||||
|
||||
public class MyBinder extends Binder {
|
||||
public TestService getService() {
|
||||
return TestService.this;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
LogUtils.d(TAG, "onCreate()");
|
||||
|
||||
|
||||
run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
LogUtils.d(TAG, "onStartCommand(...)");
|
||||
TestServiceBean bean = TestServiceBean.loadBean(this, TestServiceBean.class);
|
||||
if (bean == null) {
|
||||
bean = new TestServiceBean();
|
||||
}
|
||||
if (intent.getAction() != null && intent.getAction().equals(SOS.ACTION_SERVICE_ENABLE)) {
|
||||
bean.setIsEnable(true);
|
||||
TestServiceBean.saveBean(this, bean);
|
||||
run();
|
||||
} else if (intent.getAction() != null && intent.getAction().equals(SOS.ACTION_SERVICE_DISABLE)) {
|
||||
bean.setIsEnable(false);
|
||||
TestServiceBean.saveBean(this, bean);
|
||||
}
|
||||
LogUtils.d(TAG, String.format("TestServiceBean.saveBean setIsEnable %s", bean.isEnable()));
|
||||
return (bean.isEnable()) ? START_STICKY : super.onStartCommand(intent, flags, startId);
|
||||
//return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
|
||||
void run() {
|
||||
LogUtils.d(TAG, "run()");
|
||||
TestServiceBean bean = TestServiceBean.loadBean(this, TestServiceBean.class);
|
||||
if (bean == null) {
|
||||
bean = new TestServiceBean();
|
||||
TestServiceBean.saveBean(this, bean);
|
||||
}
|
||||
if (bean.isEnable()) {
|
||||
LogUtils.d(TAG, "run() bean.isEnable()");
|
||||
TestThread.getInstance(this).start();
|
||||
LogUtils.d(TAG, "_TestThread.start()");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
LogUtils.d(TAG, "onDestroy()");
|
||||
TestThread.getInstance(this).setIsExit(true);
|
||||
|
||||
_IsRunning = false;
|
||||
}
|
||||
|
||||
static class TestThread extends Thread {
|
||||
|
||||
volatile static TestThread _TestThread;
|
||||
Context mContext;
|
||||
volatile boolean isStarted = false;
|
||||
volatile boolean isExit = false;
|
||||
|
||||
TestThread(Context context) {
|
||||
super();
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public static synchronized TestThread getInstance(Context context) {
|
||||
if (_TestThread != null) {
|
||||
_TestThread.setIsExit(true);
|
||||
}
|
||||
_TestThread = new TestThread(context);
|
||||
|
||||
return _TestThread;
|
||||
}
|
||||
|
||||
public synchronized void setIsExit(boolean isExit) {
|
||||
this.isExit = isExit;
|
||||
}
|
||||
|
||||
public boolean isExit() {
|
||||
return isExit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (isStarted == false) {
|
||||
isStarted = true;
|
||||
super.run();
|
||||
LogUtils.d(TAG, "run() start");
|
||||
SOS.bindToAPPService(mContext, new APPSOSBean(mContext.getPackageName(), TestService.class.getName()));
|
||||
|
||||
while (!isExit()) {
|
||||
LogUtils.d(TAG, "run()");
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
}
|
||||
|
||||
LogUtils.d(TAG, "run() exit");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package cc.winboll.studio.libappbase.utils;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/17 19:38:20
|
||||
* @Describe 服务工具集
|
||||
*/
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import java.util.List;
|
||||
|
||||
public class ServiceUtils {
|
||||
|
||||
public static final String TAG = "ServiceUtils";
|
||||
|
||||
/**
|
||||
* 检查指定服务是否正在运行
|
||||
* @param context 上下文
|
||||
* @param serviceClass 服务类
|
||||
* @return true 如果服务正在运行,否则返回 false
|
||||
*/
|
||||
public static boolean isServiceRunning(Context context, String serviceClassName) {
|
||||
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
if (activityManager == null) {
|
||||
return false;
|
||||
}
|
||||
List<ActivityManager.RunningServiceInfo> runningServices;
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
// Intent intent = new Intent(context, serviceClass);
|
||||
// runningServices = activityManager.getRunningServices(100, intent);
|
||||
// } else {
|
||||
runningServices = activityManager.getRunningServices(100);
|
||||
//}
|
||||
for (ActivityManager.RunningServiceInfo serviceInfo : runningServices) {
|
||||
if (serviceClassName.equals(serviceInfo.service.getClassName())) {
|
||||
LogUtils.d(TAG, "Service is running: " + serviceInfo.service.getClassName());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
LogUtils.d(TAG, "Service is not running: " + serviceClassName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
package cc.winboll.studio.libappbase.widgets;
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/15 14:41:25
|
||||
* @Describe TimeWidget
|
||||
*/
|
||||
import android.app.PendingIntent;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
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 java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import cc.winboll.studio.libappbase.bean.APPSOSReportBean;
|
||||
import java.io.IOException;
|
||||
|
||||
public class APPSOSReportWidget extends AppWidgetProvider {
|
||||
|
||||
public static final String TAG = "APPSOSReportWidget";
|
||||
|
||||
public static final String ACTION_ADD_SOS_REPORT = "cc.winboll.studio.libappbase.widgets.APPSOSReportWidget.ACTION_ADD_SOS_REPORT";
|
||||
public static final String ACTION_RELOAD_SOS_REPORT = "cc.winboll.studio.libappbase.widgets.APPSOSReportWidget.ACTION_RELOAD_SOS_REPORT";
|
||||
|
||||
volatile static ArrayList<APPSOSReportBean> _APPSOSReportBeanList;
|
||||
final static int _MAX_PAGES = 10;
|
||||
final static int _OnePageLinesCount = 5;
|
||||
volatile static int _CurrentPageIndex = 0;
|
||||
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||
initAPPSOSReportBeanList(context);
|
||||
for (int appWidgetId : appWidgetIds) {
|
||||
updateAppWidget(context, appWidgetManager, appWidgetId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
super.onReceive(context, intent);
|
||||
initAPPSOSReportBeanList(context);
|
||||
if (intent.getAction().equals(ACTION_ADD_SOS_REPORT)) {
|
||||
LogUtils.d(TAG, "ACTION_ADD_SOS_REPORT");
|
||||
String szAPPSOSReportBean = intent.getStringExtra("APPSOSReportBean");
|
||||
LogUtils.d(TAG, String.format("szAPPSOSBean %s", szAPPSOSReportBean));
|
||||
if (szAPPSOSReportBean != null && !szAPPSOSReportBean.equals("")) {
|
||||
try {
|
||||
APPSOSReportBean bean = APPSOSReportBean.parseStringToBean(szAPPSOSReportBean, APPSOSReportBean.class);
|
||||
if (bean != null) {
|
||||
addAPPSOSReportBean(context, bean);
|
||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
|
||||
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, APPSOSReportWidget.class));
|
||||
for (int appWidgetId : appWidgetIds) {
|
||||
updateAppWidget(context, appWidgetManager, appWidgetId);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
}
|
||||
} else if (intent.getAction().equals(ACTION_RELOAD_SOS_REPORT)) {
|
||||
LogUtils.d(TAG, "ACTION_RELOAD_SOS_REPORT");
|
||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
|
||||
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, APPSOSReportWidget.class));
|
||||
for (int appWidgetId : appWidgetIds) {
|
||||
updateAppWidget(context, appWidgetManager, appWidgetId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// 加入新报告信息
|
||||
//
|
||||
void addAPPSOSReportBean(Context context, APPSOSReportBean bean) {
|
||||
initAPPSOSReportBeanList(context);
|
||||
_APPSOSReportBeanList.add(0, bean);
|
||||
// 控制记录总数
|
||||
while (_APPSOSReportBeanList.size() > _MAX_PAGES * _OnePageLinesCount) {
|
||||
_APPSOSReportBeanList.remove(_APPSOSReportBeanList.size() - 1);
|
||||
}
|
||||
APPSOSReportBean.saveBeanList(context, _APPSOSReportBeanList, APPSOSReportBean.class);
|
||||
}
|
||||
|
||||
void initAPPSOSReportBeanList(Context context) {
|
||||
if (_APPSOSReportBeanList == null) {
|
||||
_APPSOSReportBeanList = new ArrayList<APPSOSReportBean>();
|
||||
APPSOSReportBean.loadBeanList(context, _APPSOSReportBeanList, APPSOSReportBean.class);
|
||||
}
|
||||
if (_APPSOSReportBeanList == null) {
|
||||
_APPSOSReportBeanList = new ArrayList<APPSOSReportBean>();
|
||||
APPSOSReportBean.saveBeanList(context, _APPSOSReportBeanList, APPSOSReportBean.class);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
|
||||
LogUtils.d(TAG, "updateAppWidget(...)");
|
||||
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
|
||||
//设置按钮点击事件
|
||||
Intent intentPre = new Intent(context, WidgetButtonClickListener.class);
|
||||
intentPre.setAction(WidgetButtonClickListener.ACTION_PRE);
|
||||
PendingIntent pendingIntentPre = PendingIntent.getBroadcast(context, 0, intentPre, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
views.setOnClickPendingIntent(R.id.widget_button_pre, pendingIntentPre);
|
||||
Intent intentNext = new Intent(context, WidgetButtonClickListener.class);
|
||||
intentNext.setAction(WidgetButtonClickListener.ACTION_NEXT);
|
||||
PendingIntent pendingIntentNext = PendingIntent.getBroadcast(context, 0, intentNext, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
views.setOnClickPendingIntent(R.id.widget_button_next, pendingIntentNext);
|
||||
|
||||
views.setTextViewText(R.id.infoTextView, getPageInfo());
|
||||
views.setTextViewText(R.id.sosReportTextView, getMessage());
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views);
|
||||
}
|
||||
|
||||
public static String getMessage() {
|
||||
ArrayList<String> msgTemp = new ArrayList<String>();
|
||||
if (_APPSOSReportBeanList != null) {
|
||||
int start = _OnePageLinesCount * _CurrentPageIndex;
|
||||
start = _APPSOSReportBeanList.size() > start ? start : _APPSOSReportBeanList.size() - 1;
|
||||
for (int i = start, j = 0; i < _APPSOSReportBeanList.size() && j < _OnePageLinesCount; i++, j++) {
|
||||
msgTemp.add(_APPSOSReportBeanList.get(i).getSosReport());
|
||||
}
|
||||
String message = String.join("\n", msgTemp);
|
||||
return message;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void prePage(Context context) {
|
||||
if (_APPSOSReportBeanList != null) {
|
||||
if (_CurrentPageIndex > 0) {
|
||||
_CurrentPageIndex = _CurrentPageIndex - 1;
|
||||
}
|
||||
Intent intentAPPSOSReportWidget = new Intent(context, APPSOSReportWidget.class);
|
||||
intentAPPSOSReportWidget.setAction(APPSOSReportWidget.ACTION_RELOAD_SOS_REPORT);
|
||||
context.sendBroadcast(intentAPPSOSReportWidget);
|
||||
}
|
||||
}
|
||||
|
||||
public static void nextPage(Context context) {
|
||||
if (_APPSOSReportBeanList != null) {
|
||||
if ((_CurrentPageIndex + 1) * _OnePageLinesCount < _APPSOSReportBeanList.size()) {
|
||||
_CurrentPageIndex = _CurrentPageIndex + 1;
|
||||
}
|
||||
Intent intentAPPSOSReportWidget = new Intent(context, APPSOSReportWidget.class);
|
||||
intentAPPSOSReportWidget.setAction(APPSOSReportWidget.ACTION_RELOAD_SOS_REPORT);
|
||||
context.sendBroadcast(intentAPPSOSReportWidget);
|
||||
}
|
||||
}
|
||||
|
||||
String getPageInfo() {
|
||||
if (_APPSOSReportBeanList == null) {
|
||||
return "0/0";
|
||||
}
|
||||
int leftCount = _APPSOSReportBeanList.size() % _OnePageLinesCount;
|
||||
int currentPageCount = _APPSOSReportBeanList.size() / _OnePageLinesCount + (leftCount == 0 ?0: 1);
|
||||
return String.format("%d/%d", _CurrentPageIndex + 1, currentPageCount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package cc.winboll.studio.libappbase.widgets;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/17 20:32:12
|
||||
*/
|
||||
import android.app.PendingIntent;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
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 com.hjq.toast.ToastUtils;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
import cc.winboll.studio.libappbase.services.TestService;
|
||||
|
||||
public class StatusWidget extends AppWidgetProvider {
|
||||
|
||||
public static final String TAG = "StatusWidget";
|
||||
|
||||
public static final String ACTION_STATUS_UPDATE = "cc.winboll.studio.libappbase.widgets.APPWidget.ACTION_STATUS_UPDATE";
|
||||
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||
for (int appWidgetId : appWidgetIds) {
|
||||
updateAppWidget(context, appWidgetManager, appWidgetId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
super.onReceive(context, intent);
|
||||
if (intent.getAction().equals(ACTION_STATUS_UPDATE)) {
|
||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
|
||||
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, StatusWidget.class));
|
||||
for (int appWidgetId : appWidgetIds) {
|
||||
updateAppWidget(context, appWidgetManager, appWidgetId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_status);
|
||||
//设置按钮点击事件
|
||||
Intent intentAppButton = new Intent(context, StatusWidgetClickListener.class);
|
||||
intentAppButton.setAction(StatusWidgetClickListener.ACTION_IVAPP);
|
||||
PendingIntent pendingIntentAppButton = PendingIntent.getBroadcast(context, 0, intentAppButton, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
views.setOnClickPendingIntent(R.id.ivapp, pendingIntentAppButton);
|
||||
|
||||
boolean isActive = ServiceUtils.isServiceRunning(context, TestService.class.getName());
|
||||
if (isActive) {
|
||||
views.setImageViewResource(R.id.ivapp, cc.winboll.studio.libappbase.R.drawable.ic_launcher);
|
||||
} else {
|
||||
views.setImageViewResource(R.id.ivapp, cc.winboll.studio.libappbase.R.drawable.ic_launcher_disable);
|
||||
}
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package cc.winboll.studio.libappbase.widgets;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/17 20:33:53
|
||||
* @Describe APPWidgetClickListener
|
||||
*/
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
|
||||
public class StatusWidgetClickListener extends BroadcastReceiver {
|
||||
|
||||
public static final String TAG = "APPWidgetClickListener";
|
||||
|
||||
public static final String ACTION_IVAPP = "cc.winboll.studio.libappbase.widgets.StatusWidgetClickListener.ACTION_IVAPP";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action == null) {
|
||||
LogUtils.d(TAG, String.format("action %s", action));
|
||||
return;
|
||||
}
|
||||
if (action.equals(ACTION_IVAPP)) {
|
||||
ToastUtils.show("ACTION_LAUNCHER");
|
||||
} else {
|
||||
LogUtils.d(TAG, String.format("action %s", action));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
<?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="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>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:clickable="true"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp">
|
||||
<item android:drawable="@drawable/ic_launcher_background"/>
|
||||
<item
|
||||
android:left="0dp"
|
||||
android:top="0dp"
|
||||
android:right="0dp"
|
||||
android:bottom="0dp"
|
||||
android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</layer-list>
|
||||
|
||||
170
libappbase/src/main/res/drawable/ic_launcher_background.xml
Normal file
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#FF005C12"
|
||||
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>
|
||||
13
libappbase/src/main/res/drawable/ic_launcher_disable.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:clickable="true"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp">
|
||||
<item android:drawable="@drawable/ic_launcher_background"/>
|
||||
<item
|
||||
android:left="0dp"
|
||||
android:top="0dp"
|
||||
android:right="0dp"
|
||||
android:bottom="0dp"
|
||||
android:drawable="@drawable/ic_launcher_foreground_disable"/>
|
||||
</layer-list>
|
||||
10
libappbase/src/main/res/drawable/ic_launcher_foreground.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?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>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?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="#FF808080"
|
||||
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>
|
||||
15
libappbase/src/main/res/layout/widget_status.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:id="@+id/ivapp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<attr name="attrColorPrimary" format="color" />
|
||||
|
||||
<attr name="themeGlobalCrashActivity" format="reference"/>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#FFFFE200</color>
|
||||
<color name="colorPrimaryDark">#FFFFE200</color>
|
||||
<color name="colorAccent">#FFFFE200</color>
|
||||
<color name="colorText">#FFFFE200</color>
|
||||
<color name="colorPrimary">#FF00B322</color>
|
||||
<color name="colorPrimaryDark">#FF005C12</color>
|
||||
<color name="colorAccent">#FF8DFFA2</color>
|
||||
<color name="colorText">#FFFFFB8D</color>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:minWidth="40dp"
|
||||
android:minHeight="40dp"
|
||||
android:updatePeriodMillis="1000"
|
||||
android:initialLayout="@layout/widget_status"
|
||||
android:resizeMode="none">
|
||||
</appwidget-provider>
|
||||
BIN
positions/.DS_Store
vendored
Normal file
39
positions/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Positions
|
||||
|
||||
#### 介绍
|
||||
位置应用,与卫星定位有关的应用。可以根据设定的位置与时间条件判断,来发送通知的应用。
|
||||
|
||||
#### 软件架构
|
||||
以腾讯位置服务SDK源码为基础。源码地址:https://lbs.qq.com/mobile/androidMapSDK/developerGuide/configuration
|
||||
适配安卓应用 [AIDE Pro] 的 Gradle 编译结构。
|
||||
也适配安卓应用 [AndroidIDE] 的 Gradle 编译结构。
|
||||
|
||||
|
||||
#### Gradle 编译说明
|
||||
调试版编译命令 :gradle assembleBetaDebug
|
||||
阶段版编译命令 :gradle assembleStageRelease
|
||||
|
||||
#### 使用说明
|
||||
|
||||
在安卓系统中需要设置两个权限允许。
|
||||
1.自启动权限允许。
|
||||
2.省电策略-无限制权限允许。
|
||||
|
||||
#### 参与贡献
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码 : ZhanGSKen(ZhanGSKen@AliYun.Com)
|
||||
4. 新建 Pull Request
|
||||
|
||||
|
||||
#### 特技
|
||||
|
||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
|
||||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
|
||||
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
|
||||
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
||||
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
|
||||
#### 参考文档
|
||||
0
positions/app_update_description.txt
Normal file
84
positions/build.gradle
Normal file
@@ -0,0 +1,84 @@
|
||||
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']
|
||||
}
|
||||
|
||||
Properties properties = new Properties()
|
||||
File localFile = project.rootProject.file('local.properties')
|
||||
if (localFile.exists()) {
|
||||
InputStream inputStream = localFile.newDataInputStream()
|
||||
properties.load(inputStream)
|
||||
}
|
||||
|
||||
def mapsdkkey = properties.getProperty('mapsdk.key', "")
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion "30.0.3"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "cc.winboll.studio.positions"
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
// versionName 更新后需要手动设置
|
||||
// 项目模块目录的 build.gradle 文件的 stageCount=0
|
||||
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
|
||||
versionName "1.0"
|
||||
if(true) {
|
||||
versionName = genVersionName("${versionName}")
|
||||
}
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
manifestPlaceholders = ["TencentMapSDK_KEY": mapsdkkey]
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// 定位服务
|
||||
implementation 'com.google.android.gms:play-services-location:20.0.0'
|
||||
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.viewpager:viewpager:1.0.0'
|
||||
implementation 'androidx.fragment:fragment:1.0.0'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
implementation 'pub.devrel:easypermissions:2.0.1'
|
||||
// 地图
|
||||
implementation 'com.tencent.map:tencent-map-vector-sdk:6.2.1.250120.3f971009.140342819'
|
||||
// 基础库
|
||||
implementation 'com.tencent.openmap:foundation:0.5.6.9be4e02'
|
||||
implementation 'com.tencent.map:sdk-utilities:1.0.9'
|
||||
implementation 'com.tencent.map.geolocation:TencentLocationSdk-openplatform:7.5.4.3'
|
||||
implementation 'com.google.code.gson:gson:2.8.5'
|
||||
|
||||
implementation 'io.github.medyo:android-about-page:2.0.0'
|
||||
implementation 'com.github.getActivity:ToastUtils:10.5'
|
||||
|
||||
implementation 'cc.winboll.studio:libapputils:9.3.2'
|
||||
implementation 'cc.winboll.studio:libappbase:1.5.6'
|
||||
}
|
||||
8
positions/build.properties
Normal file
@@ -0,0 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Tue Feb 25 05:04:52 GMT 2025
|
||||
stageCount=0
|
||||
libraryProject=
|
||||
baseVersion=1.0
|
||||
publishVersion=1.0.0
|
||||
buildCount=184
|
||||
baseBetaVersion=1.0.1
|
||||
41
positions/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
# 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
|
||||
-dontwarn com.tencent.bugly.**
|
||||
-keep public class com.tencent.bugly.**{*;}
|
||||
|
||||
-dontwarn com.tencent.tmsqmsp.**
|
||||
-keep public class com.tencent.tmsqmsp.**{*;}
|
||||
|
||||
-dontwarn com.tencent.tmsbeacon.**
|
||||
-keep public class com.tencent.tmsbeacon.**{*;}
|
||||
|
||||
-dontwarn com.tencent.map.**
|
||||
-keep public class com.tencent.map.** {*;}
|
||||
|
||||
-dontwarn com.tencent.mapsdk.**
|
||||
-keep public class com.tencent.mapsdk.** {*;}
|
||||
|
||||
-dontwarn com.tencent.tencentmap.**
|
||||
-keep public class com.tencent.tencentmap.** {*;}
|
||||
|
||||
-dontwarn com.tencent.lbssearch.**
|
||||
-keep public class com.tencent.lbssearch.** {*;}
|
||||
BIN
positions/src/.DS_Store
vendored
Normal file
13
positions/src/beta/AndroidManifest.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?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
|
||||
tools:replace="android:icon"
|
||||
android:icon="@drawable/ic_winbollbeta">
|
||||
|
||||
<!-- Put flavor specific code here -->
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
6
positions/src/beta/res/values/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_name">Positions+</string>
|
||||
|
||||
</resources>
|
||||
BIN
positions/src/main/.DS_Store
vendored
Normal file
741
positions/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,741 @@
|
||||
<?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.positions">
|
||||
|
||||
<!-- 拥有完全的网络访问权限 -->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<!-- 查看网络连接 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
|
||||
<!-- 查看WLAN连接 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
|
||||
<!-- 修改或删除您共享存储空间中的内容 -->
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
|
||||
<!-- 读取您共享存储空间中的内容 -->
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
|
||||
<!-- 读取手机状态和身份 -->
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
|
||||
|
||||
<!-- 只能在前台获取精确的位置信息 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
|
||||
<!-- 只能在前台获取大概位置(基于网络) -->
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
||||
|
||||
<!-- 连接WLAN网络和断开连接 -->
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||
|
||||
<!-- 更改网络连接性 -->
|
||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
|
||||
|
||||
<application
|
||||
android:name=".App"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/MyAppTheme"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
tools:ignore="AllowBackup,GoogleAppIndexingWarning"
|
||||
tools:targetApi="q">
|
||||
|
||||
<activity android:name=".MainSimpleActivity">
|
||||
|
||||
<intent-filter>
|
||||
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity android:name=".MainActivity2">
|
||||
|
||||
</activity>
|
||||
|
||||
<activity android:name="com.tencent.map.vector.demo.DemoMainActivity">
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="com.tencent.map.vector.demo.basic.MapViewActivity"
|
||||
android:description="@string/demo_description_show_map"
|
||||
android:label="@string/demo_label_show_map">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_basic"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".basic.SetMapTypeActivity"
|
||||
android:description="@string/demo_description_map_type"
|
||||
android:label="@string/demo_label_map_type">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_basic"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".basic.MapRenderLayerActivity"
|
||||
android:description="@string/demo_description_show_mapRenderLayer"
|
||||
android:label="@string/demo_label_show_mapRenderLayer">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_basic"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".location.LocationLayerActivity"
|
||||
android:description="@string/demo_description_show_location"
|
||||
android:label="@string/demo_label_show_location">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_location"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".location.LocationPointActivity"
|
||||
android:description="@string/demo_description_change_location_style"
|
||||
android:label="@string/demo_label_change_location_style">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_location"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".basic.IndoorMapActivity"
|
||||
android:description="@string/demo_description_indoor_map"
|
||||
android:label="@string/demo_label_indoor_map">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_basic"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".basic.OverseaMapActivity"
|
||||
android:description="@string/demo_description_oversea"
|
||||
android:label="@string/demo_label_oversea">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_basic"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".basic.MapStyleDemoActivity"
|
||||
android:description="@string/demo_description_style"
|
||||
android:label="@string/demo_label_style">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_basic"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".basic.UiSettingsActivity"
|
||||
android:description="@string/demo_description_ui"
|
||||
android:label="@string/demo_label_ui">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_interactive"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".gesture.GestureSettingsActivity"
|
||||
android:description="@string/demo_description_gesture"
|
||||
android:label="@string/demo_label_gesture">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_interactive"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".transaction.ZoomMapActivity"
|
||||
android:description="@string/demo_description_modify_zoom"
|
||||
android:label="@string/demo_label_modify_zoom">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_interactive"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".camera.MapCameraCenterActivity"
|
||||
android:description="@string/demo_description_modify_map_center"
|
||||
android:label="@string/demo_label_modify_map_center">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_interactive"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".camera.MapBoundActivity"
|
||||
android:description="@string/demo_description_map_bound"
|
||||
android:label="@string/demo_label_map_bound">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_interactive"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".poi.PoiClickActivity"
|
||||
android:description="@string/demo_description_click_poi"
|
||||
android:label="@string/demo_label_click_poi">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_interactive"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".transaction.AnimateCameraActivity"
|
||||
android:description="@string/demo_description_animate_camera"
|
||||
android:label="@string/demo_label_animate_camera">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_interactive"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".camera.MapAnchorZoomActivity"
|
||||
android:description="@string/demo_description_map_camera_anchor"
|
||||
android:label="@string/demo_label_map_camera_anchor">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_interactive"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".transaction.ScollMapActivity"
|
||||
android:description="@string/demo_description_camera_translation"
|
||||
android:label="@string/demo_label_camera_translation">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_transformation"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".transaction.RotateMapActivity"
|
||||
android:description="@string/demo_description_camera_rotation"
|
||||
android:label="@string/demo_label_camera_rotation">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_transformation"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".transaction.ZoomCalulateActivity"
|
||||
android:description="@string/demo_description_camera_include_points"
|
||||
android:label="@string/demo_label_camera_include_points">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_transformation"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".transaction.MoveCameraActivity"
|
||||
android:description="@string/demo_description_camera_change_listener"
|
||||
android:label="@string/demo_label_camera_change_listener">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_transformation"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".gesture.MapListenActivity"
|
||||
android:description="@string/demo_description_map_click_listener"
|
||||
android:label="@string/demo_label_map_click_listener">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_transformation"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".gesture.MapLongClickActivity"
|
||||
android:description="@string/demo_description_map_long_click_listener"
|
||||
android:label="@string/demo_label_map_long_click_listener">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_transformation"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".marker.SimpleMarkerActivity"
|
||||
android:description="@string/demo_description_simple_marker"
|
||||
android:label="@string/demo_label_simple_marker">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_marker"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".marker.MarkerCollisions"
|
||||
android:description="@string/demo_description_collisions_marker"
|
||||
android:label="@string/demo_label_collisions_marker">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_marker"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".marker.MarkerOptionsActivity"
|
||||
android:description="@string/demo_description_marker_options"
|
||||
android:label="@string/demo_label_marker_options">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_marker"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".marker.MarkerClickActivity"
|
||||
android:description="@string/demo_description_marker_click_listener"
|
||||
android:label="@string/demo_label_marker_click_listener">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_marker"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".marker.MarkerDragActivity"
|
||||
android:description="@string/demo_description_marker_drag_listener"
|
||||
android:label="@string/demo_label_marker_drag_listener">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_marker"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".marker.MarkerInfoWindowActivity"
|
||||
android:description="@string/demo_description_infowindow_click_listener"
|
||||
android:label="@string/demo_label_infowindow_click_listener">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_marker"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".marker.MarkerClusterActivity"
|
||||
android:description="@string/demo_description_marker_cluster"
|
||||
android:label="@string/demo_label_marker_cluster">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_marker"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".marker.MarkerAnimation"
|
||||
android:description="@string/demo_description_marker_animation"
|
||||
android:label="@string/demo_label_marker_animation">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_marker"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".heatoverlay.DrawHeatOverlayActivity"
|
||||
android:description="@string/demo_description_heat_map"
|
||||
android:label="@string/demo_label_heat_map">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".polygon.TileOverlayActivity"
|
||||
android:description="@string/demo_description_tileOverlay_map"
|
||||
android:label="@string/demo_label_tileOverlay_map">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".polyline.DrawLineActivity"
|
||||
android:description="@string/demo_description_polyline"
|
||||
android:label="@string/demo_label_polyline">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".polyline.MutablePolylineActivity"
|
||||
android:description="@string/demo_description_mutable_polyline"
|
||||
android:label="@string/demo_label_mutable_polyline">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".polygon.DrawPolygonActivity"
|
||||
android:description="@string/demo_description_polygon"
|
||||
android:label="@string/demo_label_polygon">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".circle.DrawCircleActivity"
|
||||
android:description="@string/demo_description_circle"
|
||||
android:label="@string/demo_label_circle">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".circle.ArcActivity"
|
||||
android:description="@string/demo_description_arc"
|
||||
android:label="@string/demo_label_arc">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".search.WalkingRouteActivity"
|
||||
android:description="@string/demo_description_walking_plan"
|
||||
android:label="@string/demo_label_walking_plan">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_route_plan"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".search.DrivingRouteActivity"
|
||||
android:description="@string/demo_description_driving_plan"
|
||||
android:label="@string/demo_label_driving_plan">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_route_plan"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".search.TransitRouteActivity"
|
||||
android:description="@string/demo_description_transit_plan"
|
||||
android:label="@string/demo_label_transit_plan">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_route_plan"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".search.TruckingRouteActivity"
|
||||
android:description="@string/demo_description_truking_plan"
|
||||
android:label="@string/demo_label_truking_plan">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_route_plan"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".search.SearchBasicActivity"
|
||||
android:description="@string/demo_description_basic_search"
|
||||
android:label="@string/demo_label_basic_search">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_search"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".search.GeoCoderActivity"
|
||||
android:description="@string/demo_description_geocoder"
|
||||
android:label="@string/demo_label_geocoder">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_search"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".search.DistrictActivity"
|
||||
android:description="@string/demo_description_district"
|
||||
android:label="@string/demo_label_district">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_search"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".polyline.LineTextActivity"
|
||||
android:description="@string/demo_description_line_text"
|
||||
android:label="@string/demo_label_line_text">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_special"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".utils.BitMapActivity"
|
||||
android:description="@string/demo_description_bitmap"
|
||||
android:enabled="false"
|
||||
android:label="@string/demo_label_bitmap">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_tools"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".utils.SnapshotActivity"
|
||||
android:description="@string/demo_description_map_snapshot"
|
||||
android:label="@string/demo_label_map_snapshot">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_tools"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".utils.CoordinateActivity"
|
||||
android:description="@string/demo_description_projection"
|
||||
android:label="@string/demo_label_projection">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_tools"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity android:name=".basic.SupportMapFragmentActivity"/>
|
||||
|
||||
<activity
|
||||
android:name=".marker.CustomRenderActivity"
|
||||
android:description="@string/demo_description_opengl"
|
||||
android:label="@string/demo_label_opengl">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".marker.GroundOverlayActivity"
|
||||
android:description="@string/demo_description_overlay"
|
||||
android:label="@string/demo_label_ground_overlay">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".marker.AoiLayerActivity"
|
||||
android:description="@string/demo_description_aoi"
|
||||
android:label="@string/demo_label_aoi">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".heatoverlay.VectorHeatMapActivity"
|
||||
android:description="@string/demo_description_vectorheatmap"
|
||||
android:label="@string/demo_label_vectorheatmap">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".heatoverlay.ArcLineLayerActivity"
|
||||
android:description="@string/demo_description_arcline"
|
||||
android:label="@string/demo_label_arcline_map">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".heatoverlay.HeatMapVectorOverlayActivity"
|
||||
android:description="@string/demo_description_3dheatmap"
|
||||
android:label="@string/demo_label_3d_heat_map">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".heatoverlay.AggregationOverlayActivity"
|
||||
android:description="@string/demo_description_AggregationOverlay"
|
||||
android:label="@string/demo_label_3d_aggregationOverlay_map">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".heatoverlay.ScatterPlotOverlayActivity"
|
||||
android:description="@string/demo_description_ScatterPlotOverlay"
|
||||
android:label="@string/demo_label_3d_scatterplotoverlay_map">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".heatoverlay.TrailOverlayActivity"
|
||||
android:description="@string/demo_description_TrailOverlay"
|
||||
android:label="@string/demo_label_3d_railoverltay_map">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".heatoverlay.GLModelActivity"
|
||||
android:description="@string/demo_description_glModel"
|
||||
android:label="@string/demo_label_glModel">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".basic.RecyclerListActivity"
|
||||
android:description="@string/demo_description_recycler_map"
|
||||
android:label="@string/demo_label_recycler_map">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_basic"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".smooth.SmoothMoveActivity"
|
||||
android:description="@string/demo_description_smooth_move"
|
||||
android:label="@string/demo_label_smooth_move">
|
||||
|
||||
<meta-data
|
||||
android:name="@string/demo_type"
|
||||
android:value="@string/demo_type_draw"/>
|
||||
|
||||
</activity>
|
||||
|
||||
<meta-data
|
||||
android:name="TencentMapSDK"
|
||||
android:value="SCYBZ-EC5Y4-XMHUI-FX2PU-ZYMMS-IBB7P"/>
|
||||
|
||||
<activity android:name="cc.winboll.studio.positions.activities.TestMapViewActivity"/>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
BIN
positions/src/main/assets/21.jpg
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
positions/src/main/assets/22.jpg
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
positions/src/main/assets/23.jpg
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
positions/src/main/assets/24.jpg
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
positions/src/main/assets/25.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
positions/src/main/assets/26.jpg
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
50
positions/src/main/assets/arc.dat
Normal file
@@ -0,0 +1,50 @@
|
||||
31.23037 121.4737 40.07733 116.60039 45.0
|
||||
30.5702 104.06476 40.07733 116.60039 45.0
|
||||
22.54286 114.05956 40.07733 116.60039 45.0
|
||||
23.12908 113.26436 40.07733 116.60039 45.0
|
||||
29.56471 106.55073 40.07733 116.60039 45.0
|
||||
30.27415 120.15515 40.07733 116.60039 45.0
|
||||
24.87966 102.83322 40.07733 116.60039 45.0
|
||||
34.32932 108.70929 40.07733 116.60039 45.0
|
||||
45.80216 126.5358 40.07733 116.60039 45.0
|
||||
28.22778 112.93886 40.07733 116.60039 45.0
|
||||
18.25248 109.51209 40.07733 116.60039 45.0
|
||||
43.82663 87.61688 40.07733 116.60039 45.0
|
||||
30.59276 114.30525 40.07733 116.60039 45.0
|
||||
22.27534 114.16546 40.07733 116.60039 45.0
|
||||
26.64702 106.63024 40.07733 116.60039 45.0
|
||||
24.47951 118.08948 40.07733 116.60039 45.0
|
||||
20.04422 110.19989 40.07733 116.60039 45.0
|
||||
28.68202 115.85794 40.07733 116.60039 45.0
|
||||
43.81602 125.32357 40.07733 116.60039 45.0
|
||||
36.06623 120.38299 40.07733 116.60039 45.0
|
||||
22.81673 108.3669 40.07733 116.60039 45.0
|
||||
26.07421 119.29647 40.07733 116.60039 45.0
|
||||
38.91369 121.61476 40.07733 116.60039 45.0
|
||||
41.80563 123.43236 40.07733 116.60039 45.0
|
||||
32.05838 118.79647 40.07733 116.60039 45.0
|
||||
36.06138 103.83417 40.07733 116.60039 45.0
|
||||
38.48644 106.23248 40.07733 116.60039 45.0
|
||||
27.99492 120.69939 40.07733 116.60039 45.0
|
||||
37.46353 121.44801 40.07733 116.60039 45.0
|
||||
22.27073 113.57668 40.07733 116.60039 45.0
|
||||
29.87386 121.55027 40.07733 116.60039 45.0
|
||||
31.82057 117.22901 40.07733 116.60039 45.0
|
||||
34.34127 108.93984 40.07733 116.60039 45.0
|
||||
49.21163 119.76584 40.07733 116.60039 45.0
|
||||
40.84149 111.75199 40.07733 116.60039 45.0
|
||||
37.87059 112.55067 40.07733 116.60039 45.0
|
||||
46.58758 125.10307 40.07733 116.60039 45.0
|
||||
25.27361 110.29002 40.07733 116.60039 45.0
|
||||
31.46751 104.6796 40.07733 116.60039 45.0
|
||||
24.87389 118.67587 40.07733 116.60039 45.0
|
||||
30.69186 111.28642 40.07733 116.60039 45.0
|
||||
23.54972 116.37271 40.07733 116.60039 45.0
|
||||
40.65781 109.84021 40.07733 116.60039 45.0
|
||||
37.51348 122.12171 40.07733 116.60039 45.0
|
||||
31.49099 120.31237 40.07733 116.60039 45.0
|
||||
22.18684 113.54294 40.07733 116.60039 45.0
|
||||
34.74725 113.62493 40.07733 116.60039 45.0
|
||||
34.61812 112.45361 40.07733 116.60039 45.0
|
||||
36.50204 102.104287 40.07733 116.60039 45.0
|
||||
24.954708 121.48068 40.07733 116.60039 45.0
|
||||
10
positions/src/main/assets/arcDistricts.dat
Normal file
@@ -0,0 +1,10 @@
|
||||
39.90469 116.40717 29.56471 106.55073 30.0
|
||||
39.90469 116.40717 39.53775 116.68376 30.0
|
||||
39.90469 116.40717 31.23037 121.4737 30.0
|
||||
39.90469 116.40717 23.12908 113.26436 30.0
|
||||
39.90469 116.40717 28.22778 112.93886 30.0
|
||||
29.56471 106.55073 39.90469 116.40717 60.0
|
||||
18.25248 109.51209 39.90469 116.40717 60.0
|
||||
31.23037 121.4737 39.90469 116.40717 60.0
|
||||
23.12908 113.26436 39.90469 116.40717 60.0
|
||||
39.53775 116.68376 39.90469 116.40717 60.0
|
||||
25
positions/src/main/assets/cluster_new
Normal file
@@ -0,0 +1,25 @@
|
||||
116.307621 39.984059
|
||||
116.304703 39.981954
|
||||
116.312256 39.984355
|
||||
116.315346 39.980442
|
||||
116.308994 39.981527
|
||||
116.310539 39.979751
|
||||
116.305776 39.977252
|
||||
116.316419 39.984026
|
||||
116.314874 39.976956
|
||||
116.311827 39.978501
|
||||
116.312814 39.980277
|
||||
116.369022 39.980236
|
||||
116.368486 39.980236
|
||||
116.367488 39.977161
|
||||
116.396713 39.915398
|
||||
116.455421 39.937645
|
||||
116.321182 39.896304
|
||||
121.452827 31.254487
|
||||
121.485443 31.225133
|
||||
121.442528 31.216912
|
||||
121.500893 31.251552
|
||||
121.455917 31.249204
|
||||
114.042892 22.546885
|
||||
113.999805 22.538086
|
||||
114.082031 22.538086
|
||||
BIN
positions/src/main/assets/color_arrow_texture.png
Normal file
|
After Width: | Height: | Size: 781 B |
BIN
positions/src/main/assets/color_texture.png
Normal file
|
After Width: | Height: | Size: 712 B |
2000
positions/src/main/assets/data2k
Normal file
1000
positions/src/main/assets/datab
Normal file
9162
positions/src/main/assets/gltf-BrainStem/BrainStem.gltf
Normal file
BIN
positions/src/main/assets/gltf-BrainStem/BrainStem0.bin
Normal file
BIN
positions/src/main/assets/groundoverlay.jpg
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
positions/src/main/assets/gugong.jpg
Normal file
|
After Width: | Height: | Size: 49 KiB |
11671
positions/src/main/assets/honeycomb.txt
Normal file
2
positions/src/main/assets/trailData.dat
Normal file
BIN
positions/src/main/java/.DS_Store
vendored
Normal file
29
positions/src/main/java/cc/winboll/studio/positions/App.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package cc.winboll.studio.positions;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@QQ.COM
|
||||
* @Date 2024/12/08 15:10:51
|
||||
* @Describe 全局应用类
|
||||
*/
|
||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libapputils.app.WinBollActivityManager;
|
||||
|
||||
public class App extends GlobalApplication {
|
||||
|
||||
public static final String TAG = "App";
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
// 必须在调用基类前设置应用调试标志,
|
||||
// 这样可以预先设置日志与数据的存储根目录。
|
||||
setIsDebuging(this, BuildConfig.DEBUG);
|
||||
super.onCreate();
|
||||
// 设置 WinBoll 应用 UI 类型
|
||||
WinBollActivityManager.getInstance(this).setWinBollUI_TYPE(WinBollActivityManager.WinBollUI_TYPE.Aplication);
|
||||
|
||||
|
||||
LogUtils.d(TAG, "onCreate");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,394 @@
|
||||
package cc.winboll.studio.positions;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.telecom.TelecomManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Toast;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.LogView;
|
||||
import cc.winboll.studio.libapputils.app.IWinBollActivity;
|
||||
import cc.winboll.studio.libapputils.app.WinBollActivityManager;
|
||||
import cc.winboll.studio.libapputils.bean.APPInfo;
|
||||
import cc.winboll.studio.libapputils.view.YesNoAlertDialog;
|
||||
import cc.winboll.studio.positions.R;
|
||||
import com.tencent.map.vector.demo.DemoMainActivity;
|
||||
import cc.winboll.studio.positions.activities.SettingsActivity;
|
||||
import cc.winboll.studio.positions.adapters.MyPagerAdapter;
|
||||
import cc.winboll.studio.positions.beans.MainServiceBean;
|
||||
import cc.winboll.studio.positions.services.MainService;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.tencent.map.vector.demo.AbsListActivity;
|
||||
import com.tencent.map.vector.demo.AbsActivity;
|
||||
|
||||
final public class MainSimpleActivity extends AbsActivity implements IWinBollActivity, ViewPager.OnPageChangeListener, View.OnClickListener {
|
||||
|
||||
public static final String TAG = "MainActivity";
|
||||
|
||||
public static final int REQUEST_HOME_ACTIVITY = 0;
|
||||
public static final int REQUEST_ABOUT_ACTIVITY = 1;
|
||||
|
||||
public static final String ACTION_SOS = "cc.winboll.studio.libappbase.WinBoll.ACTION_SOS";
|
||||
|
||||
LogView mLogView;
|
||||
Toolbar mToolbar;
|
||||
CheckBox cbMainService;
|
||||
MainServiceBean mMainServiceBean;
|
||||
ViewPager viewPager;
|
||||
private List<View> views; //用来存放放进ViewPager里面的布局
|
||||
//实例化存储imageView(导航原点)的集合
|
||||
ImageView[] imageViews;
|
||||
//MyPagerAdapter adapter;//适配器
|
||||
MyPagerAdapter pagerAdapter;
|
||||
LinearLayout linearLayout;//下标所在在LinearLayout布局里
|
||||
int currentPoint = 0;//当前被选中中页面的下标
|
||||
|
||||
private static final int DIALER_REQUEST_CODE = 1;
|
||||
|
||||
@Override
|
||||
public AppCompatActivity getActivity() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public APPInfo getAppInfo() {
|
||||
// String szBranchName = "contacts";
|
||||
//
|
||||
// APPInfo appInfo = AboutActivityFactory.buildDefaultAPPInfo();
|
||||
// appInfo.setAppName("Contacts");
|
||||
// appInfo.setAppIcon(cc.winboll.studio.libapputils.R.drawable.ic_winboll);
|
||||
// appInfo.setAppDescription("Contacts Description");
|
||||
// appInfo.setAppGitName("APP");
|
||||
// appInfo.setAppGitOwner("Studio");
|
||||
// appInfo.setAppGitAPPBranch(szBranchName);
|
||||
// appInfo.setAppGitAPPSubProjectFolder(szBranchName);
|
||||
// appInfo.setAppHomePage("https://www.winboll.cc/studio/details.php?app=Contacts");
|
||||
// appInfo.setAppAPKName("Contacts");
|
||||
// appInfo.setAppAPKFolderName("Contacts");
|
||||
// return appInfo;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
// 接收并处理 Intent 数据,函数 Intent 处理接收就直接返回
|
||||
//if (prosessIntents(getIntent())) return;
|
||||
// 以下正常创建主窗口
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
// 初始化工具栏
|
||||
mToolbar = findViewById(R.id.activitymainToolbar1);
|
||||
setSupportActionBar(mToolbar);
|
||||
if (isEnableDisplayHomeAsUp()) {
|
||||
// 显示后退按钮
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
getSupportActionBar().setSubtitle(getTag());
|
||||
|
||||
initData();
|
||||
initView();
|
||||
//initPoint();//调用初始化导航原点的方法
|
||||
viewPager.addOnPageChangeListener(this);//滑动事件
|
||||
|
||||
ViewPager viewPager = findViewById(R.id.activitymainViewPager1);
|
||||
MyPagerAdapter pagerAdapter = new MyPagerAdapter(getSupportFragmentManager());
|
||||
viewPager.setAdapter(pagerAdapter);
|
||||
TabLayout tabLayout = findViewById(R.id.activitymainTabLayout1);
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
|
||||
// mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
|
||||
// if (mMainServiceBean == null) {
|
||||
// mMainServiceBean = new MainServiceBean();
|
||||
// }
|
||||
// cbMainService = findViewById(R.id.activitymainCheckBox1);
|
||||
// cbMainService.setChecked(mMainServiceBean.isEnable());
|
||||
// cbMainService.setOnClickListener(new View.OnClickListener(){
|
||||
// @Override
|
||||
// public void onClick(View view) {
|
||||
// if (cbMainService.isChecked()) {
|
||||
// MainService.startMainService(MainActivity.this);
|
||||
// } else {
|
||||
// MainService.stopMainService(MainActivity.this);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
MainService.startMainService(Main2Activity.this);
|
||||
}
|
||||
|
||||
//初始化view,即显示的图片
|
||||
void initView() {
|
||||
viewPager = findViewById(R.id.activitymainViewPager1);
|
||||
pagerAdapter = new MyPagerAdapter(getSupportFragmentManager());
|
||||
viewPager.setAdapter(pagerAdapter);
|
||||
//adapter = new MyPagerAdapter(views);
|
||||
//viewPager = findViewById(R.id.activitymainViewPager1);
|
||||
//viewPager.setAdapter(adapter);
|
||||
//linearLayout = findViewById(R.id.activitymainLinearLayout1);
|
||||
//initPoint();//初始化页面下方的点
|
||||
viewPager.setOnPageChangeListener(this);
|
||||
|
||||
}
|
||||
|
||||
//初始化所要显示的布局
|
||||
void initData() {
|
||||
ViewPager viewPager = findViewById(R.id.activitymainViewPager1);
|
||||
LayoutInflater inflater = LayoutInflater.from(getActivity());
|
||||
View view1 = inflater.inflate(R.layout.fragment_gms, viewPager, false);
|
||||
View view2 = inflater.inflate(R.layout.fragment_contacts, viewPager, false);
|
||||
View view3 = inflater.inflate(R.layout.fragment_log, viewPager, false);
|
||||
|
||||
views = new ArrayList<>();
|
||||
views.add(view1);
|
||||
views.add(view2);
|
||||
views.add(view3);
|
||||
}
|
||||
|
||||
// void initPoint() {
|
||||
// imageViews = new ImageView[5];//实例化5个图片
|
||||
// for (int i = 0; i < linearLayout.getChildCount(); i++) {
|
||||
// imageViews[i] = (ImageView) linearLayout.getChildAt(i);
|
||||
// imageViews[i].setImageResource(R.drawable.ic_launcher);
|
||||
// imageViews[i].setOnClickListener(this);//点击导航点,即可跳转
|
||||
// imageViews[i].setTag(i);//重复利用实例化的对象
|
||||
// }
|
||||
// currentPoint = 0;//默认第一个坐标
|
||||
// imageViews[currentPoint].setImageResource(R.drawable.ic_launcher);
|
||||
// }
|
||||
|
||||
//OnPageChangeListener接口要实现的三个方法
|
||||
/* onPageScrollStateChanged(int state)
|
||||
此方法是在状态改变的时候调用,其中state这个参数有三种状态:
|
||||
SCROLL_STATE_DRAGGING(1)表示用户手指“按在屏幕上并且开始拖动”的状态
|
||||
(手指按下但是还没有拖动的时候还不是这个状态,只有按下并且手指开始拖动后log才打出。)
|
||||
SCROLL_STATE_IDLE(0)滑动动画做完的状态。
|
||||
SCROLL_STATE_SETTLING(2)在“手指离开屏幕”的状态。*/
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
/* onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
|
||||
当页面在滑动的时候会调用此方法,在滑动被停止之前,此方法回一直得到调用。其中三个参数的含义分别为:
|
||||
|
||||
position :当前页面,即你点击滑动的页面(从A滑B,则是A页面的position。
|
||||
positionOffset:当前页面偏移的百分比
|
||||
positionOffsetPixels:当前页面偏移的像素位置*/
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
}
|
||||
/* onPageSelected(int position)
|
||||
此方法是页面滑动完后得到调用,position是你当前选中的页面的Position(位置编号)
|
||||
(从A滑动到B,就是B的position)*/
|
||||
public void onPageSelected(int position) {
|
||||
|
||||
// ImageView preView = imageViews[currentPoint];
|
||||
// preView.setImageResource(R.drawable.ic_launcher);
|
||||
// ImageView currView = imageViews[position];
|
||||
// currView.setImageResource(R.drawable.ic_launcher);
|
||||
// currentPoint = position;
|
||||
}
|
||||
|
||||
//小圆点点击事件
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// TODO Auto-generated method stub
|
||||
//通过getTag(),可以判断是哪个控件
|
||||
// int i = (Integer) v.getTag();
|
||||
// viewPager.setCurrentItem(i);//直接跳转到某一个页面的情况
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostCreate(Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
//setSubTitle("");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
LogUtils.d(TAG, "onDestroy() SOS");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// 处理传入的 Intent 数据
|
||||
//
|
||||
// boolean prosessIntents(Intent intent) {
|
||||
// if (intent == null
|
||||
// || intent.getAction() == null
|
||||
// || intent.getAction().equals(""))
|
||||
// return false;
|
||||
//
|
||||
// if (intent.getAction().equals(StringToQrCodeView.ACTION_UNITTEST_QRCODE)) {
|
||||
// try {
|
||||
// WinBollActivity clazzActivity = UnitTestActivity.class.newInstance();
|
||||
// String tag = clazzActivity.getTag();
|
||||
// LogUtils.d(TAG, "String tag = clazzActivity.getTag(); tag " + tag);
|
||||
// Intent subIntent = new Intent(this, UnitTestActivity.class);
|
||||
// subIntent.setAction(intent.getAction());
|
||||
// File file = new File(getCacheDir(), UUID.randomUUID().toString());
|
||||
// //取出文件uri
|
||||
// Uri uri = intent.getData();
|
||||
// if (uri == null) {
|
||||
// uri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
|
||||
// }
|
||||
// //获取文件真实地址
|
||||
// String szSrcPath = UriUtils.getFileFromUri(getApplication(), uri);
|
||||
// if (TextUtils.isEmpty(szSrcPath)) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// Files.copy(Paths.get(szSrcPath), Paths.get(file.getPath()));
|
||||
// //startWinBollActivity(subIntent, tag);
|
||||
// WinBollActivityManager.getInstance(this).startWinBollActivity(this, subIntent, UnitTestActivity.class);
|
||||
// } catch (IllegalAccessException | InstantiationException | IOException e) {
|
||||
// LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
// // 函数处理异常返回失败
|
||||
// return false;
|
||||
// }
|
||||
// } else {
|
||||
// LogUtils.d(TAG, "prosessIntents|" + intent.getAction() + "|yet");
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public String getTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Toolbar initToolBar() {
|
||||
return findViewById(R.id.activitymainToolbar1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAddWinBollToolBar() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnableDisplayHomeAsUp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
exit();
|
||||
}
|
||||
|
||||
void exit() {
|
||||
YesNoAlertDialog.OnDialogResultListener listener = new YesNoAlertDialog.OnDialogResultListener(){
|
||||
|
||||
@Override
|
||||
public void onYes() {
|
||||
WinBollActivityManager.getInstance(getApplicationContext()).finishAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNo() {
|
||||
}
|
||||
};
|
||||
YesNoAlertDialog.show(this, "[ " + getString(R.string.app_name) + " ]", "Exit(Yes/No).\nIs close all activity?", listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.toolbar_main, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.item_settings) {
|
||||
Intent intent = new Intent(this, SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
//WinBollActivityManager.getInstance(this).startWinBollActivity(this, CallActivity.class);
|
||||
} else if (item.getItemId() == R.id.item_demomain) {
|
||||
Intent intent = new Intent(this, com.tencent.map.vector.demo.DemoMainActivity.class);
|
||||
startActivity(intent);
|
||||
//WinBollActivityManager.getInstance(this).startWinBollActivity(this, CallActivity.class);
|
||||
}
|
||||
// } else
|
||||
// if (item.getItemId() == R.id.item_exit) {
|
||||
// exit();
|
||||
// return true;
|
||||
// }
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
/**
|
||||
* Android M 及以上检查是否是系统默认电话应用
|
||||
*/
|
||||
public boolean isDefaultPhoneCallApp() {
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
TelecomManager manger = (TelecomManager) getSystemService(TELECOM_SERVICE);
|
||||
if (manger != null && manger.getDefaultDialerPackage() != null) {
|
||||
return manger.getDefaultDialerPackage().equals(getPackageName());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isServiceRunning(Class<?> serviceClass) {
|
||||
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
|
||||
if (manager == null) return false;
|
||||
|
||||
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(
|
||||
Integer.MAX_VALUE)) {
|
||||
if (serviceClass.getName().equals(service.service.getClassName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
// switch (resultCode) {
|
||||
// case REQUEST_HOME_ACTIVITY : {
|
||||
// LogUtils.d(TAG, "REQUEST_HOME_ACTIVITY");
|
||||
// break;
|
||||
// }
|
||||
// case REQUEST_ABOUT_ACTIVITY : {
|
||||
// LogUtils.d(TAG, "REQUEST_ABOUT_ACTIVITY");
|
||||
// break;
|
||||
// }
|
||||
// default : {
|
||||
// super.onActivityResult(requestCode, resultCode, data);
|
||||
// }
|
||||
// }
|
||||
if (requestCode == DIALER_REQUEST_CODE) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
Toast.makeText(Main2Activity.this, getString(R.string.app_name) + " 已成为默认电话应用",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,470 @@
|
||||
package cc.winboll.studio.positions;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/24 11:05:49
|
||||
*/
|
||||
import android.Manifest;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Matrix;
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import cc.winboll.studio.libappbase.LogView;
|
||||
import cc.winboll.studio.positions.R;
|
||||
import cc.winboll.studio.positions.activities.SettingsActivity;
|
||||
import cc.winboll.studio.positions.activities.TestMapViewActivity;
|
||||
import cc.winboll.studio.positions.utils.LocationFileStorage;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.tencent.map.geolocation.TencentLocation;
|
||||
import com.tencent.map.geolocation.TencentLocationListener;
|
||||
import com.tencent.map.geolocation.TencentLocationManager;
|
||||
import com.tencent.map.geolocation.TencentLocationRequest;
|
||||
import com.tencent.tencentmap.mapsdk.maps.CameraUpdate;
|
||||
import com.tencent.tencentmap.mapsdk.maps.CameraUpdateFactory;
|
||||
import com.tencent.tencentmap.mapsdk.maps.LocationSource;
|
||||
import com.tencent.tencentmap.mapsdk.maps.TencentMap;
|
||||
import com.tencent.tencentmap.mapsdk.maps.TencentMapInitializer;
|
||||
import com.tencent.tencentmap.mapsdk.maps.TextureMapView;
|
||||
import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptor;
|
||||
import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptorFactory;
|
||||
import com.tencent.tencentmap.mapsdk.maps.model.CameraPosition;
|
||||
import com.tencent.tencentmap.mapsdk.maps.model.LatLng;
|
||||
import com.tencent.tencentmap.mapsdk.maps.model.Marker;
|
||||
import com.tencent.tencentmap.mapsdk.maps.model.MarkerOptions;
|
||||
import com.tencent.tencentmap.mapsdk.maps.model.MyLocationStyle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import pub.devrel.easypermissions.EasyPermissions;
|
||||
import cc.winboll.studio.positions.beans.LocationJson;
|
||||
|
||||
public class MainSimpleActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks,LocationSource, TencentLocationListener {
|
||||
|
||||
public static final String TAG ="MainSimpleActivity";
|
||||
|
||||
private static final int PERMISSION_REQUEST_CODE = 1;
|
||||
|
||||
Toolbar mToolbar;
|
||||
private TextureMapView mapView;
|
||||
protected TencentMap tencentMap;
|
||||
TextView mtvInfo;
|
||||
private LocationSource.OnLocationChangedListener locationChangedListener;
|
||||
|
||||
private TencentLocationManager locationManager;
|
||||
private TencentLocationRequest locationRequest;
|
||||
private MyLocationStyle locationStyle;
|
||||
ArrayList<LocationJson> locationJsonList;
|
||||
LogView mLogView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main_simple);
|
||||
|
||||
locationJsonList = new ArrayList<LocationJson>();
|
||||
|
||||
// 初始化工具栏
|
||||
mToolbar = findViewById(R.id.activitymainToolbar1);
|
||||
setSupportActionBar(mToolbar);
|
||||
getSupportActionBar().setSubtitle(TAG);
|
||||
|
||||
mLogView = findViewById(R.id.logview);
|
||||
mLogView.start();
|
||||
|
||||
TencentMapInitializer.setAgreePrivacy(this, true);
|
||||
TencentMapInitializer.start(this);
|
||||
TencentLocationManager.setUserAgreePrivacy(true);
|
||||
|
||||
|
||||
mapView = findViewById(R.id.mapview);
|
||||
mapView.setOpaque(false);
|
||||
//创建tencentMap地图对象,可以完成对地图的几乎所有操作
|
||||
tencentMap = mapView.getMap();
|
||||
|
||||
FloatingActionButton fab = findViewById(R.id.fab);
|
||||
fab.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Snackbar.make(view, "点击了悬浮按钮", Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
|
||||
mtvInfo = findViewById(R.id.tv_info);
|
||||
|
||||
checkLocationPermission();
|
||||
|
||||
//设置显示定位的图标
|
||||
TencentLocationManager.setUserAgreePrivacy(true);
|
||||
//建立定位
|
||||
//initLocation();
|
||||
//对地图操作类进行操作
|
||||
CameraUpdate cameraSigma =
|
||||
CameraUpdateFactory.newCameraPosition(new CameraPosition(
|
||||
new LatLng(22.984066, 116.307548),
|
||||
15,
|
||||
0f,
|
||||
0f));
|
||||
//移动地图
|
||||
tencentMap.moveCamera(cameraSigma);
|
||||
|
||||
// 设置地图点击监听
|
||||
tencentMap.setOnMapClickListener(new TencentMap.OnMapClickListener(){
|
||||
|
||||
@Override
|
||||
public void onMapClick(com.tencent.tencentmap.mapsdk.maps.model.LatLng latLng) {
|
||||
//创建Marker对象之前,设置属性
|
||||
//LatLng position = new LatLng(40.011313,116.391907);
|
||||
BitmapDescriptor custom = BitmapDescriptorFactory.fromResource(R.drawable.marker);
|
||||
Location location = createLocationFromLatLng(latLng);
|
||||
addLocationJson(location);
|
||||
Marker mCustomMarker = tencentMap.addMarker(new MarkerOptions(latLng));
|
||||
|
||||
//创建Marker对象之后,修改属性
|
||||
// Animation animation = new AlphaAnimation(0.7f, 0f);
|
||||
// animation.setDuration(2000);
|
||||
// mCustomMarker.setAnimation(animation);
|
||||
// mCustomMarker.startAnimation();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
void loadLocations() {
|
||||
// 存储位置数据
|
||||
// Location location = new Location("gps");
|
||||
// location.setLatitude(22.984066);
|
||||
// location.setLongitude(116.307548);
|
||||
// location.setTime(System.currentTimeMillis());
|
||||
//
|
||||
// // 方式1:保存到文件
|
||||
// List<Location> locations = new ArrayList<>();
|
||||
// locations.add(location);
|
||||
// LocationFileStorage.saveToFile(this, locations);
|
||||
|
||||
// 读取数据
|
||||
locationJsonList = LocationFileStorage.loadFromFile(this);
|
||||
|
||||
for (LocationJson lj : locationJsonList) {
|
||||
tencentMap.addMarker(new MarkerOptions(toTencentLatLng(lj.toLocation())));
|
||||
//LogUtils.d("Location", "Lat: " + loc.getLatitude() + ", Lng: " + loc.getLongitude());
|
||||
}
|
||||
}
|
||||
|
||||
void addLocationJson(Location location) {
|
||||
// 存储位置数据
|
||||
// Location location = new Location("gps");
|
||||
// location.setLatitude(22.984066);
|
||||
// location.setLongitude(116.307548);
|
||||
// location.setTime(System.currentTimeMillis());
|
||||
|
||||
// 方式1:保存到文件
|
||||
//List<Location> locations = new ArrayList<>();
|
||||
locationJsonList.add(new LocationJson(location));
|
||||
LocationFileStorage.saveToFile(this, locationJsonList);
|
||||
|
||||
// 读取数据
|
||||
// List<Location> loaded = LocationFileStorage.loadFromFile(this);
|
||||
// for (Location loc : loaded) {
|
||||
// tencentMap.addMarker(new MarkerOptions(toTencentLatLng(loc)));
|
||||
// //LogUtils.d("Location", "Lat: " + loc.getLatitude() + ", Lng: " + loc.getLongitude());
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 创建Location对象方法
|
||||
private Location createLocationFromLatLng(LatLng latLng) {
|
||||
Location location = new Location("tencent_map_manual");
|
||||
|
||||
// 设置基础坐标
|
||||
location.setLatitude(latLng.getLatitude());
|
||||
location.setLongitude(latLng.getLongitude());
|
||||
|
||||
// 设置必要元数据
|
||||
location.setTime(System.currentTimeMillis());
|
||||
location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
|
||||
location.setAccuracy(5.0f); // 手动点击精度设为5米
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
|
||||
public LatLng toTencentLatLng(Location location) {
|
||||
return new LatLng(
|
||||
location.getLatitude(),
|
||||
location.getLongitude()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// 添加标记方法
|
||||
private void addMarker(LatLng latLng) {
|
||||
tencentMap.clearAllOverlays();
|
||||
MarkerOptions options = new MarkerOptions(latLng)
|
||||
.icon(BitmapDescriptorFactory.defaultMarker())
|
||||
.title("点击保存");
|
||||
tencentMap.addMarker(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostCreate(Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
// LatLng center = new LatLng(39.904556, 116.427242);
|
||||
// tencentMap.moveCamera(
|
||||
// CameraUpdateFactory.newLatLngZoom(center, 13f) // 注意 13 → 13f
|
||||
// );
|
||||
loadLocations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.toolbar_main, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.item_settings) {
|
||||
Intent intent = new Intent(this, SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
//WinBollActivityManager.getInstance(this).startWinBollActivity(this, CallActivity.class);
|
||||
} else if (item.getItemId() == R.id.item_demomain) {
|
||||
Intent intent = new Intent(this, com.tencent.map.vector.demo.DemoMainActivity.class);
|
||||
startActivity(intent);
|
||||
//WinBollActivityManager.getInstance(this).startWinBollActivity(this, CallActivity.class);
|
||||
} else if (item.getItemId() == R.id.item_testmapview) {
|
||||
Intent intent = new Intent(this, TestMapViewActivity.class);
|
||||
startActivity(intent);
|
||||
//WinBollActivityManager.getInstance(this).startWinBollActivity(this, CallActivity.class);
|
||||
}
|
||||
// } else
|
||||
// if (item.getItemId() == R.id.item_exit) {
|
||||
// exit();
|
||||
// return true;
|
||||
// }
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* mapview的生命周期管理
|
||||
*/
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestart() {
|
||||
super.onRestart();
|
||||
mapView.onRestart();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 设置定位图标样式
|
||||
*/
|
||||
private void setLocMarkerStyle() {
|
||||
locationStyle = new MyLocationStyle();
|
||||
//创建图标
|
||||
BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(getBitMap(R.drawable.marker));
|
||||
locationStyle.icon(bitmapDescriptor);
|
||||
//设置定位圆形区域的边框宽度
|
||||
locationStyle.strokeWidth(3);
|
||||
//设置圆区域的颜色
|
||||
locationStyle.fillColor(R.color.style);
|
||||
|
||||
tencentMap.setMyLocationStyle(locationStyle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Bitmap getBitMap(int resourceId) {
|
||||
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resourceId);
|
||||
int width = bitmap.getWidth();
|
||||
int height = bitmap.getHeight();
|
||||
int newWidth = 55;
|
||||
int newHeight = 55;
|
||||
float widthScale = ((float)newWidth) / width;
|
||||
float heightScale = ((float)newHeight) / height;
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.postScale(widthScale, heightScale);
|
||||
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 定位的一些初始化设置
|
||||
*/
|
||||
private void initLocation() {
|
||||
//用于访问腾讯定位服务的类, 周期性向客户端提供位置更新
|
||||
locationManager = TencentLocationManager.getInstance(this);
|
||||
//设置坐标系
|
||||
locationManager.setCoordinateType(TencentLocationManager.COORDINATE_TYPE_GCJ02);
|
||||
//创建定位请求
|
||||
locationRequest = TencentLocationRequest.create();
|
||||
//设置定位周期(位置监听器回调周期)为3s
|
||||
locationRequest.setInterval(3000);
|
||||
|
||||
//地图上设置定位数据源
|
||||
tencentMap.setLocationSource(this);
|
||||
//设置当前位置可见
|
||||
tencentMap.setMyLocationEnabled(true);
|
||||
//设置定位图标样式
|
||||
setLocMarkerStyle();
|
||||
// locationStyle = locationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);
|
||||
tencentMap.setMyLocationStyle(locationStyle);
|
||||
}
|
||||
/**
|
||||
* 实现位置监听
|
||||
* @param tencentLocation
|
||||
* @param i
|
||||
* @param s
|
||||
*/
|
||||
@Override
|
||||
public void onLocationChanged(TencentLocation tencentLocation, int i, String s) {
|
||||
|
||||
if (i == TencentLocation.ERROR_OK && locationChangedListener != null) {
|
||||
final Location location = new Location(tencentLocation.getProvider());
|
||||
//设置经纬度以及精度
|
||||
location.setLatitude(tencentLocation.getLatitude());
|
||||
location.setLongitude(tencentLocation.getLongitude());
|
||||
location.setAccuracy(tencentLocation.getAccuracy());
|
||||
locationChangedListener.onLocationChanged(location);
|
||||
|
||||
//显示回调的实时位置信息
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Rules.getEffectInfo(location);
|
||||
// double distance = DistanceUtils.getDistance(
|
||||
// locationA.getLatitude(),
|
||||
// locationA.getLongitude(),
|
||||
// locationB.getLatitude(),
|
||||
// locationB.getLongitude()
|
||||
// );
|
||||
mtvInfo.setText(String.format("\n%f %f", location.getLatitude(), location.getLongitude()));
|
||||
//打印tencentLocation的json字符串
|
||||
// Toast.makeText(getApplicationContext(), new Gson().toJson(location), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusUpdate(String s, int i, String s1) {
|
||||
//GPS, WiFi, Radio 等状态发生变化
|
||||
Log.v("State changed", s + "===" + s1);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void activate(OnLocationChangedListener onLocationChangedListener) {
|
||||
locationChangedListener = onLocationChangedListener;
|
||||
|
||||
int err = locationManager.requestLocationUpdates(locationRequest, this, Looper.myLooper());
|
||||
switch (err) {
|
||||
case 1:
|
||||
Toast.makeText(this, "设备缺少使用腾讯定位服务需要的基本条件", Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
case 2:
|
||||
Toast.makeText(this, "manifest 中配置的 key 不正确", Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
case 3:
|
||||
Toast.makeText(this, "自动加载libtencentloc.so失败", Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
locationManager.removeUpdates(this);
|
||||
locationManager = null;
|
||||
locationRequest = null;
|
||||
locationChangedListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
|
||||
Log.e("location quest: ", "success");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
|
||||
Log.e("location quest: ", "failed");
|
||||
}
|
||||
|
||||
private void checkLocationPermission() {
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
|
||||
|| ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(this,
|
||||
new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
|
||||
PERMISSION_REQUEST_CODE);
|
||||
} else {
|
||||
// 权限已授予,可进行定位操作
|
||||
//startLocationUpdates();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (requestCode == PERMISSION_REQUEST_CODE) {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
//startLocationUpdates();
|
||||
} else {
|
||||
// 用户拒绝了权限请求
|
||||
Toast.makeText(this, "请授予定位权限", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package cc.winboll.studio.positions.activities;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/22 02:01:44
|
||||
*/
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Button;
|
||||
import android.widget.FrameLayout;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import cc.winboll.studio.positions.R;
|
||||
import cc.winboll.studio.positions.views.GridMapView;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.View;
|
||||
|
||||
public class GridMapActivity extends AppCompatActivity {
|
||||
|
||||
GridMapView gridMap;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_gridmap);
|
||||
|
||||
// 初始化视图
|
||||
GridMapView mapView = (GridMapView) findViewById(R.id.map_view);
|
||||
|
||||
// 设置网格参数
|
||||
mapView.setGridParameters(10000f, 10000f, 10f);
|
||||
|
||||
// 初始化显示区域(中心点400,300,显示范围2000x200)
|
||||
mapView.initViewport(5000f, 5000f, 1000f, 1000f);
|
||||
|
||||
// 绘制图形
|
||||
mapView.drawPoint(5000f, 5000f, Color.RED, 8f);
|
||||
mapView.drawCircle(5000f, 5000f, 50f, Color.BLUE, 8f);
|
||||
mapView.drawLine(4975f, 4975f, 5025f, 5025f, Color.GREEN, 2f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package cc.winboll.studio.positions.activities;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/21 05:37:42
|
||||
*/
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import cc.winboll.studio.positions.R;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import java.lang.reflect.Field;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import cc.winboll.studio.libappbase.IWinBollActivity;
|
||||
import cc.winboll.studio.libappbase.bean.APPInfo;
|
||||
|
||||
public class SettingsActivity extends AppCompatActivity implements IWinBollActivity {
|
||||
|
||||
public static final String TAG = "SettingsActivity";
|
||||
|
||||
Toolbar mToolbar;
|
||||
|
||||
@Override
|
||||
public APPInfo getAppInfo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppCompatActivity getActivity() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Toolbar initToolBar() {
|
||||
return findViewById(R.id.activitymainToolbar1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAddWinBollToolBar() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnableDisplayHomeAsUp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_settings);
|
||||
|
||||
// 初始化工具栏
|
||||
mToolbar = findViewById(R.id.activitymainToolbar1);
|
||||
setSupportActionBar(mToolbar);
|
||||
if (isEnableDisplayHomeAsUp()) {
|
||||
// 显示后退按钮
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
getSupportActionBar().setSubtitle(getTag());
|
||||
|
||||
}
|
||||
|
||||
public void onDefaultPhone(View view) {
|
||||
Intent intent = new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
|
||||
startActivity(intent);
|
||||
}
|
||||
public void onCanDrawOverlays(View view) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
||||
&& !Settings.canDrawOverlays(this)) {
|
||||
// 请求 悬浮框 权限
|
||||
askForDrawOverlay();
|
||||
} else {
|
||||
ToastUtils.show("悬浮窗已开启");
|
||||
}
|
||||
}
|
||||
|
||||
private void askForDrawOverlay() {
|
||||
AlertDialog alertDialog = new AlertDialog.Builder(this)
|
||||
.setTitle("允许显示悬浮框")
|
||||
.setMessage("为了使电话监听服务正常工作,请允许这项权限")
|
||||
.setPositiveButton("去设置", new DialogInterface.OnClickListener(){
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
openDrawOverlaySettings();
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.setNegativeButton("稍后再说", new DialogInterface.OnClickListener(){
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.create();
|
||||
|
||||
//noinspection ConstantConditions
|
||||
alertDialog.getWindow().setFlags(
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
|
||||
alertDialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转悬浮窗管理设置界面
|
||||
*/
|
||||
private void openDrawOverlaySettings() {
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
// Android M 以上引导用户去系统设置中打开允许悬浮窗
|
||||
// 使用反射是为了用尽可能少的代码保证在大部分机型上都可用
|
||||
try {
|
||||
Context context = this;
|
||||
Class clazz = Settings.class;
|
||||
Field field = clazz.getDeclaredField("ACTION_MANAGE_OVERLAY_PERMISSION");
|
||||
Intent intent = new Intent(field.get(null).toString());
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.setData(Uri.parse("package:" + context.getPackageName()));
|
||||
context.startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
Toast.makeText(this, "请在悬浮窗管理中打开权限", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package cc.winboll.studio.positions.activities;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/24 12:14:04
|
||||
*/
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import cc.winboll.studio.positions.R;
|
||||
import com.tencent.map.vector.demo.heatoverlay.ScatterPlotOverlayActivity;
|
||||
import com.tencent.tencentmap.mapsdk.maps.MapView;
|
||||
import com.tencent.tencentmap.mapsdk.maps.TencentMap;
|
||||
import com.tencent.tencentmap.mapsdk.maps.TencentMapOptions;
|
||||
import com.tencent.tencentmap.mapsdk.maps.TextureMapView;
|
||||
import com.tencent.tencentmap.mapsdk.maps.model.LatLng;
|
||||
|
||||
public class TestMapViewActivity extends AppCompatActivity {
|
||||
|
||||
public static final String TAG = "TestMapViewActivity";
|
||||
|
||||
/**
|
||||
* 由于SDK并没有提供用于MapView管理地图生命周期的Activity
|
||||
* 因此需要用户继承Activity后管理地图的生命周期,防止内存泄露
|
||||
*/
|
||||
|
||||
private TextureMapView mapView;
|
||||
protected TencentMap tencentMap;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_testmapview);
|
||||
|
||||
mapView = findViewById(R.id.mapview);
|
||||
mapView.setOpaque(false);
|
||||
//创建tencentMap地图对象,可以完成对地图的几乎所有操作
|
||||
tencentMap = mapView.getMap();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* mapview的生命周期管理
|
||||
*/
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestart() {
|
||||
super.onRestart();
|
||||
mapView.onRestart();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package cc.winboll.studio.positions.adapters;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/20 13:33:04
|
||||
* @Describe MyPagerAdapter
|
||||
*/
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import cc.winboll.studio.positions.fragments.GmsFragment;
|
||||
import cc.winboll.studio.positions.fragments.ContactsFragment;
|
||||
import cc.winboll.studio.positions.fragments.LogFragment;
|
||||
|
||||
public class MyPagerAdapter extends FragmentPagerAdapter {
|
||||
public static final String TAG = "MyPagerAdapter";
|
||||
|
||||
private static final int PAGE_COUNT = 3;
|
||||
|
||||
public MyPagerAdapter(@NonNull FragmentManager fm) {
|
||||
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
if(position == 1) {
|
||||
return ContactsFragment.newInstance(position);
|
||||
} else if(position == 2) {
|
||||
return LogFragment.newInstance(position);
|
||||
} else {
|
||||
return GmsFragment.newInstance(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return PAGE_COUNT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
package cc.winboll.studio.positions.beans;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/25 02:58:33
|
||||
* @Describe LocationJson
|
||||
*/
|
||||
|
||||
import android.util.JsonReader;
|
||||
import android.util.JsonWriter;
|
||||
import cc.winboll.studio.libappbase.BaseBean;
|
||||
import java.io.IOException;
|
||||
import android.location.Location;
|
||||
|
||||
public class LocationJson extends BaseBean {
|
||||
|
||||
public static final String TAG = "LocationJson";
|
||||
|
||||
private double latitude;
|
||||
private double longitude;
|
||||
private long timestamp;
|
||||
private double accuracy;
|
||||
private String provider;
|
||||
|
||||
public LocationJson() {
|
||||
this.latitude = 0.0f;
|
||||
this.longitude = 0.0f;
|
||||
this.timestamp = 0L;
|
||||
this.accuracy = 0.0f;
|
||||
this.provider = "";
|
||||
}
|
||||
|
||||
public LocationJson(Location location) {
|
||||
this.latitude = location.getLatitude();
|
||||
this.longitude = location.getLongitude();
|
||||
this.timestamp = location.getTime();
|
||||
this.accuracy = location.getAccuracy();
|
||||
this.provider = location.getProvider();
|
||||
}
|
||||
|
||||
public void setLatitude(double latitude) {
|
||||
this.latitude = latitude;
|
||||
}
|
||||
|
||||
public double getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
public void setLongitude(double longitude) {
|
||||
this.longitude = longitude;
|
||||
}
|
||||
|
||||
public double getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public void setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setAccuracy(double accuracy) {
|
||||
this.accuracy = accuracy;
|
||||
}
|
||||
|
||||
public double getAccuracy() {
|
||||
return accuracy;
|
||||
}
|
||||
|
||||
public void setProvider(String provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
public String getProvider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return LocationJson.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
|
||||
super.writeThisToJsonWriter(jsonWriter);
|
||||
jsonWriter.name("latitude").value(getLatitude());
|
||||
jsonWriter.name("longitude").value(getLongitude());
|
||||
jsonWriter.name("timestamp").value(getTimestamp());
|
||||
jsonWriter.name("accuracy").value(getAccuracy());
|
||||
jsonWriter.name("provider").value(getProvider());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
|
||||
if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
|
||||
if (name.equals("latitude")) {
|
||||
setLatitude(jsonReader.nextDouble());
|
||||
} else if (name.equals("longitude")) {
|
||||
setLongitude(jsonReader.nextDouble());
|
||||
} else if (name.equals("timestamp")) {
|
||||
setTimestamp(jsonReader.nextLong());
|
||||
} else if (name.equals("accuracy")) {
|
||||
setAccuracy(jsonReader.nextDouble());
|
||||
} else if (name.equals("provider")) {
|
||||
setProvider(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;
|
||||
}
|
||||
|
||||
public Location toLocation() {
|
||||
Location location = new Location(getProvider());
|
||||
location.setLatitude(getLatitude());
|
||||
location.setLongitude(getLongitude());
|
||||
location.setTime(getTimestamp());
|
||||
location.setAccuracy((float)getAccuracy());
|
||||
return location;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package cc.winboll.studio.positions.beans;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/13 07:06:13
|
||||
*/
|
||||
import android.util.JsonReader;
|
||||
import android.util.JsonWriter;
|
||||
import cc.winboll.studio.libappbase.BaseBean;
|
||||
import java.io.IOException;
|
||||
|
||||
public class MainServiceBean extends BaseBean {
|
||||
|
||||
public static final String TAG = "MainServiceBean";
|
||||
|
||||
boolean isEnable;
|
||||
|
||||
public MainServiceBean() {
|
||||
this.isEnable = false;
|
||||
}
|
||||
|
||||
public void setIsEnable(boolean isEnable) {
|
||||
this.isEnable = isEnable;
|
||||
}
|
||||
|
||||
public boolean isEnable() {
|
||||
return isEnable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MainServiceBean.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
|
||||
super.writeThisToJsonWriter(jsonWriter);
|
||||
MainServiceBean 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package cc.winboll.studio.positions.beans;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/25 01:21:17
|
||||
* @Describe 定位信息类
|
||||
*/
|
||||
public class RulsBean {
|
||||
|
||||
public static final String TAG = "LocationBean";
|
||||
|
||||
float latitude;
|
||||
float longitude;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package cc.winboll.studio.positions.fragments;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/20 12:57:50
|
||||
* @Describe 联系人
|
||||
*/
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import cc.winboll.studio.positions.R;
|
||||
|
||||
public class ContactsFragment extends Fragment {
|
||||
|
||||
public static final String TAG = "ContactsFragment";
|
||||
|
||||
private static final String ARG_PAGE = "ARG_PAGE";
|
||||
private int mPage;
|
||||
|
||||
public static ContactsFragment newInstance(int page) {
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(ARG_PAGE, page);
|
||||
ContactsFragment fragment = new ContactsFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments()!= null) {
|
||||
mPage = getArguments().getInt(ARG_PAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_contacts, container, false);
|
||||
TextView textView = view.findViewById(R.id.page_text);
|
||||
textView.setText("这是第 " + mPage + " 页");
|
||||
return view;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package cc.winboll.studio.positions.fragments;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/20 12:57:00
|
||||
* @Describe 拨号
|
||||
*/
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import cc.winboll.studio.positions.R;
|
||||
import cc.winboll.studio.libappbase.LogView;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.graphics.Color;
|
||||
import android.widget.TextView;
|
||||
import cc.winboll.studio.positions.views.GridMapView;
|
||||
import com.tencent.tencentmap.mapsdk.maps.MapView;
|
||||
import com.tencent.tencentmap.mapsdk.maps.TencentMap;
|
||||
import com.tencent.tencentmap.mapsdk.maps.TextureMapView;
|
||||
|
||||
public class GmsFragment extends Fragment {
|
||||
|
||||
public static final String TAG = "GmsFragment";
|
||||
|
||||
private static final String ARG_PAGE = "ARG_PAGE";
|
||||
private int mPage;
|
||||
private TextureMapView mapView;
|
||||
protected TencentMap tencentMap;
|
||||
|
||||
public static GmsFragment newInstance(int page) {
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(ARG_PAGE, page);
|
||||
GmsFragment fragment = new GmsFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments()!= null) {
|
||||
mPage = getArguments().getInt(ARG_PAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_gms, container, false);
|
||||
|
||||
// // 初始化视图
|
||||
// GridMapView mapView = (GridMapView) view.findViewById(R.id.map_view);
|
||||
//
|
||||
// // 设置网格参数
|
||||
// mapView.setGridParameters(10000f, 10000f, 10f);
|
||||
//
|
||||
// // 初始化显示区域(中心点400,300,显示范围2000x200)
|
||||
// mapView.initViewport(5000f, 5000f, 1000f, 1000f);
|
||||
//
|
||||
// // 绘制图形
|
||||
// mapView.drawPoint(5000f, 5000f, Color.RED, 8f);
|
||||
// mapView.drawCircle(5000f, 5000f, 50f, Color.BLUE, 8f);
|
||||
// mapView.drawLine(4975f, 4975f, 5025f, 5025f, Color.GREEN, 2f);
|
||||
|
||||
// 初始化地图视图
|
||||
mapView = view.findViewById(R.id.mapView);
|
||||
mapView.setOpaque(false);
|
||||
//创建tencentMap地图对象,可以完成对地图的几乎所有操作
|
||||
tencentMap = mapView.getMap();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* mapview的生命周期管理
|
||||
*/
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package cc.winboll.studio.positions.fragments;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/20 12:58:15
|
||||
* @Describe 应用日志
|
||||
*/
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import cc.winboll.studio.positions.R;
|
||||
import cc.winboll.studio.libappbase.LogView;
|
||||
|
||||
public class LogFragment extends Fragment {
|
||||
|
||||
public static final String TAG = "LogFragment";
|
||||
|
||||
private static final String ARG_PAGE = "ARG_PAGE";
|
||||
private int mPage;
|
||||
|
||||
public static LogFragment newInstance(int page) {
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(ARG_PAGE, page);
|
||||
LogFragment fragment = new LogFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null) {
|
||||
mPage = getArguments().getInt(ARG_PAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_log, container, false);
|
||||
LogView logView = view.findViewById(R.id.logview);
|
||||
logView.start();
|
||||
return view;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,461 @@
|
||||
package cc.winboll.studio.positions.fragments;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/25 12:44:39
|
||||
* @Describe 腾讯地图服务视图
|
||||
*/
|
||||
import android.Manifest;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Matrix;
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import cc.winboll.studio.libappbase.LogView;
|
||||
import cc.winboll.studio.positions.R;
|
||||
import cc.winboll.studio.positions.activities.SettingsActivity;
|
||||
import cc.winboll.studio.positions.activities.TestMapViewActivity;
|
||||
import cc.winboll.studio.positions.utils.LocationFileStorage;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.tencent.map.geolocation.TencentLocation;
|
||||
import com.tencent.map.geolocation.TencentLocationListener;
|
||||
import com.tencent.map.geolocation.TencentLocationManager;
|
||||
import com.tencent.map.geolocation.TencentLocationRequest;
|
||||
import com.tencent.tencentmap.mapsdk.maps.CameraUpdate;
|
||||
import com.tencent.tencentmap.mapsdk.maps.CameraUpdateFactory;
|
||||
import com.tencent.tencentmap.mapsdk.maps.LocationSource;
|
||||
import com.tencent.tencentmap.mapsdk.maps.TencentMap;
|
||||
import com.tencent.tencentmap.mapsdk.maps.TencentMapInitializer;
|
||||
import com.tencent.tencentmap.mapsdk.maps.TextureMapView;
|
||||
import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptor;
|
||||
import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptorFactory;
|
||||
import com.tencent.tencentmap.mapsdk.maps.model.CameraPosition;
|
||||
import com.tencent.tencentmap.mapsdk.maps.model.LatLng;
|
||||
import com.tencent.tencentmap.mapsdk.maps.model.Marker;
|
||||
import com.tencent.tencentmap.mapsdk.maps.model.MarkerOptions;
|
||||
import com.tencent.tencentmap.mapsdk.maps.model.MyLocationStyle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import pub.devrel.easypermissions.EasyPermissions;
|
||||
import cc.winboll.studio.positions.beans.LocationJson;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import cc.winboll.studio.positions.R;
|
||||
import cc.winboll.studio.libappbase.LogView;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.graphics.Color;
|
||||
import android.widget.TextView;
|
||||
import cc.winboll.studio.positions.views.GridMapView;
|
||||
import com.tencent.tencentmap.mapsdk.maps.MapView;
|
||||
import com.tencent.tencentmap.mapsdk.maps.TencentMap;
|
||||
import com.tencent.tencentmap.mapsdk.maps.TextureMapView;
|
||||
|
||||
public class TXMSFragment extends Fragment implements EasyPermissions.PermissionCallbacks,LocationSource, TencentLocationListener {
|
||||
|
||||
public static final String TAG = "TXMSFragment";
|
||||
|
||||
|
||||
private static final String ARG_PAGE = "ARG_PAGE";
|
||||
private int mPage;
|
||||
private TextureMapView mapView;
|
||||
protected TencentMap tencentMap;
|
||||
TextView mtvInfo;
|
||||
private LocationSource.OnLocationChangedListener locationChangedListener;
|
||||
|
||||
private TencentLocationManager locationManager;
|
||||
private TencentLocationRequest locationRequest;
|
||||
private MyLocationStyle locationStyle;
|
||||
ArrayList<LocationJson> locationJsonList;
|
||||
|
||||
public static TXMSFragment newInstance(int page) {
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(ARG_PAGE, page);
|
||||
TXMSFragment fragment = new GmsFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments()!= null) {
|
||||
mPage = getArguments().getInt(ARG_PAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View viewRoot = inflater.inflate(R.layout.fragment_gms, container, false);
|
||||
locationJsonList = new ArrayList<LocationJson>();
|
||||
|
||||
mLogView = viewRoot.findViewById(R.id.logview);
|
||||
mLogView.start();
|
||||
|
||||
TencentMapInitializer.setAgreePrivacy(this, true);
|
||||
TencentMapInitializer.start(this);
|
||||
TencentLocationManager.setUserAgreePrivacy(true);
|
||||
|
||||
|
||||
mapView = viewRoot.findViewById(R.id.mapview);
|
||||
mapView.setOpaque(false);
|
||||
//创建tencentMap地图对象,可以完成对地图的几乎所有操作
|
||||
tencentMap = mapView.getMap();
|
||||
|
||||
FloatingActionButton fab = viewRoot.findViewById(R.id.fab);
|
||||
fab.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Snackbar.make(view, "点击了悬浮按钮", Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
|
||||
mtvInfo = viewRoot.findViewById(R.id.tv_info);
|
||||
|
||||
checkLocationPermission();
|
||||
|
||||
//设置显示定位的图标
|
||||
TencentLocationManager.setUserAgreePrivacy(true);
|
||||
//建立定位
|
||||
//initLocation();
|
||||
//对地图操作类进行操作
|
||||
CameraUpdate cameraSigma =
|
||||
CameraUpdateFactory.newCameraPosition(new CameraPosition(
|
||||
new LatLng(22.984066, 116.307548),
|
||||
15,
|
||||
0f,
|
||||
0f));
|
||||
//移动地图
|
||||
tencentMap.moveCamera(cameraSigma);
|
||||
|
||||
// 设置地图点击监听
|
||||
tencentMap.setOnMapClickListener(new TencentMap.OnMapClickListener(){
|
||||
|
||||
@Override
|
||||
public void onMapClick(com.tencent.tencentmap.mapsdk.maps.model.LatLng latLng) {
|
||||
//创建Marker对象之前,设置属性
|
||||
//LatLng position = new LatLng(40.011313,116.391907);
|
||||
BitmapDescriptor custom = BitmapDescriptorFactory.fromResource(R.drawable.marker);
|
||||
Location location = createLocationFromLatLng(latLng);
|
||||
addLocationJson(location);
|
||||
Marker mCustomMarker = tencentMap.addMarker(new MarkerOptions(latLng));
|
||||
|
||||
//创建Marker对象之后,修改属性
|
||||
// Animation animation = new AlphaAnimation(0.7f, 0f);
|
||||
// animation.setDuration(2000);
|
||||
// mCustomMarker.setAnimation(animation);
|
||||
// mCustomMarker.startAnimation();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return viewRoot;
|
||||
}
|
||||
|
||||
void loadLocations() {
|
||||
// 存储位置数据
|
||||
// Location location = new Location("gps");
|
||||
// location.setLatitude(22.984066);
|
||||
// location.setLongitude(116.307548);
|
||||
// location.setTime(System.currentTimeMillis());
|
||||
//
|
||||
// // 方式1:保存到文件
|
||||
// List<Location> locations = new ArrayList<>();
|
||||
// locations.add(location);
|
||||
// LocationFileStorage.saveToFile(this, locations);
|
||||
|
||||
// 读取数据
|
||||
locationJsonList = LocationFileStorage.loadFromFile(this);
|
||||
|
||||
for (LocationJson lj : locationJsonList) {
|
||||
tencentMap.addMarker(new MarkerOptions(toTencentLatLng(lj.toLocation())));
|
||||
//LogUtils.d("Location", "Lat: " + loc.getLatitude() + ", Lng: " + loc.getLongitude());
|
||||
}
|
||||
}
|
||||
|
||||
void addLocationJson(Location location) {
|
||||
// 存储位置数据
|
||||
// Location location = new Location("gps");
|
||||
// location.setLatitude(22.984066);
|
||||
// location.setLongitude(116.307548);
|
||||
// location.setTime(System.currentTimeMillis());
|
||||
|
||||
// 方式1:保存到文件
|
||||
//List<Location> locations = new ArrayList<>();
|
||||
locationJsonList.add(new LocationJson(location));
|
||||
LocationFileStorage.saveToFile(this, locationJsonList);
|
||||
|
||||
// 读取数据
|
||||
// List<Location> loaded = LocationFileStorage.loadFromFile(this);
|
||||
// for (Location loc : loaded) {
|
||||
// tencentMap.addMarker(new MarkerOptions(toTencentLatLng(loc)));
|
||||
// //LogUtils.d("Location", "Lat: " + loc.getLatitude() + ", Lng: " + loc.getLongitude());
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 创建Location对象方法
|
||||
private Location createLocationFromLatLng(LatLng latLng) {
|
||||
Location location = new Location("tencent_map_manual");
|
||||
|
||||
// 设置基础坐标
|
||||
location.setLatitude(latLng.getLatitude());
|
||||
location.setLongitude(latLng.getLongitude());
|
||||
|
||||
// 设置必要元数据
|
||||
location.setTime(System.currentTimeMillis());
|
||||
location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
|
||||
location.setAccuracy(5.0f); // 手动点击精度设为5米
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
|
||||
public LatLng toTencentLatLng(Location location) {
|
||||
return new LatLng(
|
||||
location.getLatitude(),
|
||||
location.getLongitude()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// 添加标记方法
|
||||
private void addMarker(LatLng latLng) {
|
||||
tencentMap.clearAllOverlays();
|
||||
MarkerOptions options = new MarkerOptions(latLng)
|
||||
.icon(BitmapDescriptorFactory.defaultMarker())
|
||||
.title("点击保存");
|
||||
tencentMap.addMarker(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* mapview的生命周期管理
|
||||
*/
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
mapView.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
mapView.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onPostCreate(Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
// LatLng center = new LatLng(39.904556, 116.427242);
|
||||
// tencentMap.moveCamera(
|
||||
// CameraUpdateFactory.newLatLngZoom(center, 13f) // 注意 13 → 13f
|
||||
// );
|
||||
loadLocations();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置定位图标样式
|
||||
*/
|
||||
private void setLocMarkerStyle() {
|
||||
locationStyle = new MyLocationStyle();
|
||||
//创建图标
|
||||
BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(getBitMap(R.drawable.marker));
|
||||
locationStyle.icon(bitmapDescriptor);
|
||||
//设置定位圆形区域的边框宽度
|
||||
locationStyle.strokeWidth(3);
|
||||
//设置圆区域的颜色
|
||||
locationStyle.fillColor(R.color.style);
|
||||
|
||||
tencentMap.setMyLocationStyle(locationStyle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Bitmap getBitMap(int resourceId) {
|
||||
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resourceId);
|
||||
int width = bitmap.getWidth();
|
||||
int height = bitmap.getHeight();
|
||||
int newWidth = 55;
|
||||
int newHeight = 55;
|
||||
float widthScale = ((float)newWidth) / width;
|
||||
float heightScale = ((float)newHeight) / height;
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.postScale(widthScale, heightScale);
|
||||
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 定位的一些初始化设置
|
||||
*/
|
||||
private void initLocation() {
|
||||
//用于访问腾讯定位服务的类, 周期性向客户端提供位置更新
|
||||
locationManager = TencentLocationManager.getInstance(this);
|
||||
//设置坐标系
|
||||
locationManager.setCoordinateType(TencentLocationManager.COORDINATE_TYPE_GCJ02);
|
||||
//创建定位请求
|
||||
locationRequest = TencentLocationRequest.create();
|
||||
//设置定位周期(位置监听器回调周期)为3s
|
||||
locationRequest.setInterval(3000);
|
||||
|
||||
//地图上设置定位数据源
|
||||
tencentMap.setLocationSource(this);
|
||||
//设置当前位置可见
|
||||
tencentMap.setMyLocationEnabled(true);
|
||||
//设置定位图标样式
|
||||
setLocMarkerStyle();
|
||||
// locationStyle = locationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);
|
||||
tencentMap.setMyLocationStyle(locationStyle);
|
||||
}
|
||||
/**
|
||||
* 实现位置监听
|
||||
* @param tencentLocation
|
||||
* @param i
|
||||
* @param s
|
||||
*/
|
||||
@Override
|
||||
public void onLocationChanged(TencentLocation tencentLocation, int i, String s) {
|
||||
|
||||
if (i == TencentLocation.ERROR_OK && locationChangedListener != null) {
|
||||
final Location location = new Location(tencentLocation.getProvider());
|
||||
//设置经纬度以及精度
|
||||
location.setLatitude(tencentLocation.getLatitude());
|
||||
location.setLongitude(tencentLocation.getLongitude());
|
||||
location.setAccuracy(tencentLocation.getAccuracy());
|
||||
locationChangedListener.onLocationChanged(location);
|
||||
|
||||
//显示回调的实时位置信息
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Rules.getEffectInfo(location);
|
||||
// double distance = DistanceUtils.getDistance(
|
||||
// locationA.getLatitude(),
|
||||
// locationA.getLongitude(),
|
||||
// locationB.getLatitude(),
|
||||
// locationB.getLongitude()
|
||||
// );
|
||||
mtvInfo.setText(String.format("\n%f %f", location.getLatitude(), location.getLongitude()));
|
||||
//打印tencentLocation的json字符串
|
||||
// Toast.makeText(getApplicationContext(), new Gson().toJson(location), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusUpdate(String s, int i, String s1) {
|
||||
//GPS, WiFi, Radio 等状态发生变化
|
||||
Log.v("State changed", s + "===" + s1);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void activate(OnLocationChangedListener onLocationChangedListener) {
|
||||
locationChangedListener = onLocationChangedListener;
|
||||
|
||||
int err = locationManager.requestLocationUpdates(locationRequest, this, Looper.myLooper());
|
||||
switch (err) {
|
||||
case 1:
|
||||
Toast.makeText(this, "设备缺少使用腾讯定位服务需要的基本条件", Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
case 2:
|
||||
Toast.makeText(this, "manifest 中配置的 key 不正确", Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
case 3:
|
||||
Toast.makeText(this, "自动加载libtencentloc.so失败", Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
locationManager.removeUpdates(this);
|
||||
locationManager = null;
|
||||
locationRequest = null;
|
||||
locationChangedListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
|
||||
Log.e("location quest: ", "success");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
|
||||
Log.e("location quest: ", "failed");
|
||||
}
|
||||
|
||||
private void checkLocationPermission() {
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
|
||||
|| ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(this,
|
||||
new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
|
||||
PERMISSION_REQUEST_CODE);
|
||||
} else {
|
||||
// 权限已授予,可进行定位操作
|
||||
//startLocationUpdates();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (requestCode == PERMISSION_REQUEST_CODE) {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
//startLocationUpdates();
|
||||
} else {
|
||||
// 用户拒绝了权限请求
|
||||
Toast.makeText(this, "请授予定位权限", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package cc.winboll.studio.positions.gps;
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package cc.winboll.studio.positions.handlers;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/14 03:51:40
|
||||
*/
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import cc.winboll.studio.positions.services.MainService;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class MainServiceHandler extends Handler {
|
||||
public static final String TAG = "MainServiceHandler";
|
||||
|
||||
public static final int MSG_REMINDTHREAD = 0;
|
||||
|
||||
WeakReference<MainService> serviceWeakReference;
|
||||
public MainServiceHandler(MainService service) {
|
||||
serviceWeakReference = new WeakReference<MainService>(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_REMINDTHREAD: // 处理下载完成消息,更新UI
|
||||
{
|
||||
// 显示提醒消息
|
||||
//
|
||||
//LogUtils.d(TAG, "显示提醒消息");
|
||||
MainService mainService = serviceWeakReference.get();
|
||||
if (mainService != null) {
|
||||
mainService.appenMessage((String)msg.obj);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package cc.winboll.studio.positions.receivers;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/13 06:58:04
|
||||
* @Describe 主要广播接收器
|
||||
*/
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import cc.winboll.studio.positions.services.MainService;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class MainReceiver extends BroadcastReceiver {
|
||||
|
||||
public static final String TAG = "MainReceiver";
|
||||
public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
|
||||
WeakReference<MainService> mwrService;
|
||||
// 存储电量指示值,
|
||||
// 用于校验电量消息时的电量变化
|
||||
static volatile int _mnTheQuantityOfElectricityOld = -1;
|
||||
static volatile boolean _mIsCharging = false;
|
||||
|
||||
public MainReceiver(MainService service) {
|
||||
mwrService = new WeakReference<MainService>(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String szAction = intent.getAction();
|
||||
if (szAction.equals(ACTION_BOOT_COMPLETED)) {
|
||||
ToastUtils.show("ACTION_BOOT_COMPLETED");
|
||||
MainService.startMainService(context);
|
||||
} else {
|
||||
ToastUtils.show(szAction);
|
||||
}
|
||||
}
|
||||
|
||||
// 注册 Receiver
|
||||
//
|
||||
public void registerAction(Context context) {
|
||||
IntentFilter filter=new IntentFilter();
|
||||
filter.addAction(ACTION_BOOT_COMPLETED);
|
||||
//filter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||
context.registerReceiver(this, filter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package cc.winboll.studio.positions.services;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/14 03:38:31
|
||||
* @Describe 守护进程服务
|
||||
*/
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import cc.winboll.studio.positions.beans.MainServiceBean;
|
||||
import cc.winboll.studio.positions.services.MainService;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.SOS;
|
||||
import cc.winboll.studio.libappbase.bean.APPSOSBean;
|
||||
|
||||
public class AssistantService extends Service {
|
||||
|
||||
public static final String TAG = "AssistantService";
|
||||
|
||||
MainServiceBean mMainServiceBean;
|
||||
MyServiceConnection mMyServiceConnection;
|
||||
MainService mMainService;
|
||||
boolean isBound = false;
|
||||
volatile boolean isThreadAlive = false;
|
||||
|
||||
public synchronized void setIsThreadAlive(boolean isThreadAlive) {
|
||||
LogUtils.d(TAG, "setIsThreadAlive(...)");
|
||||
LogUtils.d(TAG, String.format("isThreadAlive %s", isThreadAlive));
|
||||
this.isThreadAlive = isThreadAlive;
|
||||
}
|
||||
|
||||
public boolean isThreadAlive() {
|
||||
return isThreadAlive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return new MyBinder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
LogUtils.d(TAG, "onCreate");
|
||||
super.onCreate();
|
||||
|
||||
//mMyBinder = new MyBinder();
|
||||
if (mMyServiceConnection == null) {
|
||||
mMyServiceConnection = new MyServiceConnection();
|
||||
}
|
||||
// 设置运行参数
|
||||
setIsThreadAlive(false);
|
||||
assistantService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
LogUtils.d(TAG, "call onStartCommand(...)");
|
||||
assistantService();
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
//LogUtils.d(TAG, "onDestroy");
|
||||
setIsThreadAlive(false);
|
||||
// 解除绑定
|
||||
if (isBound) {
|
||||
unbindService(mMyServiceConnection);
|
||||
isBound = false;
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
// 运行服务内容
|
||||
//
|
||||
void assistantService() {
|
||||
LogUtils.d(TAG, "assistantService()");
|
||||
mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
|
||||
LogUtils.d(TAG, String.format("mMainServiceBean.isEnable() %s", mMainServiceBean.isEnable()));
|
||||
if (mMainServiceBean.isEnable()) {
|
||||
LogUtils.d(TAG, String.format("mIsThreadAlive %s", isThreadAlive()));
|
||||
if (isThreadAlive() == false) {
|
||||
// 设置运行状态
|
||||
setIsThreadAlive(true);
|
||||
// 唤醒和绑定主进程
|
||||
wakeupAndBindMain();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 唤醒和绑定主进程
|
||||
//
|
||||
void wakeupAndBindMain() {
|
||||
LogUtils.d(TAG, "wakeupAndBindMain()");
|
||||
// 绑定服务的Intent
|
||||
Intent intent = new Intent(this, MainService.class);
|
||||
startService(new Intent(this, MainService.class));
|
||||
bindService(intent, mMyServiceConnection, Context.BIND_IMPORTANT);
|
||||
|
||||
// startService(new Intent(this, MainService.class));
|
||||
// bindService(new Intent(AssistantService.this, MainService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
|
||||
}
|
||||
|
||||
// 主进程与守护进程连接时需要用到此类
|
||||
//
|
||||
class MyServiceConnection implements ServiceConnection {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
LogUtils.d(TAG, "onServiceConnected(...)");
|
||||
MainService.MyBinder binder = (MainService.MyBinder) service;
|
||||
mMainService = binder.getService();
|
||||
isBound = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
LogUtils.d(TAG, "onServiceDisconnected(...)");
|
||||
mMainServiceBean = MainServiceBean.loadBean(AssistantService.this, MainServiceBean.class);
|
||||
if (mMainServiceBean.isEnable()) {
|
||||
wakeupAndBindMain();
|
||||
}
|
||||
isBound = false;
|
||||
mMainService = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 用于返回服务实例的Binder
|
||||
public class MyBinder extends Binder {
|
||||
AssistantService getService() {
|
||||
LogUtils.d(TAG, "AssistantService MyBinder getService()");
|
||||
return AssistantService.this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package cc.winboll.studio.positions.services;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/13 06:56:41
|
||||
* @Describe 拨号主服务
|
||||
* 参考:
|
||||
* 进程保活-双进程守护的正确姿势
|
||||
* https://blog.csdn.net/sinat_35159441/article/details/75267380
|
||||
* Android Service之onStartCommand方法研究
|
||||
* https://blog.csdn.net/cyp331203/article/details/38920491
|
||||
*/
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.SOS;
|
||||
import cc.winboll.studio.libappbase.bean.APPSOSBean;
|
||||
import cc.winboll.studio.positions.beans.MainServiceBean;
|
||||
import cc.winboll.studio.positions.handlers.MainServiceHandler;
|
||||
import cc.winboll.studio.positions.receivers.MainReceiver;
|
||||
import cc.winboll.studio.positions.services.MainService;
|
||||
import cc.winboll.studio.positions.threads.MainServiceThread;
|
||||
|
||||
public class MainService extends Service {
|
||||
|
||||
public static final String TAG = "MainService";
|
||||
|
||||
public static final int MSG_UPDATE_STATUS = 0;
|
||||
|
||||
static MainService _mControlCenterService;
|
||||
|
||||
volatile boolean isServiceRunning;
|
||||
|
||||
MainServiceBean mMainServiceBean;
|
||||
MainServiceThread mMainServiceThread;
|
||||
MainServiceHandler mMainServiceHandler;
|
||||
MyServiceConnection mMyServiceConnection;
|
||||
AssistantService mAssistantService;
|
||||
boolean isBound = false;
|
||||
MainReceiver mMainReceiver;
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return new MyBinder();
|
||||
}
|
||||
|
||||
public MainServiceThread getRemindThread() {
|
||||
return mMainServiceThread;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
LogUtils.d(TAG, "onCreate()");
|
||||
_mControlCenterService = MainService.this;
|
||||
isServiceRunning = false;
|
||||
mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
|
||||
|
||||
if (mMyServiceConnection == null) {
|
||||
mMyServiceConnection = new MyServiceConnection();
|
||||
}
|
||||
mMainServiceHandler = new MainServiceHandler(this);
|
||||
|
||||
// 运行服务内容
|
||||
mainService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
LogUtils.d(TAG, "onStartCommand(...)");
|
||||
// 运行服务内容
|
||||
mainService();
|
||||
return (mMainServiceBean.isEnable()) ? START_STICKY : super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
|
||||
// 运行服务内容
|
||||
//
|
||||
void mainService() {
|
||||
LogUtils.d(TAG, "mainService()");
|
||||
mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
|
||||
if (mMainServiceBean.isEnable() && isServiceRunning == false) {
|
||||
LogUtils.d(TAG, "mainService() start running");
|
||||
isServiceRunning = true;
|
||||
// 唤醒守护进程
|
||||
wakeupAndBindAssistant();
|
||||
// 召唤 WinBoll APP 绑定本服务
|
||||
SOS.bindToAPPService(this, new APPSOSBean(getPackageName(), MainService.class.getName()));
|
||||
|
||||
if (mMainReceiver == null) {
|
||||
// 注册广播接收器
|
||||
mMainReceiver = new MainReceiver(this);
|
||||
mMainReceiver.registerAction(this);
|
||||
}
|
||||
|
||||
|
||||
MainServiceThread.getInstance(this, mMainServiceHandler).start();
|
||||
|
||||
LogUtils.i(TAG, "Main Service Is Start.");
|
||||
}
|
||||
}
|
||||
|
||||
// 唤醒和绑定守护进程
|
||||
//
|
||||
void wakeupAndBindAssistant() {
|
||||
LogUtils.d(TAG, "wakeupAndBindAssistant()");
|
||||
// if (ServiceUtils.isServiceAlive(getApplicationContext(), AssistantService.class.getName()) == false) {
|
||||
// startService(new Intent(MainService.this, AssistantService.class));
|
||||
// //LogUtils.d(TAG, "call wakeupAndBindAssistant() : Binding... AssistantService");
|
||||
// bindService(new Intent(MainService.this, AssistantService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
|
||||
// }
|
||||
Intent intent = new Intent(this, AssistantService.class);
|
||||
startService(intent);
|
||||
// 绑定服务的Intent
|
||||
//Intent intent = new Intent(this, AssistantService.class);
|
||||
bindService(intent, mMyServiceConnection, Context.BIND_IMPORTANT);
|
||||
|
||||
// Intent intent = new Intent(this, AssistantService.class);
|
||||
// startService(intent);
|
||||
// LogUtils.d(TAG, "startService(intent)");
|
||||
// bindService(new Intent(this, AssistantService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
//LogUtils.d(TAG, "onDestroy");
|
||||
mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
|
||||
//LogUtils.d(TAG, "onDestroy done");
|
||||
if (mMainServiceBean.isEnable() == false) {
|
||||
// 设置运行状态
|
||||
isServiceRunning = false;// 解除绑定
|
||||
if (isBound) {
|
||||
unbindService(mMyServiceConnection);
|
||||
isBound = false;
|
||||
}
|
||||
// 停止守护进程
|
||||
Intent intent = new Intent(this, AssistantService.class);
|
||||
stopService(intent);
|
||||
// 停止Receiver
|
||||
if (mMainReceiver != null) {
|
||||
unregisterReceiver(mMainReceiver);
|
||||
mMainReceiver = null;
|
||||
}
|
||||
// 停止前台通知栏
|
||||
stopForeground(true);
|
||||
|
||||
// 停止主要进程
|
||||
MainServiceThread.getInstance(this, mMainServiceHandler).setIsExit(true);
|
||||
}
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
// 主进程与守护进程连接时需要用到此类
|
||||
//
|
||||
private class MyServiceConnection implements ServiceConnection {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
LogUtils.d(TAG, "onServiceConnected(...)");
|
||||
AssistantService.MyBinder binder = (AssistantService.MyBinder) service;
|
||||
mAssistantService = binder.getService();
|
||||
isBound = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
LogUtils.d(TAG, "onServiceDisconnected(...)");
|
||||
if (mMainServiceBean.isEnable()) {
|
||||
// 唤醒守护进程
|
||||
wakeupAndBindAssistant();
|
||||
SOS.sosWinBollService(getApplicationContext(), new APPSOSBean(getPackageName(), MainService.class.getName()));
|
||||
}
|
||||
isBound = false;
|
||||
mAssistantService = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 用于返回服务实例的Binder
|
||||
public class MyBinder extends Binder {
|
||||
MainService getService() {
|
||||
LogUtils.d(TAG, "MainService MyBinder getService()");
|
||||
return MainService.this;
|
||||
}
|
||||
}
|
||||
|
||||
// //
|
||||
// // 启动服务
|
||||
// //
|
||||
// public static void startControlCenterService(Context context) {
|
||||
// Intent intent = new Intent(context, MainService.class);
|
||||
// context.startForegroundService(intent);
|
||||
// }
|
||||
//
|
||||
// //
|
||||
// // 停止服务
|
||||
// //
|
||||
// public static void stopControlCenterService(Context context) {
|
||||
// Intent intent = new Intent(context, MainService.class);
|
||||
// context.stopService(intent);
|
||||
// }
|
||||
|
||||
public void appenMessage(String message) {
|
||||
LogUtils.d(TAG, String.format("Message : %s", message));
|
||||
}
|
||||
|
||||
public static void stopMainService(Context context) {
|
||||
LogUtils.d(TAG, "stopMainService");
|
||||
MainServiceBean bean = new MainServiceBean();
|
||||
bean.setIsEnable(false);
|
||||
MainServiceBean.saveBean(context, bean);
|
||||
context.stopService(new Intent(context, MainService.class));
|
||||
}
|
||||
|
||||
public static void startMainService(Context context) {
|
||||
LogUtils.d(TAG, "startMainService");
|
||||
MainServiceBean bean = new MainServiceBean();
|
||||
bean.setIsEnable(true);
|
||||
MainServiceBean.saveBean(context, bean);
|
||||
context.startService(new Intent(context, MainService.class));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package cc.winboll.studio.positions.tasks;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/25 01:15:08
|
||||
* @Describe 定位规则类
|
||||
*/
|
||||
import com.tencent.map.geolocation.TencentLocation;
|
||||
import android.location.Location;
|
||||
|
||||
public class Rules {
|
||||
|
||||
public static final String TAG = "Rules";
|
||||
|
||||
public static String getEffectInfo(Location locationA) {
|
||||
//Location locationB = new Location(22.0f, 111.0f);
|
||||
// 腾讯SDK返回的坐标点(注意坐标系需统一)
|
||||
//TencentLocation locationA = ...; // 第一个点
|
||||
//TencentLocation locationB = ...; // 第二个点
|
||||
|
||||
// float[] results = new float[1];
|
||||
// Location.distanceBetween(
|
||||
// locationA.getLatitude(), // 纬度
|
||||
// locationA.getLongitude(), // 经度
|
||||
// locationB.getLatitude(),
|
||||
// locationB.getLongitude(),
|
||||
// results
|
||||
// );
|
||||
//
|
||||
// return "两点距离:" + results[0] + "米";
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package cc.winboll.studio.positions.threads;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/14 03:46:44
|
||||
*/
|
||||
import android.content.Context;
|
||||
import cc.winboll.studio.positions.handlers.MainServiceHandler;
|
||||
import cc.winboll.studio.positions.services.MainService;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.SOS;
|
||||
import cc.winboll.studio.libappbase.bean.APPSOSBean;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class MainServiceThread extends Thread {
|
||||
|
||||
public static final String TAG = "MainServiceThread";
|
||||
|
||||
volatile static MainServiceThread _MainServiceThread;
|
||||
// 控制线程是否退出的标志
|
||||
volatile boolean isExit = false;
|
||||
volatile boolean isStarted = false;
|
||||
Context mContext;
|
||||
// 服务Handler, 用于线程发送消息使用
|
||||
WeakReference<MainServiceHandler> mwrMainServiceHandler;
|
||||
|
||||
MainServiceThread(Context context, MainServiceHandler handler) {
|
||||
mContext = context;
|
||||
mwrMainServiceHandler = new WeakReference<MainServiceHandler>(handler);
|
||||
}
|
||||
|
||||
public void setIsExit(boolean isExit) {
|
||||
this.isExit = isExit;
|
||||
}
|
||||
|
||||
public boolean isExit() {
|
||||
return isExit;
|
||||
}
|
||||
|
||||
public void setIsStarted(boolean isStarted) {
|
||||
this.isStarted = isStarted;
|
||||
}
|
||||
|
||||
public boolean isStarted() {
|
||||
return isStarted;
|
||||
}
|
||||
|
||||
public static MainServiceThread getInstance(Context context, MainServiceHandler handler) {
|
||||
if (_MainServiceThread != null) {
|
||||
_MainServiceThread.setIsExit(true);
|
||||
}
|
||||
_MainServiceThread = new MainServiceThread(context, handler);
|
||||
return _MainServiceThread;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (isStarted == false) {
|
||||
isStarted = true;
|
||||
LogUtils.d(TAG, "run()");
|
||||
|
||||
while (!isExit()) {
|
||||
//ToastUtils.show("run");
|
||||
//LogUtils.d(TAG, "run()");
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
}
|
||||
_MainServiceThread = null;
|
||||
LogUtils.d(TAG, "run() exit");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package cc.winboll.studio.positions.utils;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/25 03:02:17
|
||||
* @Describe LocationFileStorage
|
||||
*/
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.json.JSONArray;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.positions.beans.LocationJson;
|
||||
|
||||
public class LocationFileStorage {
|
||||
public static final String TAG = "LocationFileStorage";
|
||||
|
||||
private static final String FILE_NAME = "locations.json";
|
||||
|
||||
public static void saveToFile(Context context, ArrayList<LocationJson> locations) {
|
||||
try {
|
||||
LocationJson.saveBeanList(context, locations, LocationJson.class);
|
||||
} catch (Exception e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
}
|
||||
|
||||
public static ArrayList<LocationJson> loadFromFile(Context context) {
|
||||
ArrayList<LocationJson> result = new ArrayList<LocationJson>();
|
||||
try {
|
||||
LocationJson.loadBeanList(context, result, LocationJson.class);
|
||||
} catch (Exception e) {
|
||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
package cc.winboll.studio.positions.views;
|
||||
|
||||
/**
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/22 03:32:48
|
||||
* @Describe GridMapView
|
||||
*/
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PointF;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ScaleGestureDetector;
|
||||
import android.view.View;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GridMapView extends View {
|
||||
// 网格参数
|
||||
private float gridTotalWidth = 1000f;
|
||||
private float gridTotalHeight = 1000f;
|
||||
private float gridSpacing = 50f;
|
||||
|
||||
// 视图变换参数
|
||||
private float offsetX = 0f;
|
||||
private float offsetY = 0f;
|
||||
private float scaleFactor = 1.0f;
|
||||
private final float minScale = 0.5f;
|
||||
private final float maxScale = 5.0f;
|
||||
|
||||
// 手势检测
|
||||
private final ScaleGestureDetector scaleDetector;
|
||||
private float lastTouchX;
|
||||
private float lastTouchY;
|
||||
|
||||
// 图形存储
|
||||
private final List<MapShape> shapes = new ArrayList<MapShape>();
|
||||
|
||||
public GridMapView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public GridMapView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
scaleDetector = new ScaleGestureDetector(context, new ScaleListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
canvas.save();
|
||||
canvas.translate(offsetX, offsetY);
|
||||
canvas.scale(scaleFactor, scaleFactor);
|
||||
|
||||
drawGrid(canvas);
|
||||
drawShapes(canvas);
|
||||
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
private void drawGrid(Canvas canvas) {
|
||||
Paint gridPaint = new Paint();
|
||||
gridPaint.setColor(Color.LTGRAY);
|
||||
gridPaint.setStrokeWidth(1f / scaleFactor);
|
||||
|
||||
// 绘制垂直线
|
||||
for (float x = 0; x <= gridTotalWidth; x += gridSpacing) {
|
||||
canvas.drawLine(x, 0, x, gridTotalHeight, gridPaint);
|
||||
}
|
||||
|
||||
// 绘制水平线
|
||||
for (float y = 0; y <= gridTotalHeight; y += gridSpacing) {
|
||||
canvas.drawLine(0, y, gridTotalWidth, y, gridPaint);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawShapes(Canvas canvas) {
|
||||
for (MapShape shape : shapes) {
|
||||
shape.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
scaleDetector.onTouchEvent(event);
|
||||
|
||||
final int action = event.getAction();
|
||||
final float x = event.getX();
|
||||
final float y = event.getY();
|
||||
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
if (!scaleDetector.isInProgress()) {
|
||||
lastTouchX = x;
|
||||
lastTouchY = y;
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (!scaleDetector.isInProgress()) {
|
||||
final float dx = x - lastTouchX;
|
||||
final float dy = y - lastTouchY;
|
||||
|
||||
offsetX += dx;
|
||||
offsetY += dy;
|
||||
invalidate();
|
||||
|
||||
lastTouchX = x;
|
||||
lastTouchY = y;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 初始化视图显示区域
|
||||
public void initViewport(final float centerX, final float centerY,
|
||||
final float viewWidth, final float viewHeight) {
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
float viewportWidth = getWidth();
|
||||
float viewportHeight = getHeight();
|
||||
|
||||
float widthScale = viewportWidth / viewWidth;
|
||||
float heightScale = viewportHeight / viewHeight;
|
||||
scaleFactor = Math.min(widthScale, heightScale);
|
||||
|
||||
offsetX = viewportWidth/2 - centerX * scaleFactor;
|
||||
offsetY = viewportHeight/2 - centerY * scaleFactor;
|
||||
invalidate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 图形绘制方法
|
||||
public void drawPoint(float x, float y, int color, float size) {
|
||||
shapes.add(new MapShape(MapShape.TYPE_POINT, x, y, color, size));
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void drawCircle(float x, float y, float radius, int color, float strokeWidth) {
|
||||
MapShape shape = new MapShape(MapShape.TYPE_CIRCLE, x, y, color, radius);
|
||||
shape.setStrokeWidth(strokeWidth);
|
||||
shapes.add(shape);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void drawLine(float startX, float startY, float endX, float endY,
|
||||
int color, float strokeWidth) {
|
||||
MapShape shape = new MapShape(MapShape.TYPE_LINE, startX, startY, endX, endY, color);
|
||||
shape.setStrokeWidth(strokeWidth);
|
||||
shapes.add(shape);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
// 网格参数设置
|
||||
public void setGridParameters(float totalWidth, float totalHeight, float spacing) {
|
||||
gridTotalWidth = totalWidth;
|
||||
gridTotalHeight = totalHeight;
|
||||
gridSpacing = spacing;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
|
||||
@Override
|
||||
public boolean onScale(ScaleGestureDetector detector) {
|
||||
float newScale = scaleFactor * detector.getScaleFactor();
|
||||
newScale = Math.max(minScale, Math.min(newScale, maxScale));
|
||||
|
||||
float focusX = detector.getFocusX();
|
||||
float focusY = detector.getFocusY();
|
||||
|
||||
offsetX = focusX - ((focusX - offsetX) / scaleFactor * newScale);
|
||||
offsetY = focusY - ((focusY - offsetY) / scaleFactor * newScale);
|
||||
|
||||
scaleFactor = newScale;
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MapShape {
|
||||
static final int TYPE_POINT = 0;
|
||||
static final int TYPE_CIRCLE = 1;
|
||||
static final int TYPE_LINE = 2;
|
||||
|
||||
final int type;
|
||||
final PointF[] points;
|
||||
final int color;
|
||||
float radius;
|
||||
float strokeWidth = 2f;
|
||||
|
||||
MapShape(int type, float x, float y, int color, float size) {
|
||||
this.type = type;
|
||||
this.points = new PointF[]{new PointF(x, y)};
|
||||
this.color = color;
|
||||
this.radius = size;
|
||||
}
|
||||
|
||||
MapShape(int type, float x1, float y1, float x2, float y2, int color) {
|
||||
this.type = type;
|
||||
this.points = new PointF[]{
|
||||
new PointF(x1, y1),
|
||||
new PointF(x2, y2)
|
||||
};
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
MapShape setStrokeWidth(float width) {
|
||||
this.strokeWidth = width;
|
||||
return this;
|
||||
}
|
||||
|
||||
void draw(Canvas canvas) {
|
||||
Paint paint = new Paint();
|
||||
paint.setColor(color);
|
||||
|
||||
switch (type) {
|
||||
case TYPE_POINT:
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
canvas.drawCircle(points[0].x, points[0].y, radius, paint);
|
||||
break;
|
||||
|
||||
case TYPE_CIRCLE:
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(strokeWidth);
|
||||
canvas.drawCircle(points[0].x, points[0].y, radius, paint);
|
||||
break;
|
||||
|
||||
case TYPE_LINE:
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(strokeWidth);
|
||||
canvas.drawLine(
|
||||
points[0].x, points[0].y,
|
||||
points[1].x, points[1].y,
|
||||
paint
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
positions/src/main/java/com/.DS_Store
vendored
Normal file
BIN
positions/src/main/java/com/tencent/.DS_Store
vendored
Normal file
BIN
positions/src/main/java/com/tencent/map/.DS_Store
vendored
Normal file
BIN
positions/src/main/java/com/tencent/map/vector/.DS_Store
vendored
Normal file
BIN
positions/src/main/java/com/tencent/map/vector/demo/.DS_Store
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
package com.tencent.map.vector.demo;
|
||||
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import cc.winboll.studio.positions.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AbsActivity extends AppCompatActivity {
|
||||
|
||||
private static final int PERMISSIONS_REQUEST_CODE = 0x99FF;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
requestPermission();
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||
private void requestPermission() {
|
||||
String[] permissions = onRequestPermissions();
|
||||
if (permissions != null) {
|
||||
List<String> deniedPermissions = new ArrayList<>();
|
||||
for (String permission : permissions) {
|
||||
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
|
||||
deniedPermissions.add(permission);
|
||||
}
|
||||
}
|
||||
|
||||
if (deniedPermissions.size() > 0) {
|
||||
requestPermissions(deniedPermissions.toArray(new String[0]), PERMISSIONS_REQUEST_CODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected String[] onRequestPermissions() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||