解决了在 Android 11 上崩溃的问题;注意在 Android 11 上无法使用 LOG 功能

This commit is contained in:
ZCShou 2020-11-17 11:14:56 +08:00
parent 4e1f640a33
commit ec13982e55
10 changed files with 130 additions and 853 deletions

View File

@ -1,13 +1,13 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 30
compileSdkVersion 29
defaultConfig {
applicationId "com.zcshou.gogogo"
minSdkVersion 21
targetSdkVersion 30
versionCode 108
versionName "1.0.8"
minSdkVersion 26
targetSdkVersion 29
versionCode 110
versionName "1.1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
ndkVersion '21.3.6528147'

Binary file not shown.

View File

@ -10,8 +10,8 @@
{
"type": "SINGLE",
"filters": [],
"versionCode": 108,
"versionName": "1.0.8",
"versionCode": 110,
"versionName": "1.1.0",
"outputFile": "app-release.apk"
}
]

View File

@ -18,6 +18,7 @@ public class GoApplication extends Application {
public void onCreate() {
super.onCreate();
mVibrator = (Vibrator)getApplicationContext().getSystemService(Service.VIBRATOR_SERVICE);
// 百度地图 SDK 初始化
SDKInitializer.initialize(getApplicationContext());
// 谷歌广告 SDK 初始化
MobileAds.initialize(getApplicationContext(), initializationStatus -> {

View File

@ -200,11 +200,9 @@ public class MainActivity extends BaseActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(layout.activity_main);
Toolbar toolbar = findViewById(id.toolbar);
setSupportActionBar(toolbar);
try {
@ -592,68 +590,64 @@ public class MainActivity extends BaseActivity
public boolean isAllowMockLocation() {
boolean canMockPosition;
if (Build.VERSION.SDK_INT <= 22) {//6.0以下
canMockPosition = Settings.Secure.getInt(this.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0;
} else {
try {
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);//获得LocationManager引用
String providerStr = LocationManager.GPS_PROVIDER;
LocationProvider provider = locationManager.getProvider(providerStr);
// 为防止在已有testProvider的情况下导致addTestProvider抛出异常先移除testProvider
try {
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);//获得LocationManager引用
String providerStr = LocationManager.GPS_PROVIDER;
LocationProvider provider = locationManager.getProvider(providerStr);
// 为防止在已有testProvider的情况下导致addTestProvider抛出异常先移除testProvider
try {
locationManager.removeTestProvider(providerStr);
Log.d("PERMISSION", "try to move test provider");
} catch (Exception e) {
e.printStackTrace();
Log.e("PERMISSION", "try to move test provider");
}
if (provider != null) {
try {
locationManager.addTestProvider(
provider.getName()
, provider.requiresNetwork()
, provider.requiresSatellite()
, provider.requiresCell()
, provider.hasMonetaryCost()
, provider.supportsAltitude()
, provider.supportsSpeed()
, provider.supportsBearing()
, provider.getPowerRequirement()
, provider.getAccuracy());
canMockPosition = true;
} catch (Exception e) {
Log.e("FUCK", "add origin gps test provider error");
canMockPosition = false;
e.printStackTrace();
}
} else {
try {
locationManager.addTestProvider(
providerStr
, true, true, false, false, true, true, true
, Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
canMockPosition = true;
} catch (Exception e) {
Log.e("FUCK", "add gps test provider error");
canMockPosition = false;
e.printStackTrace();
}
}
// 模拟位置可用
if (canMockPosition) {
locationManager.setTestProviderEnabled(providerStr, true);
locationManager.setTestProviderStatus(providerStr, LocationProvider.AVAILABLE, null, System.currentTimeMillis());
//remove test provider
locationManager.setTestProviderEnabled(providerStr, false);
locationManager.removeTestProvider(providerStr);
}
} catch (SecurityException e) {
canMockPosition = false;
locationManager.removeTestProvider(providerStr);
Log.d("PERMISSION", "try to move test provider");
} catch (Exception e) {
e.printStackTrace();
Log.e("PERMISSION", "try to move test provider");
}
if (provider != null) {
try {
locationManager.addTestProvider(
provider.getName()
, provider.requiresNetwork()
, provider.requiresSatellite()
, provider.requiresCell()
, provider.hasMonetaryCost()
, provider.supportsAltitude()
, provider.supportsSpeed()
, provider.supportsBearing()
, provider.getPowerRequirement()
, provider.getAccuracy());
canMockPosition = true;
} catch (Exception e) {
Log.e("FUCK", "add origin gps test provider error");
canMockPosition = false;
e.printStackTrace();
}
} else {
try {
locationManager.addTestProvider(
providerStr
, true, true, false, false, true, true, true
, Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
canMockPosition = true;
} catch (Exception e) {
Log.e("FUCK", "add gps test provider error");
canMockPosition = false;
e.printStackTrace();
}
}
// 模拟位置可用
if (canMockPosition) {
locationManager.setTestProviderEnabled(providerStr, true);
locationManager.setTestProviderStatus(providerStr, LocationProvider.AVAILABLE, null, System.currentTimeMillis());
//remove test provider
locationManager.setTestProviderEnabled(providerStr, false);
locationManager.removeTestProvider(providerStr);
}
} catch (SecurityException e) {
canMockPosition = false;
e.printStackTrace();
}
return canMockPosition;
@ -670,10 +664,9 @@ public class MainActivity extends BaseActivity
//WIFI是否可用
private boolean isWifiConnected() {
ConnectivityManager mConnectivityManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWiFiNetworkInfo = mConnectivityManager
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
NetworkInfo mWiFiNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
if (mWiFiNetworkInfo != null) {
if (mWiFiNetworkInfo != null && mWiFiNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
return mWiFiNetworkInfo.isAvailable();
}
@ -683,10 +676,9 @@ public class MainActivity extends BaseActivity
//MOBILE网络是否可用
private boolean isMobileConnected() {
ConnectivityManager mConnectivityManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mMobileNetworkInfo = mConnectivityManager
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
NetworkInfo mMobileNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
if (mMobileNetworkInfo != null) {
if (mMobileNetworkInfo != null && mMobileNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
return mMobileNetworkInfo.isAvailable();
}
@ -699,7 +691,7 @@ public class MainActivity extends BaseActivity
NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
if (mNetworkInfo != null) {
return mNetworkInfo.isAvailable();
return mNetworkInfo.isConnected();
}
return false;
@ -1691,7 +1683,7 @@ public class MainActivity extends BaseActivity
private void startGoLocation() {
if (!isLimit && isNetworkAvailable()) { // 时间限制
//悬浮窗权限判断
if (Build.VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(getApplicationContext())) {
if (!Settings.canDrawOverlays(getApplicationContext())) {
showEnableFloatWindowDialog();
} else {
isGPSOpen = isGpsOpened();

View File

@ -8,7 +8,6 @@ import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.CountDownTimer;
@ -154,47 +153,39 @@ public class WelcomeActivity extends BaseActivity {
}
private void requestNeedPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// 定位精确位置
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ReqPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
// 定位精确位置
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ReqPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ReqPermissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
if (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ReqPermissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
//悬浮窗
// if (checkSelfPermission(Manifest.permission.SYSTEM_ALERT_WINDOW) != PackageManager.PERMISSION_GRANTED) {
// permissions.add(Manifest.permission.SYSTEM_ALERT_WINDOW);
// }
//悬浮窗
// if (checkSelfPermission(Manifest.permission.SYSTEM_ALERT_WINDOW) != PackageManager.PERMISSION_GRANTED) {
// permissions.add(Manifest.permission.SYSTEM_ALERT_WINDOW);
// }
/*
* 读写权限和电话状态权限非必要权限(建议授予)只会申请一次用户同意或者禁止只会弹一次
*/
// 读写权限
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ReqPermissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}
/*
* 读写权限和电话状态权限非必要权限(建议授予)只会申请一次用户同意或者禁止只会弹一次
*/
// 读写权限
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ReqPermissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ReqPermissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ReqPermissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
// 读取电话状态权限
if (checkSelfPermission( Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
ReqPermissions.add(Manifest.permission.READ_PHONE_STATE);
}
// 读取电话状态权限
if (checkSelfPermission( Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
ReqPermissions.add(Manifest.permission.READ_PHONE_STATE);
}
if (ReqPermissions.size() > 0) {
requestPermissions(ReqPermissions.toArray(new String[0]), SDK_PERMISSION_REQUEST);
} else {
isPermission = true;
if (!isLimit) {
time.start();
}
}
if (ReqPermissions.size() > 0) {
requestPermissions(ReqPermissions.toArray(new String[0]), SDK_PERMISSION_REQUEST);
} else {
isPermission = true;
if (!isLimit) {
@ -206,10 +197,9 @@ public class WelcomeActivity extends BaseActivity {
//WIFI是否可用
private boolean isWifiConnected() {
ConnectivityManager mConnectivityManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWiFiNetworkInfo = mConnectivityManager
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
NetworkInfo mWiFiNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
if (mWiFiNetworkInfo != null) {
if (mWiFiNetworkInfo != null && mWiFiNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
return mWiFiNetworkInfo.isAvailable();
}
@ -219,10 +209,9 @@ public class WelcomeActivity extends BaseActivity {
//MOBILE网络是否可用
private boolean isMobileConnected() {
ConnectivityManager mConnectivityManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mMobileNetworkInfo = mConnectivityManager
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
NetworkInfo mMobileNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
if (mMobileNetworkInfo != null) {
if (mMobileNetworkInfo != null && mMobileNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
return mMobileNetworkInfo.isAvailable();
}
@ -235,7 +224,7 @@ public class WelcomeActivity extends BaseActivity {
NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
if (mNetworkInfo != null) {
return mNetworkInfo.isAvailable();
return mNetworkInfo.isConnected();
}
return false;

View File

@ -1,351 +0,0 @@
package com.zcshou.joystick;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Paint.Style;
import android.graphics.Region;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class RegionView extends View {
private Paint mPaint;
private Paint mClickPaint;
private RectF mRectFBig;
private RectF mRectFLittle;
private Path mPathLeft;
private Path mPathTop;
private Path mPathRight;
private Path mPathBottom;
private Path mPathCenter;
private float mInitSweepAngle = 0;
private float mBigSweepAngle = 84;
private float mLittleSweepAngle = 82;
private float mBigMarginAngle;
private float mLittleMarginAngle;
private List<Region> mList;
private Region mAllRegion;
private Region mRegionTop;
private Region mRegionRight;
private Region mRegionLeft;
private Region mRegionBottom;
private Region mRegionCenter;
private int mRadius;
private static final int LEFT = 0;
private static final int TOP = 1;
private static final int RIGHT = 2;
private static final int BOTTOM = 3;
private static final int CENTER = 4;
private int mClickFlag = -1;
private int mWidth;
private int mCurX, mCurY;
private RegionViewClickListener mListener;
public RegionView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
public RegionView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public RegionView(Context context) {
super(context);
initView();
}
public void setListener(RegionViewClickListener mListener) {
this.mListener = mListener;
}
private void initView() {
mPaint = new Paint();
mPaint.setStyle(Style.FILL);
mPaint.setAntiAlias(true);
mPaint.setColor(Color.parseColor("#218868"));
mClickPaint = new Paint(mPaint);
mClickPaint.setColor(Color.parseColor("#B03060"));
mPathLeft = new Path();
mPathTop = new Path();
mPathRight = new Path();
mPathBottom = new Path();
mPathCenter = new Path();
mList = new ArrayList<>();
mRegionLeft = new Region();
mRegionTop = new Region();
mRegionRight = new Region();
mRegionBottom = new Region();
mRegionCenter = new Region();
mBigMarginAngle = 90 - mBigSweepAngle;
mLittleMarginAngle = 90 - mLittleSweepAngle;
}
private void initPath() {
mList.clear();
// 初始化right路径
mPathRight.addArc(mRectFBig, mInitSweepAngle - mBigSweepAngle / 2,
mBigSweepAngle);
mPathRight.arcTo(mRectFLittle, mInitSweepAngle + mLittleSweepAngle / 2,
-mLittleSweepAngle);
mPathRight.close();
// 计算right的区域
mRegionRight.setPath(mPathRight, mAllRegion);
mList.add(mRegionRight);
// 初始化bottom路径
mPathBottom.addArc(mRectFBig, mInitSweepAngle - mBigSweepAngle / 2
+ mBigMarginAngle + mBigSweepAngle, mBigSweepAngle);
mPathBottom.arcTo(mRectFLittle, mInitSweepAngle + mLittleSweepAngle / 2
+ mLittleMarginAngle + mLittleSweepAngle, -mLittleSweepAngle);
mPathBottom.close();
// 计算bottom的区域
mRegionBottom.setPath(mPathBottom, mAllRegion);
mList.add(mRegionBottom);
// 初始化left路径
mPathLeft.addArc(mRectFBig, mInitSweepAngle - mBigSweepAngle / 2 + 2
* (mBigMarginAngle + mBigSweepAngle), mBigSweepAngle);
mPathLeft.arcTo(mRectFLittle, mInitSweepAngle + mLittleSweepAngle / 2
+ 2 * (mLittleMarginAngle + mLittleSweepAngle),
-mLittleSweepAngle);
mPathLeft.close();
// 计算left的区域
mRegionLeft.setPath(mPathLeft, mAllRegion);
mList.add(mRegionLeft);
// 初始化top路径
mPathTop.addArc(mRectFBig, mInitSweepAngle - mBigSweepAngle / 2 + 3
* (mBigMarginAngle + mBigSweepAngle), mBigSweepAngle);
mPathTop.arcTo(mRectFLittle, mInitSweepAngle + mLittleSweepAngle / 2
+ 3 * (mLittleMarginAngle + mLittleSweepAngle),
-mLittleSweepAngle);
mPathTop.close();
// 计算top的区域
mRegionTop.setPath(mPathTop, mAllRegion);
mList.add(mRegionTop);
// 初始化center路径
mPathCenter.addCircle(0, 0, mRadius, Path.Direction.CW);
mPathCenter.close();
// 计算center的区域
mRegionCenter.setPath(mPathCenter, mAllRegion);
mList.add(mRegionCenter);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.translate(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
canvas.drawPath(mPathRight, mPaint);
canvas.drawPath(mPathBottom, mPaint);
canvas.drawPath(mPathLeft, mPaint);
canvas.drawPath(mPathTop, mPaint);
canvas.drawPath(mPathCenter, mPaint);
switch (mClickFlag) {
case RIGHT:
canvas.drawPath(mPathRight, mClickPaint);
break;
case BOTTOM:
canvas.drawPath(mPathBottom, mClickPaint);
break;
case LEFT:
canvas.drawPath(mPathLeft, mClickPaint);
break;
case TOP:
canvas.drawPath(mPathTop, mClickPaint);
break;
case CENTER:
canvas.drawPath(mPathCenter, mClickPaint);
break;
}
canvas.restore();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mAllRegion = new Region(-mWidth, -mWidth, mWidth, mWidth);
mRectFBig = new RectF(-mWidth / 2, -mWidth / 2, mWidth / 2, mWidth / 2);
mRectFLittle = new RectF(-mWidth / 3, -mWidth / 3, mWidth / 3,
mWidth / 3);
mRadius = mWidth / 4;
initPath();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// 减去移除 的位置
mCurX = (int) event.getX() - getMeasuredWidth() / 2;
mCurY = (int) event.getY() - getMeasuredHeight() / 2;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
containRect(mCurX, mCurY);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
if (mClickFlag != -1) {
containRect(mCurX, mCurY);
}
invalidate();
break;
case MotionEvent.ACTION_UP:
if (mClickFlag != -1) {
switch (mClickFlag) {
case RIGHT:
if (mListener != null) {
mListener.clickRight();
}
break;
case BOTTOM:
if (mListener != null) {
mListener.clickBottom();
}
break;
case LEFT:
if (mListener != null) {
mListener.clickLeft();
}
break;
case TOP:
if (mListener != null) {
mListener.clickTop();
}
break;
case CENTER:
if (mListener != null) {
mListener.clickCenter();
}
break;
}
mClickFlag = -1;
}
invalidate();
break;
default:
break;
}
return true;
}
public void containRect(int x, int y) {
int index = -1;
for (int i = 0; i < mList.size(); i++) {
if (mList.get(i).contains(x, y)) {
mClickFlag = switchRect(i);
index = i;
break;
}
}
if (index == -1) {
mClickFlag = -1;
}
}
public int switchRect(int i) {
switch (i) {
case 0:
Log.i("aaa", "RIGHT ");
return RIGHT;
case 1:
Log.i("aaa", "BOTTOM ");
return BOTTOM;
case 2:
Log.i("aaa", "LEFT ");
return LEFT;
case 3:
Log.i("aaa", "TOP");
return TOP;
case 4:
Log.i("aaa", "CENTER");
return CENTER;
default:
return -1;
}
}
public interface RegionViewClickListener {
/**
* 左边按钮被点击了
*/
public void clickLeft();
/**
* 上边按钮被点击了
*/
public void clickTop();
/**
* 右边按钮被点击了
*/
public void clickRight();
/**
* 下边按钮被点击了
*/
public void clickBottom();
/**
* 中间按钮被点击了
*/
public void clickCenter();
}
}

View File

@ -1,251 +0,0 @@
package com.zcshou.joystick;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 仿遥控器上下左右ok圆形菜单
* Created by 庞光渝 on 2017/3/9.博客https://my.oschina.net/u/1462828/blog
*/
public class RoundMenuView extends View {
/**
* 变量
*/
private int coreX;//中心点的坐标X
private int coreY;//中心点的坐标Y
private List<RoundMenu> roundMenus;//菜单列表
private boolean isCoreMenu = false;//是否有中心按钮
private int coreMenuColor;//中心按钮的默认背景--最好不要透明色
private int coreMenuStrokeColor;//中心按钮描边颜色
private int coreMenuStrokeSize;//中心按钮描边粗细
private int coreMenuSelectColor;//中心按钮选中时的背景颜色
private Bitmap coreBitmap;//OK图片
private OnClickListener onCoreClickListener;//中心按钮的点击回调
private float deviationDegree;//偏移角度
private int onClickState = -2;//-2是无点击-1是点击中心圆其他是点击菜单
private int roundRadius;//中心圆的半径
private double radiusDistance;//半径的长度比中心圆半径=大圆半径*radiusDistance
private long touchTime;//按下时间抬起的时候判定一下超过300毫秒算点击
public RoundMenuView(Context context) {
super(context);
}
public RoundMenuView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundMenuView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onDraw(Canvas canvas) {
coreX = getWidth() / 2;
coreY = getHeight() / 2;
roundRadius = (int) (getWidth()/2 * radiusDistance);//计算中心圆圈半径
RectF rect = new RectF(0, 0, getWidth(), getHeight());
if (roundMenus != null && roundMenus.size() > 0) {
float sweepAngle = 360 / roundMenus.size();//每个弧形的角度
deviationDegree = sweepAngle / 2;//其实的偏移角度如果4个扇形的时候是X形状而非+,设为0试试就知道什么意思了
for (int i = 0; i < roundMenus.size(); i++) {
RoundMenu roundMenu = roundMenus.get(i);
//填充
Paint paint = new Paint();
paint.setAntiAlias(true);
if (onClickState == i) {
//选中
paint.setColor(roundMenu.selectSolidColor);
} else {
//未选中
paint.setColor(roundMenu.solidColor);
}
canvas.drawArc(rect, deviationDegree + (i * sweepAngle), sweepAngle, true, paint);
//画描边
paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(roundMenu.strokeSize);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(roundMenu.strokeColor);
canvas.drawArc(rect, deviationDegree + (i * sweepAngle), sweepAngle, roundMenu.useCenter, paint);
// //画图案
// Matrix matrix = new Matrix();
// matrix.postTranslate((float) ((coreX + getWidth() / 2 * roundMenu.iconDistance) - (roundMenu.icon.getWidth() / 2)), coreY - (roundMenu.icon.getHeight() / 2));
// matrix.postRotate(((i + 1) * sweepAngle), coreX, coreY);
// canvas.drawBitmap(roundMenu.icon, matrix, null);
}
}
//画中心圆圈
if (isCoreMenu) {
//填充
RectF rect1 = new RectF(coreX - roundRadius, coreY - roundRadius, coreX + roundRadius, coreY + roundRadius);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(coreMenuStrokeSize);
if (onClickState == -1) {
paint.setColor(coreMenuSelectColor);
} else {
paint.setColor(coreMenuColor);
}
canvas.drawArc(rect1, 0, 360, true, paint);
//画描边
paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(coreMenuStrokeSize);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(coreMenuStrokeColor);
canvas.drawArc(rect1, 0, 360, true, paint);
if (coreBitmap != null) {
//画中心圆圈的OK图标
canvas.drawBitmap(coreBitmap, coreX - coreBitmap.getWidth() / 2, coreY - coreBitmap.getHeight() / 2, null);// 00坐标开始画入src
}
}
}
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchTime = new Date().getTime();
float textX = event.getX();
float textY = event.getY();
int distanceLine = (int) getDisForTwoSpot(coreX, coreY, textX, textY);//距离中心点之间的直线距离
if (distanceLine <= roundRadius) {
//点击的是中心圆按下点到中心点的距离小于中心园半径那就是点击中心园了
onClickState = -1;
} else if (distanceLine <= getWidth() / 2) {
//点击的是某个扇形按下点到中心点的距离大于中心圆半径小于大圆半径那就是点击某个扇形了
float sweepAngle = 360 / roundMenus.size();//每个弧形的角度
int angle = getRotationBetweenLines(coreX, coreY, textX, textY);
//这个angle的角度是从正Y轴开始而我们的扇形是从正X轴开始再加上偏移角度所以需要计算一下
angle = (angle + 360 - 90 - (int) deviationDegree) % 360;
onClickState = (int) (angle / sweepAngle);//根据角度得出点击的是那个扇形
} else {
//点击了外面
onClickState = -2;
}
invalidate();
break;
case MotionEvent.ACTION_UP:
if ((new Date().getTime() - touchTime) < 300) {
//点击小于300毫秒算点击
OnClickListener onClickListener = null;
if (onClickState == -1) {
onClickListener = onCoreClickListener;
} else if (onClickState >= 0 && onClickState < roundMenus.size()) {
onClickListener = roundMenus.get(onClickState).onClickListener;
}
if (onClickListener != null) {
onClickListener.onClick(this);
}
}
onClickState = -2;
invalidate();
break;
}
return true;
}
/**
* 添加菜单
*
* @param roundMenu
*/
public void addRoundMenu(RoundMenu roundMenu) {
if (roundMenu == null) {
return;
}
if (roundMenus == null) {
roundMenus = new ArrayList<>();
}
roundMenus.add(roundMenu);
invalidate();
}
/**
* 添加中心菜单按钮
*
* @param coreMenuColor
* @param coreMenuSelectColor
* @param onClickListener
*/
public void setCoreMenu(int coreMenuColor, int coreMenuSelectColor, int coreMenuStrokeColor,
int coreMenuStrokeSize, double radiusDistance,Bitmap bitmap, OnClickListener onClickListener) {
isCoreMenu = true;
this.coreMenuColor = coreMenuColor;
this.radiusDistance = radiusDistance;
this.coreMenuSelectColor = coreMenuSelectColor;
this.coreMenuStrokeColor = coreMenuStrokeColor;
this.coreMenuStrokeSize = coreMenuStrokeSize;
coreBitmap = bitmap;
this.onCoreClickListener = onClickListener;
invalidate();
}
/**
* 获取两条线的夹角
*
* @param centerX
* @param centerY
* @param xInView
* @param yInView
* @return
*/
public static int getRotationBetweenLines(float centerX, float centerY, float xInView, float yInView) {
double rotation = 0;
double k1 = (double) (centerY - centerY) / (centerX * 2 - centerX);
double k2 = (double) (yInView - centerY) / (xInView - centerX);
double tmpDegree = Math.atan((Math.abs(k1 - k2)) / (1 + k1 * k2)) / Math.PI * 180;
if (xInView > centerX && yInView < centerY) { //第一象限
rotation = 90 - tmpDegree;
} else if (xInView > centerX && yInView > centerY) //第二象限
{
rotation = 90 + tmpDegree;
} else if (xInView < centerX && yInView > centerY) { //第三象限
rotation = 270 - tmpDegree;
} else if (xInView < centerX && yInView < centerY) { //第四象限
rotation = 270 + tmpDegree;
} else if (xInView == centerX && yInView < centerY) {
rotation = 0;
} else if (xInView == centerX && yInView > centerY) {
rotation = 180;
}
return (int) rotation;
}
/**
* 求两个点之间的距离
*
* @return s
*/
public static double getDisForTwoSpot(float x1, float y1, float x2, float y2) {
float width, height;
if (x1 > x2) {
width = x1 - x2;
} else {
width = x2 - x1;
}
if (y1 > y2) {
height = y2 - y1;
} else {
height = y2 - y1;
}
return Math.sqrt((width * width) + (height * height));
}
/**
* 扇形的对象类
*/
public static class RoundMenu {
public boolean useCenter = true;//扇形是否画连接中心点的直线
public int solidColor = 0x00000000;//背景颜色,默认透明
public int selectSolidColor = 0x00000000;//背景颜色,默认透明
public int strokeColor = 0x00000000;//描边颜色,默认透明
public int strokeSize = 1;//描边的宽度,默认1
public Bitmap icon;//菜单的图片
public OnClickListener onClickListener;//点击监听
public double iconDistance = 0.63;//图标距离中心点的距离
}
}

View File

@ -1,6 +1,7 @@
package com.zcshou.log4j;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.Locale;
import java.text.SimpleDateFormat;
@ -62,7 +63,7 @@ public class LogUtil {
/**
* 配置log4j参数
*/
public static void configLog() {
public static void configLog() throws IOException {
LogConfig logConfig = new LogConfig();
/** 设置Log等级生产环境下调用setLogToProduce()发布后调用setLogToRelease() **/
setLogToProduce(logConfig);

View File

@ -1,6 +1,5 @@
package com.zcshou.service;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@ -16,89 +15,67 @@ import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Build;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import android.util.Log;
import com.baidu.mapapi.model.LatLng;
import com.zcshou.gogogo.MainActivity;
import com.zcshou.joystick.JoyStick;
import com.zcshou.log4j.LogUtil;
import com.zcshou.gogogo.R;
import org.apache.log4j.Logger;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class GoService extends Service {
public static final int RunCode = 0x01;
public static final int StopCode = 0x02;
private static final int HANDLER_MSG_ID = 0;
private LocationManager locationManager;
private HandlerThread handlerThread;
private Handler handler;
private boolean isStop = true; // 是否启动了模拟位置
private String curLatLng = "117.027707&36.667662";// 模拟位置的经纬度字符串
private static final long mTS = 1609286402;
// 摇杆相关
private JoyStick mJoyStick;
private boolean isJoyStick = false; // 摇杆是否启动
double mSpeed;
// 限制检测
private boolean isLimit = false;
private static final long mTS = 1609286402;
private TimeTask timeTask;
private ExecutorService threadExecutor;
private TimeCount time;
// 通知栏消息
NoteActionReceiver acReceiver;
// log debug
private static final Logger log = Logger.getLogger(GoService.class);
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@SuppressLint("WrongConstant")
@Override
public void onCreate() {
LogUtil.configLog();
Log.d("GoService", "onCreate");
log.debug("onCreate");
super.onCreate();
time = new TimeCount(1000 * 60 * 20, 1000);
mSpeed = 0.00003;
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
//remove default network location provider
rmNetworkTestProvider();
//remove gps provider
rmGPSTestProvider();
//remove other provider
//rmOtherTestProvider();
removeTestProviderNetwork();
removeTestProviderGPS();
//add a new test network location provider
setNetworkTestProvider();
// add a new GPS test Provider
setGPSTestProvider();
addTestProviderNetwork();
addTestProviderGPS();
//thread
// thread
handlerThread = new HandlerThread(getUUID(), -2);
handlerThread.start();
@ -111,26 +88,22 @@ public class GoService extends Service {
setNetworkLocation();
setGPSLocation();
sendEmptyMessage(0);
sendEmptyMessage(HANDLER_MSG_ID);
// broadcast to MainActivity
Intent intent = new Intent();
intent.putExtra("StatusRun", RunCode);
// intent.putExtra("CurLatLng", curLatLng);
intent.setAction("com.zcshou.service.GoService");
sendBroadcast(intent);
}
} catch (InterruptedException e) {
e.printStackTrace();
Log.d("GoService", "handleMessage error");
log.debug("handleMessage error");
Thread.currentThread().interrupt();
}
}
};
handler.sendEmptyMessage(0);
mSpeed = 0.00003;
handler.sendEmptyMessage(HANDLER_MSG_ID);
timeTask = new TimeTask();
threadExecutor = Executors.newSingleThreadExecutor();
@ -145,10 +118,8 @@ public class GoService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("GoService", "onStartCommand");
log.debug("onStartCommand");
threadExecutor.submit(timeTask);
time.start();
String channelId = "channel_01";
String name = "channel_name";
@ -193,15 +164,10 @@ public class GoService extends Service {
startForeground(1, notification);
// get location info from mainActivity
curLatLng = intent.getStringExtra("CurLatLng");
Log.d("GoService", "LatLng from Main is " + curLatLng);
log.debug("LatLng from Main is " + curLatLng);
//start to refresh location
isStop = false;
// 开启摇杆
if (!isJoyStick) {
mJoyStick = new JoyStick(this);
@ -228,8 +194,7 @@ public class GoService extends Service {
double lat = Double.parseDouble(latLngStr[1]) + latDegree / 1000; // 为啥 / 1000 ? 按照速度算下来这里偏大
curLatLng = lng + "&" + lat;
} else {
Log.d("GoService", "isLimit " + isLimit);
log.debug("isLimit " + isLimit);
Log.d("GoService", "isLimit ");
}
}
@ -237,11 +202,8 @@ public class GoService extends Service {
public void setCurrentSpeed(double speed) {
mSpeed = speed * 3.6; // 转换为 km/h, 1米/(m/s)=3.6千米/(km/h)
}
});
mJoyStick.show();
isJoyStick = true;
}
@ -251,23 +213,18 @@ public class GoService extends Service {
@Override
public void onDestroy() {
Log.d("GoService", "onDestroy");
log.debug("onDestroy");
isStop = true;
mJoyStick.hide();
isJoyStick = false;
handler.removeMessages(0);
handler.removeMessages(HANDLER_MSG_ID);
handlerThread.quit();
time.cancel();
threadExecutor.shutdownNow();
unregisterReceiver(acReceiver);
//remove test provider
rmNetworkTestProvider();
rmGPSTestProvider();
removeTestProviderNetwork();
removeTestProviderGPS();
//rmOtherTestProvider();
stopForeground(true);
@ -281,7 +238,6 @@ public class GoService extends Service {
super.onDestroy();
}
//generate a location
public Location generateLocation(LatLng latLng) {
Location loc = new Location("gps");
loc.setAccuracy(2.0F); // 精度
@ -299,7 +255,6 @@ public class GoService extends Service {
return loc;
}
//添加网络定位
private void setNetworkLocation() {
String[] latLngStr = curLatLng.split("&");
LatLng latLng = new LatLng(Double.parseDouble(latLngStr[1]), Double.parseDouble(latLngStr[0]));
@ -310,12 +265,10 @@ public class GoService extends Service {
locationManager.setTestProviderLocation(providerStr, generateLocation(latLng));
} catch (Exception e) {
Log.d("GoService", "setNetworkLocation error");
log.debug("setNetworkLocation error");
e.printStackTrace();
}
}
//set gps location
private void setGPSLocation() {
String[] latLngStr = curLatLng.split("&");
LatLng latLng = new LatLng(Double.parseDouble(latLngStr[1]), Double.parseDouble(latLngStr[0]));
@ -325,41 +278,31 @@ public class GoService extends Service {
locationManager.setTestProviderLocation(providerStr, generateLocation(latLng));
} catch (Exception e) {
Log.d("GoService", "setGPSLocation error");
log.debug("setGPSLocation error");
e.printStackTrace();
}
}
//remove network provider
private void rmNetworkTestProvider() {
private void removeTestProviderNetwork() {
try {
if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
Log.d("GoService", "now remove NetworkProvider");
log.debug("now remove NetworkProvider");
locationManager.removeTestProvider(LocationManager.NETWORK_PROVIDER);
} else {
Log.d("GoService", "NetworkProvider is not enabled");
log.debug("NetworkProvider is not enabled");
}
} catch (Exception e) {
e.printStackTrace();
Log.d("GoService", "rmNetworkProvider error");
log.debug("rmNetworkProvider error");
Log.d("GoService", "ERROR:removeTestProviderNetwork");
}
}
//set network provider
private void setNetworkTestProvider() {
private void addTestProviderNetwork() {
try {
locationManager.addTestProvider(LocationManager.NETWORK_PROVIDER, true, false,
false, false, false, false,
false, Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
Log.d("GoService", "addTestProvider[NETWORK_PROVIDER] success");
log.debug("addTestProvider[NETWORK_PROVIDER] success");
} catch (SecurityException e) {
e.printStackTrace();
Log.d("GoService", "addTestProvider[NETWORK_PROVIDER] error");
log.debug("addTestProvider[NETWORK_PROVIDER] error");
Log.d("GoService", "ERROR:addTestProviderNetwork");
}
if (!locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
@ -368,7 +311,6 @@ public class GoService extends Service {
} catch (Exception e) {
e.printStackTrace();
Log.d("GoService", "setTestProviderEnabled[NETWORK_PROVIDER] error");
log.debug("setTestProviderEnabled[NETWORK_PROVIDER] error");
}
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
@ -378,47 +320,26 @@ public class GoService extends Service {
}
}
// set GPS provider
private void rmGPSTestProvider() {
private void removeTestProviderGPS() {
try {
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
Log.d("GoService", "now remove GPSProvider");
log.debug("now remove GPSProvider");
locationManager.removeTestProvider(LocationManager.GPS_PROVIDER);
} else {
Log.d("GoService", "GPSProvider is not enabled");
log.debug("GPSProvider is not enabled");
}
} catch (Exception e) {
e.printStackTrace();
Log.d("GoService", "rmGPSProvider error");
log.debug("rmGPSProvider error");
Log.d("GoService", "ERROR:removeTestProviderGPS");
}
}
private void setGPSTestProvider() {
// if (!locationManager.isProviderEnabled(LocationManager.PASSIVE_PROVIDER)) {
// locationManager.setTestProviderEnabled(LocationManager.PASSIVE_PROVIDER, false);
// Log.d("GoService", "Disable passive provider");
// log.debug("Disable passive provider");
// }
//
// if (!locationManager.isProviderEnabled("fused") && Build.VERSION.SDK_INT >= 29
// && !RomUtils.isVivo() && !RomUtils.isEmui()) { // 目前 ViVo 会崩溃
// locationManager.setTestProviderEnabled("fused", false);
// Log.d("GoService", "Disable fused provider");
// log.debug("Disable fused provider");
// }
private void addTestProviderGPS() {
try {
locationManager.addTestProvider(LocationManager.GPS_PROVIDER, false, true, true,
false, true, true, true, Criteria.POWER_HIGH, Criteria.ACCURACY_HIGH);
Log.d("GoService", "addTestProvider[GPS_PROVIDER] success");
log.debug("addTestProvider[GPS_PROVIDER] success");
false, true, true, true, Criteria.POWER_HIGH, Criteria.ACCURACY_MEDIUM);
} catch (Exception e) {
e.printStackTrace();
Log.d("GoService", "addTestProvider[GPS_PROVIDER] error");
log.debug("addTestProvider[GPS_PROVIDER] error");
Log.d("GoService", "ERROR:addTestProviderGPS");
}
if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
@ -427,7 +348,6 @@ public class GoService extends Service {
} catch (Exception e) {
e.printStackTrace();
Log.d("GoService", "setTestProviderEnabled[GPS_PROVIDER] error");
log.debug("setTestProviderEnabled[GPS_PROVIDER] error");
}
}
@ -444,11 +364,9 @@ public class GoService extends Service {
// try {
// locationManager.setTestProviderEnabled(LocationManager.PASSIVE_PROVIDER, false);
// Log.d("GoService", "Disable passive provider");
// log.debug("Disable passive provider");
// } catch(Exception e) {
// e.printStackTrace();
// Log.d("GoService", "Disable passive provider error");
// log.debug("Disable passive provider error");
// }
// }
//
@ -456,37 +374,18 @@ public class GoService extends Service {
// try {
// locationManager.setTestProviderEnabled("fused", false);
// Log.d("GoService", "Disable fused provider");
// log.debug("Disable fused provider");
// } catch(Exception e) {
// e.printStackTrace();
// Log.d("GoService", "Disable fused provider error");
// log.debug("Disable fused provider error");
// }
// }
// }
//uuid random
// uuid random
public static String getUUID() {
return UUID.randomUUID().toString();
}
class TimeCount extends CountDownTimer {
public TimeCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);//参数依次为总时长,和计时的时间间隔
}
@Override
public void onFinish() {//计时完毕时触发
threadExecutor.submit(timeTask);
time.start();
}
@Override
public void onTick(long millisUntilFinished) { //计时过程显示
}
}
private class TimeTask implements Runnable {
private final String[] ntpServerPool = {"ntp1.aliyun.com", "ntp2.aliyun.com", "ntp3.aliyun.com", "ntp4.aliyun.com", "ntp5.aliyun.com", "ntp6.aliyun.com", "ntp7.aliyun.com",
"cn.pool.ntp.org", "cn.ntp.org.cn", "sg.pool.ntp.org", "tw.pool.ntp.org", "jp.pool.ntp.org", "hk.pool.ntp.org", "th.pool.ntp.org",
@ -511,7 +410,6 @@ public class GoService extends Service {
if (i >= ntpServerPool.length) {
isLimit = true;
Log.d("GoService", "GoSntpClient is error");
log.debug("GoSntpClient is error");
}
}
}
@ -523,14 +421,12 @@ public class GoService extends Service {
if (action != null) {
if (action.equals("ShowJoyStick")) {
Log.d("GoService", "ShowJoyStick");
log.debug("ShowJoyStick");
mJoyStick.show();
}
if (action.equals("HideJoyStick")) {
mJoyStick.hide();
Log.d("GoService", "HideJoyStick");
log.debug("HideJoyStick");
}
}
}