[2.13.0-merge]yakun and code style
This commit is contained in:
@@ -11,6 +11,7 @@ import android.widget.TextView;
|
||||
|
||||
import com.mogo.commons.crash.FinalizeCrashFixer;
|
||||
import com.mogo.commons.screen.ScreenHelper;
|
||||
import com.mogo.commons.module.MogoServices;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.eagle.core.utilcode.mogo.toast.TipDrawable;
|
||||
import com.mogo.eagle.core.utilcode.mogo.toast.TipToast;
|
||||
@@ -47,6 +48,7 @@ public abstract class AbsMogoApplication extends Application {
|
||||
}
|
||||
ScreenHelper.setScreenConfig(this);
|
||||
Utils.init(this);
|
||||
MogoServices.getInstance().init(this);
|
||||
}
|
||||
|
||||
private void initRxJavaErrorHandler() {
|
||||
@@ -99,4 +101,5 @@ public abstract class AbsMogoApplication extends Application {
|
||||
}
|
||||
return contentView;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.mogo.commons.module;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2019-12-31
|
||||
* <p>
|
||||
* 模块描述信息
|
||||
*/
|
||||
public class MogoModule {
|
||||
|
||||
/**
|
||||
* 模块加载路径
|
||||
*/
|
||||
private String mPath;
|
||||
|
||||
/**
|
||||
* 模块名称
|
||||
*/
|
||||
private String mName;
|
||||
|
||||
/**
|
||||
* 广播接收者
|
||||
*/
|
||||
private String mBroadcastAction;
|
||||
|
||||
/**
|
||||
* @param path 模块加载路径
|
||||
* @param name 模块名称
|
||||
*/
|
||||
public MogoModule( String path, String name ) {
|
||||
this.mPath = path;
|
||||
this.mName = name;
|
||||
}
|
||||
|
||||
|
||||
public String getPath() {
|
||||
return mPath;
|
||||
}
|
||||
|
||||
public MogoModule setPath( String path ) {
|
||||
this.mPath = path;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
public MogoModule setName( String name ) {
|
||||
this.mName = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getBroadcastAction() {
|
||||
return mBroadcastAction;
|
||||
}
|
||||
|
||||
public MogoModule setBroadcastAction( String broadcastAction ) {
|
||||
this.mBroadcastAction = broadcastAction;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.mogo.commons.module;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2019-12-23
|
||||
* <p>
|
||||
* 模块路由路径
|
||||
*/
|
||||
public class MogoModulePaths {
|
||||
|
||||
private static final List<MogoModule> mMogoModules = new ArrayList<>();
|
||||
|
||||
// 不需要启动APP也能运行的模块
|
||||
private static final List<MogoModule> mMogoBaseModules = new ArrayList<>();
|
||||
|
||||
private static final List<MogoModule> mModuleFunctions = new ArrayList<>();
|
||||
|
||||
private static final List<MogoModule> mModuleFunctionServers = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 添加卡片模块
|
||||
*
|
||||
* @param module
|
||||
*/
|
||||
public static void addModule(MogoModule module) {
|
||||
if (module == null || TextUtils.isEmpty(module.getPath().replace(" ", ""))) {
|
||||
throw new IllegalArgumentException("module path can't be empty or null or blank");
|
||||
}
|
||||
mMogoModules.add(module);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加模块功能
|
||||
*
|
||||
* @param module 功能模块
|
||||
*/
|
||||
public static void addModuleFunction(MogoModule module) {
|
||||
if (module == null || TextUtils.isEmpty(module.getPath().replace(" ", ""))) {
|
||||
throw new IllegalArgumentException("module path can't be empty or null or blank");
|
||||
}
|
||||
mModuleFunctions.add(module);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加 功能服务, 不带UI Fragment的
|
||||
*
|
||||
* @param module 功能模块
|
||||
*/
|
||||
public static void addModuleFunctionServer(MogoModule module) {
|
||||
if (module == null || TextUtils.isEmpty(module.getPath().replace(" ", ""))) {
|
||||
throw new IllegalArgumentException("module path can't be empty or null or blank");
|
||||
}
|
||||
mModuleFunctionServers.add(module);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加基础模块
|
||||
*
|
||||
* @param module
|
||||
*/
|
||||
public static void addBaseModule(MogoModule module) {
|
||||
if (module == null || TextUtils.isEmpty(module.getPath().replace(" ", ""))) {
|
||||
throw new IllegalArgumentException("module path can't be empty or null or blank");
|
||||
}
|
||||
mMogoBaseModules.add(module);
|
||||
}
|
||||
|
||||
public static List<MogoModule> getModules() {
|
||||
return mMogoModules;
|
||||
}
|
||||
|
||||
public static List<MogoModule> getBaseModules() {
|
||||
return mMogoBaseModules;
|
||||
}
|
||||
|
||||
public static List<MogoModule> getModuleFunctions() {
|
||||
return mModuleFunctions;
|
||||
}
|
||||
|
||||
public static List<MogoModule> getModuleFunctionServers() {
|
||||
return mModuleFunctionServers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.mogo.commons.module;
|
||||
|
||||
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_OLD_OTHER;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.mogo.commons.debug.DebugConfig;
|
||||
import com.mogo.commons.module.intent.IMogoIntentListener;
|
||||
import com.mogo.commons.module.intent.IntentHandlerFactory;
|
||||
import com.mogo.commons.module.intent.IntentManager;
|
||||
import com.mogo.commons.module.status.MogoStatusManager;
|
||||
import com.mogo.commons.module.receiver.MogoReceiver;
|
||||
import com.mogo.commons.voice.AIAssist;
|
||||
import com.mogo.eagle.core.data.config.CloudPoiManager;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.eagle.core.utilcode.util.NetworkUtils;
|
||||
import com.mogo.realtime.api.MoGoAiCloudRealTime;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class MogoServices implements IMogoIntentListener {
|
||||
|
||||
private MogoServices() {
|
||||
}
|
||||
|
||||
private static final class InstanceHolder {
|
||||
private static final MogoServices INSTANCE = new MogoServices();
|
||||
}
|
||||
|
||||
public static MogoServices getInstance() {
|
||||
return InstanceHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private static final String TAG = "MogoServices";
|
||||
|
||||
private IntentManager mIntentManager;
|
||||
|
||||
private Context mContext;
|
||||
|
||||
public void init(Context context) {
|
||||
mContext = context;
|
||||
MogoStatusManager.getInstance().setAIAssistReady(TAG, AIAssist.getInstance(mContext).hasFlush());
|
||||
CloudPoiManager.getInstance().updateFromConfig(context);
|
||||
|
||||
registerMogoReceiver(context);
|
||||
|
||||
mIntentManager = IntentManager.getInstance();
|
||||
mIntentManager.registerIntentListener(MogoReceiver.ACTION_VOICE_UI, this);
|
||||
mIntentManager.registerIntentListener(MogoReceiver.ACTION_VOICE_READY, this);
|
||||
mIntentManager.registerIntentListener(ConnectivityManager.CONNECTIVITY_ACTION, this);
|
||||
|
||||
Intent intent = new Intent("com.freedom.ser.ACTION");
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
mContext.sendBroadcast(intent);
|
||||
|
||||
if (DebugConfig.isNeedUploadCoordinatesDurationInTime()) {
|
||||
MoGoAiCloudRealTime.startRealTime(mContext, DebugConfig.getSocketAppId());
|
||||
}
|
||||
}
|
||||
|
||||
private void registerMogoReceiver(Context context) {
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
List<MogoModule> modules = MogoModulePaths.getModules();
|
||||
if (modules.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
MogoReceiver receiver = new MogoReceiver(context);
|
||||
IntentFilter filter = new IntentFilter();
|
||||
if (!modules.isEmpty()) {
|
||||
for (MogoModule module : modules) {
|
||||
if (TextUtils.isEmpty(module.getBroadcastAction())) {
|
||||
continue;
|
||||
}
|
||||
filter.addAction(module.getBroadcastAction());
|
||||
}
|
||||
}
|
||||
filter.addAction(MogoReceiver.VOICE_ACTION);
|
||||
// 小智语音
|
||||
filter.addAction(MogoReceiver.ACTION_VOICE_UI);
|
||||
filter.addAction(MogoReceiver.ACTION_VOICE_READY);
|
||||
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
|
||||
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
try {
|
||||
context.getApplicationContext().registerReceiver(receiver, filter);
|
||||
} catch (Exception e) {
|
||||
CallerLogger.INSTANCE.e(M_OLD_OTHER + TAG, "registerMogoReceiver error : " + e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIntentReceived(String command, Intent intent) {
|
||||
if (TextUtils.equals(command, ConnectivityManager.CONNECTIVITY_ACTION)
|
||||
&& NetworkUtils.isConnected(mContext)) {
|
||||
mIntentManager.unregisterIntentListener(ConnectivityManager.CONNECTIVITY_ACTION, this);
|
||||
}
|
||||
IntentHandlerFactory.getInstance().handle(mContext, command, intent);
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
CallerLogger.INSTANCE.d(M_OLD_OTHER + TAG, "MogoServices do nothings.");
|
||||
if (DebugConfig.isNeedUploadCoordinatesDurationInTime()) {
|
||||
MoGoAiCloudRealTime.stopRealTime();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.mogo.commons.module;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-03
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class ServiceConst {
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
public static final String TYPE = "STRATEGY_REFRESH";
|
||||
|
||||
|
||||
/**
|
||||
* 卡片 用户数据
|
||||
*/
|
||||
public static final String CARD_TYPE_USER_DATA = "CARD_TYPE_USER_DATA";
|
||||
|
||||
/**
|
||||
* 卡片 探路数据
|
||||
*/
|
||||
public static final String CARD_TYPE_ROAD_CONDITION = "CARD_TYPE_ROAD_CONDITION";
|
||||
|
||||
/**
|
||||
* 卡片 新鲜事
|
||||
*/
|
||||
public static final String CARD_TYPE_NOVELTY = "CARD_TYPE_NOVELTY";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.mogo.commons.module.intent;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.mogo.commons.module.status.MogoStatusManager;
|
||||
import com.mogo.commons.voice.AIAssist;
|
||||
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020/6/5
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class AIAssistIntentHandler implements IntentHandler {
|
||||
|
||||
private static final String TAG = "AIAssistIntentHandler";
|
||||
|
||||
@Override
|
||||
public void handle( Context context, Intent intent ) {
|
||||
AIAssist.getInstance( context ).flush();
|
||||
MogoStatusManager.getInstance().setAIAssistReady( TAG, true );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.mogo.commons.module.intent;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.mogo.commons.module.ServiceConst;
|
||||
import com.mogo.commons.module.status.MogoStatusManager;
|
||||
import com.mogo.commons.utils.CarSeries;
|
||||
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020/6/5
|
||||
*
|
||||
* 描述
|
||||
*/
|
||||
public class AccStatusIntentHandler implements IntentHandler {
|
||||
|
||||
private static volatile AccStatusIntentHandler sInstance;
|
||||
|
||||
private AccStatusIntentHandler() {
|
||||
}
|
||||
|
||||
public static AccStatusIntentHandler getInstance() {
|
||||
if ( sInstance == null ) {
|
||||
synchronized ( AccStatusIntentHandler.class ) {
|
||||
if ( sInstance == null ) {
|
||||
sInstance = new AccStatusIntentHandler();
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public synchronized void release() {
|
||||
sInstance = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle( Context context, Intent intent ) {
|
||||
String action = intent.getAction();
|
||||
if ( Intent.ACTION_POWER_CONNECTED.equals( action ) ) {
|
||||
if ( CarSeries.isF8xxSeries() ) {
|
||||
MogoStatusManager.getInstance().setAccStatus( ServiceConst.TYPE, true );
|
||||
}
|
||||
} else if ( Intent.ACTION_POWER_DISCONNECTED.equals( action ) ) {
|
||||
if ( CarSeries.isF8xxSeries() ) {
|
||||
MogoStatusManager.getInstance().setAccStatus( ServiceConst.TYPE, false );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.mogo.commons.module.intent;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-04-17
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class EmptyIntentHandler implements IntentHandler {
|
||||
|
||||
private static final String TAG = "EmptyIntentHandler";
|
||||
|
||||
@Override
|
||||
public void handle( Context context, Intent intent ) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.mogo.commons.module.intent;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-09
|
||||
* <p>
|
||||
* 免唤醒语音监听
|
||||
*/
|
||||
public interface IMogoIntentListener {
|
||||
|
||||
/**
|
||||
* @param intentStr 广播action、语音 command
|
||||
* @param intent 意图
|
||||
*/
|
||||
void onIntentReceived( String intentStr, Intent intent );
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.mogo.commons.module.intent;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
import com.alibaba.android.arouter.facade.template.IProvider;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-09
|
||||
* <p>
|
||||
* 唤醒语音控制
|
||||
*/
|
||||
public interface IMogoIntentManager extends IProvider {
|
||||
|
||||
/**
|
||||
* 注册意图接收者
|
||||
*
|
||||
* @param intent
|
||||
*/
|
||||
public void registerIntentListener( String intent, IMogoIntentListener listener );
|
||||
|
||||
/**
|
||||
* 注册意图接收者
|
||||
*
|
||||
* @param intent
|
||||
*/
|
||||
public void unregisterIntentListener( String intent, IMogoIntentListener listener );
|
||||
|
||||
/**
|
||||
* 触发意图回调,各业务不用关心
|
||||
*
|
||||
* @param intentStr
|
||||
* @param intent
|
||||
*/
|
||||
public void invoke( String intentStr, Intent intent );
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.mogo.commons.module.intent;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-04-17
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public interface IntentHandler {
|
||||
|
||||
void handle( Context context, Intent intent );
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.mogo.commons.module.intent;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
|
||||
import com.mogo.commons.module.receiver.MogoReceiver;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-04-17
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class IntentHandlerFactory {
|
||||
|
||||
private IntentHandlerFactory() {
|
||||
// private constructor
|
||||
mHandlers.put( MogoReceiver.ACTION_VOICE_UI, new VoiceUiIntentHandler() );
|
||||
mHandlers.put( Intent.ACTION_POWER_CONNECTED, AccStatusIntentHandler.getInstance() );
|
||||
mHandlers.put( Intent.ACTION_POWER_DISCONNECTED, AccStatusIntentHandler.getInstance() );
|
||||
mHandlers.put( MogoReceiver.ACTION_VOICE_READY, new AIAssistIntentHandler() );
|
||||
}
|
||||
|
||||
private static final class InstanceHolder {
|
||||
private static final IntentHandlerFactory INSTANCE = new IntentHandlerFactory();
|
||||
}
|
||||
|
||||
public static IntentHandlerFactory getInstance() {
|
||||
return InstanceHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private Object readResolve() {
|
||||
// 阻止反序列化,必须实现 Serializable 接口
|
||||
return InstanceHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private final Map< String, IntentHandler > mHandlers = new HashMap<>();
|
||||
|
||||
private final IntentHandler DEFAULT = new EmptyIntentHandler();
|
||||
|
||||
private IntentHandler getIntentHandler( String intent ) {
|
||||
if ( mHandlers.containsKey( intent ) && mHandlers.get( intent ) != null ) {
|
||||
return mHandlers.get( intent );
|
||||
}
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
public void handle( Context context, String intent, Intent obj ) {
|
||||
IntentHandler handler = getIntentHandler( intent );
|
||||
if ( handler != null ) {
|
||||
handler.handle( context, obj );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.mogo.commons.module.intent;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-09
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class IntentManager implements IMogoIntentManager{
|
||||
|
||||
private static volatile IntentManager sInstance;
|
||||
private static final byte[] obj = new byte[0];
|
||||
|
||||
private IntentManager() {
|
||||
}
|
||||
|
||||
public static IntentManager getInstance() {
|
||||
if ( sInstance == null ) {
|
||||
synchronized ( obj ) {
|
||||
if ( sInstance == null ) {
|
||||
sInstance = new IntentManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public synchronized void release() {
|
||||
sInstance = null;
|
||||
}
|
||||
|
||||
private final Map< String, CopyOnWriteArrayList< IMogoIntentListener > > mListeners = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void registerIntentListener( String intent, IMogoIntentListener listener ) {
|
||||
if ( listener == null || intent == null ) {
|
||||
return;
|
||||
}
|
||||
if ( !mListeners.containsKey( intent ) ) {
|
||||
mListeners.put( intent, new CopyOnWriteArrayList<>() );
|
||||
}
|
||||
mListeners.get( intent ).add( listener );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterIntentListener( String command, IMogoIntentListener listener ) {
|
||||
if ( mListeners.containsKey( command ) ) {
|
||||
mListeners.get( command ).remove( listener );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init( Context context ) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke( String command, Intent intent ) {
|
||||
CopyOnWriteArrayList< IMogoIntentListener > listeners = mListeners.get( command );
|
||||
if ( listeners != null && !listeners.isEmpty() ) {
|
||||
Iterator< IMogoIntentListener > iterator = listeners.iterator();
|
||||
while ( iterator.hasNext() ) {
|
||||
IMogoIntentListener listener = iterator.next();
|
||||
if ( listener != null ) {
|
||||
listener.onIntentReceived( command, intent );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.mogo.commons.module.intent;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.mogo.commons.module.status.MogoStatusManager;
|
||||
import com.mogo.commons.module.receiver.MogoReceiver;
|
||||
|
||||
|
||||
public class VoiceUiIntentHandler implements IntentHandler {
|
||||
|
||||
private static final String TAG = "VoiceUiIntentHandler";
|
||||
|
||||
@Override
|
||||
public void handle( Context context, Intent intent ) {
|
||||
String val = intent.getStringExtra( MogoReceiver.PARRAM_WAKE_STATUS );
|
||||
if ( TextUtils.equals( val, MogoReceiver.VALUE_DISMISS ) ) {
|
||||
MogoStatusManager.getInstance().setVoiceUIShow( TAG, false );
|
||||
} else if ( TextUtils.equals( val, MogoReceiver.VALUE_SHOW ) ) {
|
||||
MogoStatusManager.getInstance().setVoiceUIShow( TAG, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.mogo.commons.module.receiver;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.mogo.commons.module.intent.IntentHandlerFactory;
|
||||
|
||||
|
||||
public class AccStatusReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive( Context context, Intent intent ) {
|
||||
IntentHandlerFactory.getInstance().handle( context, intent.getAction(), intent );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.mogo.commons.module.receiver;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.mogo.commons.module.intent.IntentManager;
|
||||
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2019-10-03
|
||||
* <p>
|
||||
* 广播接收者
|
||||
*/
|
||||
public class MogoReceiver extends BroadcastReceiver {
|
||||
|
||||
/**
|
||||
* 语音
|
||||
*/
|
||||
public static final String VOICE_ACTION = "com.zhidao.speech.awake.notify";
|
||||
public static final String PARAM_COMMAND = "command";
|
||||
|
||||
// 小智语音唤醒UI
|
||||
public static final String ACTION_VOICE_UI = "com.zhidao.xiaozhi.wake.status";
|
||||
public static final String PARRAM_WAKE_STATUS = "WAKE_STATUS";
|
||||
public static final String VALUE_DISMISS = "dismiss";
|
||||
public static final String VALUE_SHOW = "show";
|
||||
|
||||
/**
|
||||
* 小智语音准备就绪
|
||||
*/
|
||||
public static final String ACTION_VOICE_READY = "com.zhidao.auto.AIAssist.ready";
|
||||
|
||||
private final IntentManager mMogoIntentManager;
|
||||
|
||||
public MogoReceiver(Context context) {
|
||||
mMogoIntentManager = IntentManager.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
if (TextUtils.equals(VOICE_ACTION, action)) {
|
||||
String cmd = intent.getStringExtra(PARAM_COMMAND);
|
||||
if (!TextUtils.isEmpty(cmd)) {
|
||||
mMogoIntentManager.invoke(cmd, intent);
|
||||
}
|
||||
} else {
|
||||
mMogoIntentManager.invoke(action, intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.mogo.commons.module.status;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-04
|
||||
* <p>
|
||||
* 状态控制器监听
|
||||
*/
|
||||
public interface IMogoStatusChangedListener {
|
||||
|
||||
/**
|
||||
* @param descriptor 状态类型
|
||||
* @param isTrue true - accOn、adas ui show、voice ui show、push ui show、v2x ui show
|
||||
*/
|
||||
void onStatusChanged(StatusDescriptor descriptor, boolean isTrue );
|
||||
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package com.mogo.commons.module.status;
|
||||
|
||||
import com.alibaba.android.arouter.facade.template.IProvider;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-02
|
||||
* <p>
|
||||
* 车机状态
|
||||
*/
|
||||
public interface IMogoStatusManager extends IProvider {
|
||||
|
||||
/**
|
||||
* 是否在vr模式
|
||||
* @return true - 在vr模式 false - 不在vr模式
|
||||
*/
|
||||
boolean isVrMode();
|
||||
|
||||
/**
|
||||
* 小智语音 UI 是否在展示
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isVoiceShow();
|
||||
|
||||
/**
|
||||
* v2x UI 是否在展示
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isV2XShow();
|
||||
|
||||
/**
|
||||
* 是否开机
|
||||
*
|
||||
* @return true - 开机 false - 关机
|
||||
*/
|
||||
boolean isAccOn();
|
||||
|
||||
/**
|
||||
* 主页是否显示
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isMainPageOnResume();
|
||||
|
||||
/**
|
||||
* 主页是否在后台运行
|
||||
*
|
||||
* @return true-在后台,false-不在后台
|
||||
*/
|
||||
boolean isMainPageIsBackground();
|
||||
|
||||
/**
|
||||
* 主页是否已启动
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isMainPageLaunched();
|
||||
|
||||
/**
|
||||
* 设置vrMode状态
|
||||
* @param tag 业务类型
|
||||
* @param vrMode true - 在vr模式 false 不在vr模式
|
||||
*/
|
||||
void setVrMode(String tag, boolean vrMode);
|
||||
|
||||
/**
|
||||
* 设置小智语音UI状态
|
||||
*
|
||||
* @param tag 业务类型
|
||||
* @param show true - 显示 false - 隐藏
|
||||
*/
|
||||
void setVoiceUIShow( String tag, boolean show );
|
||||
|
||||
/**
|
||||
* 设置 V2X UI 状态
|
||||
* <p>
|
||||
*
|
||||
* @param tag 业务类型
|
||||
* @param show true - 显示 false - 隐藏
|
||||
*/
|
||||
void setV2XUIShow( String tag, boolean show );
|
||||
|
||||
/**
|
||||
* 设置 acc 状态
|
||||
*
|
||||
* @param tag 业务类型
|
||||
* @param isOn true - on, false - off
|
||||
*/
|
||||
void setAccStatus( String tag, boolean isOn );
|
||||
|
||||
/**
|
||||
* 主页 resume 状态
|
||||
*
|
||||
* @param tag
|
||||
* @param resume
|
||||
*/
|
||||
void setMainPageResumeStatus( String tag, boolean resume );
|
||||
|
||||
/**
|
||||
* 主页 后台运行 状态
|
||||
*
|
||||
* @param tag 控制来源
|
||||
* @param isBackground true-在后台运行,false-不在后台运行(也可能是挂了)
|
||||
*/
|
||||
void setMainPageIsBackgroundStatus( String tag, boolean isBackground );
|
||||
|
||||
/**
|
||||
* 设置小智语音状态
|
||||
*
|
||||
* @param tag
|
||||
* @param ready
|
||||
*/
|
||||
void setAIAssistReady( String tag, boolean ready );
|
||||
|
||||
/**
|
||||
* 设置求助状态
|
||||
*
|
||||
* @param tag
|
||||
* @param seekHelping
|
||||
*/
|
||||
void setSeekHelping( String tag, boolean seekHelping );
|
||||
|
||||
/**
|
||||
* 设置主页是否启动
|
||||
*
|
||||
* @param tag
|
||||
* @param launched
|
||||
*/
|
||||
void setMainPageLaunchedStatus( String tag, boolean launched );
|
||||
|
||||
/**
|
||||
* 注册监听
|
||||
*
|
||||
* @param tag 业务类型
|
||||
* @param descriptor 监听类型
|
||||
* @param listener 监听回调
|
||||
*/
|
||||
void registerStatusChangedListener(String tag, StatusDescriptor descriptor, IMogoStatusChangedListener listener );
|
||||
|
||||
/**
|
||||
* 注销
|
||||
*
|
||||
* @param tag 业务类型
|
||||
* @param descriptor 注销类型
|
||||
* @param listener 注销回调
|
||||
*/
|
||||
void unregisterStatusChangedListener( String tag, StatusDescriptor descriptor, IMogoStatusChangedListener listener );
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.mogo.commons.module.status;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-04
|
||||
* <p>
|
||||
* 状态控制器监听
|
||||
*/
|
||||
public interface IMogoStickyStatusChangedListener extends IMogoStatusChangedListener {
|
||||
|
||||
/**
|
||||
* 是否需要黏性状态: 先改变状态,后注册监听
|
||||
*
|
||||
* @param descriptor 状态
|
||||
* @return 默认不需要
|
||||
*/
|
||||
boolean requestStickyStatus( StatusDescriptor descriptor );
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
package com.mogo.commons.module.status;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-02
|
||||
* <p>
|
||||
* 状态控制器
|
||||
*/
|
||||
public class MogoStatusManager implements IMogoStatusManager {
|
||||
|
||||
private static volatile MogoStatusManager sInstance;
|
||||
private static final byte[] obj = new byte[0];
|
||||
|
||||
private MogoStatusManager() {
|
||||
}
|
||||
|
||||
public static MogoStatusManager getInstance() {
|
||||
if (sInstance == null) {
|
||||
synchronized (obj) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new MogoStatusManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 状态记录
|
||||
*/
|
||||
private static final Map<StatusDescriptor, Boolean> mStatus = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 回调集合
|
||||
*/
|
||||
private static final Map<StatusDescriptor, List<IMogoStatusChangedListener>> mListeners = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 状态类型修改记录
|
||||
*/
|
||||
private static final Map<StatusDescriptor, String> mModifier = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public boolean isVoiceShow() {
|
||||
return get_bool_val(StatusDescriptor.VOICE_UI);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVrMode() {
|
||||
return get_bool_val(StatusDescriptor.VR_MODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isV2XShow() {
|
||||
return get_bool_val(StatusDescriptor.V2X_UI);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccOn() {
|
||||
return get_bool_val(StatusDescriptor.ACC_STATUS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMainPageOnResume() {
|
||||
return get_bool_val(StatusDescriptor.MAIN_PAGE_RESUME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMainPageIsBackground() {
|
||||
return get_bool_val(StatusDescriptor.MAIN_PAGE_IS_BACKGROUND);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMainPageLaunched() {
|
||||
return get_bool_val(StatusDescriptor.MAIN_PAGE_CREATED);
|
||||
}
|
||||
|
||||
private boolean get_bool_val(StatusDescriptor descriptor) {
|
||||
Boolean val = mStatus.get(descriptor);
|
||||
return val != null && val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVrMode(String tag, boolean vrMode) {
|
||||
doSetStatus(tag, StatusDescriptor.VR_MODE, vrMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVoiceUIShow(String tag, boolean show) {
|
||||
doSetStatus(tag, StatusDescriptor.VOICE_UI, show);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setV2XUIShow(String tag, boolean show) {
|
||||
doSetStatus(tag, StatusDescriptor.V2X_UI, show);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAccStatus(String tag, boolean isOn) {
|
||||
doSetStatus(tag, StatusDescriptor.ACC_STATUS, isOn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMainPageResumeStatus(String tag, boolean resume) {
|
||||
doSetStatus(tag, StatusDescriptor.MAIN_PAGE_RESUME, resume);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMainPageIsBackgroundStatus(String tag, boolean isBackground) {
|
||||
doSetStatus(tag, StatusDescriptor.MAIN_PAGE_IS_BACKGROUND, isBackground);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAIAssistReady(String tag, boolean ready) {
|
||||
doSetStatus(tag, StatusDescriptor.AI_ASSIST_READY, ready);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSeekHelping(String tag, boolean seekHelping) {
|
||||
doSetStatus(tag, StatusDescriptor.SEEK_HELPING, seekHelping);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMainPageLaunchedStatus(String tag, boolean launched) {
|
||||
doSetStatus(tag, StatusDescriptor.MAIN_PAGE_CREATED, launched);
|
||||
}
|
||||
|
||||
private void doSetStatus(String tag, StatusDescriptor target, boolean value) {
|
||||
mStatus.put(target, value);
|
||||
invokeStatusChangedListener(target, value);
|
||||
recordStatusModifier(tag, target);
|
||||
}
|
||||
|
||||
private void invokeStatusChangedListener(StatusDescriptor descriptor, boolean status) {
|
||||
List<IMogoStatusChangedListener> listenerList = mListeners.get(descriptor);
|
||||
if (listenerList != null && listenerList.size() > 0) {
|
||||
IMogoStatusChangedListener[] listeners = new IMogoStatusChangedListener[listenerList.size()];
|
||||
listenerList.toArray(listeners);
|
||||
for (IMogoStatusChangedListener listener : listeners) {
|
||||
if (listener != null) {
|
||||
listener.onStatusChanged(descriptor, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void recordStatusModifier(String tag, StatusDescriptor descriptor) {
|
||||
mModifier.put(descriptor, tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerStatusChangedListener(String tag, StatusDescriptor descriptor, IMogoStatusChangedListener listener) {
|
||||
if (listener == null || descriptor == null) {
|
||||
return;
|
||||
}
|
||||
if (!mListeners.containsKey(descriptor)) {
|
||||
mListeners.put(descriptor, new ArrayList<>());
|
||||
}
|
||||
mListeners.get(descriptor).add(listener);
|
||||
|
||||
if (listener instanceof IMogoStickyStatusChangedListener && ((IMogoStickyStatusChangedListener) listener).requestStickyStatus(descriptor)) {
|
||||
Boolean val = mStatus.get(descriptor);
|
||||
if (val != null) {
|
||||
listener.onStatusChanged(descriptor, get_bool_val(descriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterStatusChangedListener(String tag, StatusDescriptor descriptor, IMogoStatusChangedListener listener) {
|
||||
if (mListeners.get(descriptor) != null) {
|
||||
mListeners.get(descriptor).remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Context context) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.mogo.commons.module.status;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-04
|
||||
* <p>
|
||||
* 状态描述
|
||||
*/
|
||||
public enum StatusDescriptor {
|
||||
|
||||
/**
|
||||
* v2x UI
|
||||
*/
|
||||
V2X_UI,
|
||||
|
||||
/**
|
||||
* 小智语音交互 UI
|
||||
*/
|
||||
VOICE_UI,
|
||||
|
||||
/**
|
||||
* 开机状态
|
||||
*/
|
||||
ACC_STATUS,
|
||||
|
||||
/**
|
||||
* 主页 resume 状态
|
||||
*/
|
||||
MAIN_PAGE_RESUME,
|
||||
|
||||
/**
|
||||
* 主页 isBackground 状态
|
||||
*/
|
||||
MAIN_PAGE_IS_BACKGROUND,
|
||||
|
||||
/**
|
||||
* 小智语音状态
|
||||
*/
|
||||
AI_ASSIST_READY,
|
||||
|
||||
/**
|
||||
* 求助状态
|
||||
*/
|
||||
SEEK_HELPING,
|
||||
|
||||
/**
|
||||
* 是否已经进入过主页
|
||||
*/
|
||||
MAIN_PAGE_CREATED,
|
||||
|
||||
/**
|
||||
* 是否已经进入vr模式
|
||||
*/
|
||||
VR_MODE,
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package com.mogo.commons.utils;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.mogo.commons.debug.DebugConfig;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-03-26
|
||||
* <p>
|
||||
* 车机类型
|
||||
*/
|
||||
public class CarSeries {
|
||||
|
||||
private static boolean invokeFlag = false;
|
||||
private static boolean isF8xxSeries = false;
|
||||
|
||||
public static boolean isF8xxSeries() {
|
||||
if ( invokeFlag ) {
|
||||
return isF8xxSeries;
|
||||
}
|
||||
isF8xxSeries = DebugConfig.getProductFlavor().startsWith( "f" );
|
||||
invokeFlag = true;
|
||||
return isF8xxSeries;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static final int CAR_SERIES_C80X = 10;
|
||||
@Deprecated
|
||||
public static final int CAR_SERIES_D80X = 20;
|
||||
@Deprecated
|
||||
public static final int CAR_SERIES_D81X = 21;
|
||||
@Deprecated
|
||||
public static final int CAR_SERIES_D82X = 22;
|
||||
@Deprecated
|
||||
public static final int CAR_SERIES_D84X = 23;
|
||||
@Deprecated
|
||||
public static final int CAR_SERIES_F80X = 30;
|
||||
@Deprecated
|
||||
public static final int CAR_SERIES_G80X = 40;
|
||||
@Deprecated
|
||||
public static final int CAR_SERIES_E84X = 50;
|
||||
@Deprecated
|
||||
public static final int CAR_SERIES_E84XCD = 51;
|
||||
@Deprecated
|
||||
public static final int CAR_SERIES_E85X = 50;
|
||||
@Deprecated
|
||||
public static final int CAR_SERIES_E85XCD = 51;
|
||||
@Deprecated
|
||||
public static final int CAR_SERIES_E85XJD = 51;
|
||||
|
||||
@Deprecated
|
||||
public static int CAR_SERIES = 0;
|
||||
|
||||
/**
|
||||
* Deprecated.
|
||||
* Use {@link DebugConfig#getProductFlavor()} instead.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public static int getSeries() {
|
||||
if ( CAR_SERIES != 0 ) {
|
||||
return CAR_SERIES;
|
||||
}
|
||||
synchronized ( CarSeries.class ) {
|
||||
if ( CAR_SERIES != 0 ) {
|
||||
return CAR_SERIES;
|
||||
}
|
||||
String device = get( "ro.fota.device" );
|
||||
if ( TextUtils.isEmpty( device ) ) {
|
||||
return CAR_SERIES_F80X;
|
||||
}
|
||||
|
||||
if ( "FG166".equals( device ) ) {
|
||||
CAR_SERIES = CAR_SERIES_C80X;
|
||||
} else if ( "D801-802".equals( device ) ) {
|
||||
CAR_SERIES = CAR_SERIES_D80X;
|
||||
} else if ( "D801B-802B".equals( device ) ) {
|
||||
// 2+16G
|
||||
CAR_SERIES = CAR_SERIES_D80X;
|
||||
} else if ( "D811-812".equals( device ) ) {
|
||||
CAR_SERIES = CAR_SERIES_D81X;
|
||||
} else if ( "D821-822".equals( device ) ) {
|
||||
CAR_SERIES = CAR_SERIES_D82X;
|
||||
} else if ( "D841-842".equals( device ) ) {
|
||||
CAR_SERIES = CAR_SERIES_D84X;
|
||||
} else if ( "G801-802".equals( device ) ) {
|
||||
CAR_SERIES = CAR_SERIES_G80X;
|
||||
} else if ( "F801-802".equals( device ) ) {
|
||||
CAR_SERIES = CAR_SERIES_F80X;
|
||||
} else if ( "E841-842".equals( device ) ) {
|
||||
CAR_SERIES = CAR_SERIES_E84X;
|
||||
} else if ( "E84XCD".equals( device ) ) {
|
||||
CAR_SERIES = CAR_SERIES_E84XCD;
|
||||
} else if ( "E851-852".equals( device ) ) {
|
||||
CAR_SERIES = CAR_SERIES_E85X;
|
||||
} else if ( "E85XCD".equals( device ) ) {
|
||||
CAR_SERIES = CAR_SERIES_E85XCD;
|
||||
} else if ( "E85XJD".equals( device ) ) {
|
||||
CAR_SERIES = CAR_SERIES_E85XJD;
|
||||
} else if ( device.startsWith( "E85" ) ) {
|
||||
CAR_SERIES = CAR_SERIES_E85XJD;
|
||||
} else {
|
||||
CAR_SERIES = CAR_SERIES_F80X;
|
||||
}
|
||||
return CAR_SERIES;
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private static String get( String key ) {
|
||||
String value = "";
|
||||
try {
|
||||
Class< ? > c = Class.forName( "android.os.SystemProperties" );
|
||||
Method get = c.getMethod( "get", new Class[]{String.class, String.class} );
|
||||
value = ( String ) get.invoke( c, new Object[]{key, "unknown"} );
|
||||
} catch ( Exception e ) {
|
||||
value = "";
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package com.mogo.commons.utils;
|
||||
|
||||
import static java.lang.Math.PI;
|
||||
|
||||
import android.util.Pair;
|
||||
|
||||
/**
|
||||
* author : donghongyu
|
||||
* e-mail : 1358506549@qq.com
|
||||
* date : 2020/4/14 1:02 PM
|
||||
* desc : 计算车辆驾驶方向的工具类
|
||||
* version: 1.0
|
||||
*/
|
||||
public class DrivingDirectionUtils {
|
||||
|
||||
public static long getDegreeOfCar2Poi2(double x1, double y1, double x2, double y2, double x1_angle) {
|
||||
Pair<Double, Double> newPoint = calculateNewPoint(x1, y1, x1_angle, 10);
|
||||
if (newPoint != null) {
|
||||
double angle = getAngle(x1, y1, newPoint.first, newPoint.second, x2, y2);
|
||||
return Math.round(angle + 0.5);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static double distance(double x1, double y1, double x2, double y2) {
|
||||
return Math.sqrt(Math.pow(x1 - x2, 2.0) + Math.pow(y1 - y2, 2.0));
|
||||
}
|
||||
|
||||
public static double getAngle(double sx, double sy, double x1, double y1, double x2, double y2) {
|
||||
x1 = x1 - sx;
|
||||
y1 = y1 - sy;
|
||||
x2 = x2 - sx;
|
||||
y2 = y2 - sy;
|
||||
double product = x1 * x2 + y1 * y2;
|
||||
double radians = Math.acos(product / (Math.sqrt(Math.pow(x1, 2.0) + Math.pow(y1, 2.0)) * Math.sqrt(Math.pow(x2, 2.0) + Math.pow(y2, 2.0))));
|
||||
return Math.toDegrees(radians);
|
||||
}
|
||||
|
||||
public static Pair<Double, Double> calculateNewPoint(double x, double y, double angle, double distance) {
|
||||
if (distance == 0) {
|
||||
return null;
|
||||
}
|
||||
double radian = Math.toRadians(angle);
|
||||
double radianCandle = Math.toRadians(90.0 - angle);
|
||||
double nX = x + distance * Math.sin(radian) / 100000.0;
|
||||
double nY = y + distance * Math.sin(radianCandle) / 100000.0;
|
||||
return Pair.create(nX, nY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算车辆行驶方向 与 poi点到车辆的连线 间的夹角
|
||||
*
|
||||
* @param carLon 车辆位置 lon
|
||||
* @param carLat 车辆位置 lat
|
||||
* @param poiLon poi 位置 lon
|
||||
* @param poiLat poi 位置 lat
|
||||
* @param carAngle 车辆行驶方向
|
||||
* @return
|
||||
*/
|
||||
public static int getDegreeOfCar2Poi(double carLon, double carLat, double poiLon, double poiLat, int carAngle) {
|
||||
int poiAngle = 0;
|
||||
// 以子午线作为y轴 计算两点的余切 再将余切值转化为角度
|
||||
double _angle = Math.atan2(Math.abs(carLon - poiLon), Math.abs(carLat - poiLat)) * (180 / PI);
|
||||
if (poiLon > carLon) {
|
||||
// poi 在 车辆位置的第1象限
|
||||
if (poiLat > carLat) {
|
||||
poiAngle = (int) _angle;
|
||||
}
|
||||
// poi 在 车辆位置的第2象限
|
||||
else {
|
||||
poiAngle = 180 - (int) _angle;
|
||||
}
|
||||
} else {
|
||||
// poi 在 车辆位置的第3象限
|
||||
if (poiLat < carLat) {
|
||||
poiAngle = (int) _angle + 180;
|
||||
}
|
||||
// poi 在 车辆位置的第4象限
|
||||
else {
|
||||
poiAngle = 360 - (int) _angle;
|
||||
}
|
||||
}
|
||||
return calculationAngle(poiAngle, carAngle);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算两个行驶方向间的夹角 计算结果小于180度
|
||||
*
|
||||
* @param angle0
|
||||
* @param angle1
|
||||
* @return
|
||||
*/
|
||||
public static int calculationAngle(int angle0, int angle1) {
|
||||
// 获取两方向间夹角
|
||||
int angle = Math.abs(angle0 - angle1);
|
||||
if (angle > 180) {
|
||||
int minAngle = Math.min(angle0, angle1);
|
||||
int maxAngle = Math.max(angle0, angle1);
|
||||
return 180 - Math.abs(minAngle + 180 - maxAngle);
|
||||
} else {
|
||||
return angle;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算车辆行驶方向角度,起点&终点经纬度
|
||||
*
|
||||
* @param carLat 车辆位置 lat
|
||||
* @param carLon 车辆位置 lon
|
||||
* @param poiLat poi 位置 lat
|
||||
* @param poiLon poi 位置 lon
|
||||
*/
|
||||
public static int getCarAngle(double carLat, double carLon, double poiLat, double poiLon) {
|
||||
int poiAngle = 0;
|
||||
// 以子午线作为y轴 计算两点的余切 再将余切值转化为角度
|
||||
double _angle = Math.atan2(Math.abs(carLon - poiLon), Math.abs(carLat - poiLat)) * (180 / PI);
|
||||
|
||||
if (poiLon > carLon) {
|
||||
// poi 在 车辆位置的第1象限
|
||||
if (poiLat > carLat) {
|
||||
poiAngle = (int) _angle;
|
||||
}
|
||||
// poi 在 车辆位置的第2象限
|
||||
else {
|
||||
poiAngle = 180 - (int) _angle;
|
||||
}
|
||||
} else {
|
||||
// poi 在 车辆位置的第3象限
|
||||
if (poiLat < carLat) {
|
||||
poiAngle = (int) _angle + 180;
|
||||
}
|
||||
// poi 在 车辆位置的第4象限
|
||||
else {
|
||||
poiAngle = 360 - (int) _angle;
|
||||
}
|
||||
}
|
||||
|
||||
if (poiAngle >= 355) {
|
||||
poiAngle = 0;
|
||||
}
|
||||
return poiAngle;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算连两个角度差值
|
||||
*
|
||||
* @param angle1 角度1
|
||||
* @param angle2 角度2
|
||||
* @return 差值
|
||||
*/
|
||||
public static double getAngleDiff(double angle1, double angle2) {
|
||||
// 两个角度差值较小
|
||||
return 180 - Math.abs(Math.abs(angle1 - angle2) - 180);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
package com.mogo.commons.utils;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
/**
|
||||
* 莫顿编码
|
||||
*
|
||||
* @author linyang
|
||||
* @since 2020.07.09
|
||||
*/
|
||||
public class MortonCode {
|
||||
|
||||
/**
|
||||
* morton 转 经纬度 时的中间常量
|
||||
*/
|
||||
private static final long NDS_180_DEGREES = 0x7fffffff;
|
||||
|
||||
/**
|
||||
* morton 转 经纬度 时的中间常量
|
||||
*/
|
||||
private static final long NDS_360_DEGREES = 4294967295L;
|
||||
|
||||
/**
|
||||
* morton 转 经纬度 时的中间常量
|
||||
*/
|
||||
private static final long NDS_90_DEGREES = 0x3fffffff;
|
||||
|
||||
/**
|
||||
* 经纬度转 morton 时的中间常量
|
||||
*/
|
||||
private static final double RULE_MORTON = Math.pow( 2, 32 ) / 360;
|
||||
|
||||
/**
|
||||
* morton 转 经纬度 时的中间常量
|
||||
*/
|
||||
private static final double RULE_MORTON_TO_LONLAT = 360.0 / Math.pow( 2, 32 );
|
||||
|
||||
/**
|
||||
* @param lon
|
||||
* @param lat
|
||||
* @return
|
||||
*/
|
||||
public static long wrapEncodeMorton( Double lon, Double lat ) {
|
||||
DecimalFormat decimalFormat = new DecimalFormat( "#.######" );
|
||||
return encodeMorton( Double.valueOf( decimalFormat.format( lon ) ),
|
||||
Double.valueOf( decimalFormat.format( lat ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* 编码 morton code
|
||||
*
|
||||
* @param lon
|
||||
* @param lat
|
||||
* @return
|
||||
*/
|
||||
public static long encodeMorton( Double lon, Double lat ) {
|
||||
|
||||
Long bit = 1L;
|
||||
long mortonCode = 0L;
|
||||
long x = ( long ) ( lon * RULE_MORTON );
|
||||
long y = ( long ) ( lat * RULE_MORTON );
|
||||
|
||||
if ( y < 0 ) {
|
||||
y += 0x7FFFFFFF;
|
||||
}
|
||||
y = y << 1;
|
||||
for ( int i = 0; i < 32; i++ ) {
|
||||
// x-part
|
||||
mortonCode = mortonCode | ( x & bit );
|
||||
x = x << 1;
|
||||
bit = bit << 1;
|
||||
// y-part
|
||||
mortonCode = mortonCode | ( y & bit );
|
||||
y = y << 1;
|
||||
bit = bit << 1;
|
||||
}
|
||||
|
||||
return mortonCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将莫顿码解码为坐标
|
||||
*
|
||||
* @param mortonCode
|
||||
* @return
|
||||
*/
|
||||
public static double[] decodeMorton( long mortonCode ) {
|
||||
long[] midPoint = mortonCodeToCoord( mortonCode );
|
||||
normalizeCoord( midPoint );
|
||||
double[] point = new double[2];
|
||||
|
||||
// 将经纬度长整数转化为 浮点类型
|
||||
point[0] = midPoint[0] * RULE_MORTON_TO_LONLAT;
|
||||
point[1] = midPoint[1] * RULE_MORTON_TO_LONLAT;
|
||||
return point;
|
||||
}
|
||||
|
||||
/**
|
||||
* 莫顿码分别拆解为 编码后的经纬度长整数
|
||||
*
|
||||
* @param mortonCode
|
||||
* @return
|
||||
*/
|
||||
private static long[] mortonCodeToCoord( long mortonCode ) {
|
||||
long bit = 1L;
|
||||
long[] longPoint = new long[2];
|
||||
|
||||
for ( int i = 0; i < 32; i++ ) {
|
||||
longPoint[0] |= mortonCode & bit;
|
||||
mortonCode >>= 1;
|
||||
longPoint[1] |= mortonCode & bit;
|
||||
bit <<= 1;
|
||||
}
|
||||
return longPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对编码后的经纬度长整数进行解码
|
||||
*
|
||||
* @param midPoint
|
||||
*/
|
||||
private static void normalizeCoord( long[] midPoint ) {
|
||||
// if x > 180 degrees, then subtract 360 degrees
|
||||
if ( midPoint[0] > NDS_180_DEGREES ) {
|
||||
midPoint[0] -=
|
||||
NDS_360_DEGREES + 1; // add 1 because 0 must be counted as well
|
||||
} else if ( midPoint[0] < -NDS_180_DEGREES ) // if x < 180 , x += 360
|
||||
{
|
||||
midPoint[0] +=
|
||||
NDS_360_DEGREES + 1; // add 1 because 0 must be counted as well
|
||||
}
|
||||
|
||||
// if y > 90 degrees, then subtract 180 degrees
|
||||
if ( midPoint[1] > NDS_90_DEGREES ) {
|
||||
midPoint[1] -=
|
||||
NDS_180_DEGREES + 1; // add 1 because 0 must be counted as well
|
||||
} else if ( midPoint[1] < -NDS_90_DEGREES ) // if y < 90, y += 180
|
||||
{
|
||||
midPoint[1] +=
|
||||
NDS_180_DEGREES + 1; // add 1 because 0 must be counted as well
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
public static void main( String[] args ) {
|
||||
System.out.println( encodeMorton( 116.39584, 39.98152 ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.mogo.commons.utils;
|
||||
|
||||
import com.mogo.eagle.core.data.map.MogoLatLng;
|
||||
|
||||
/**
|
||||
* @author liujing
|
||||
* @description 描述
|
||||
* @since: 2021/4/13
|
||||
*/
|
||||
public class Trigonometric {
|
||||
private final static double radius_b = 6378137;//大半径
|
||||
private final static double radius_s = 6356725;//小半径
|
||||
private static double mRadLo;
|
||||
private static double mRadLa;
|
||||
private static double Ec;
|
||||
private static double Ed;
|
||||
|
||||
/**
|
||||
* 计算两点间的角度
|
||||
*/
|
||||
public static double getAngle(double lon1, double lat1, double lon2,
|
||||
double lat2) {
|
||||
double fLat = Math.PI * (lat1) / 180.0;
|
||||
double fLng = Math.PI * (lon1) / 180.0;
|
||||
double tLat = Math.PI * (lat2) / 180.0;
|
||||
double tLng = Math.PI * (lon2) / 180.0;
|
||||
|
||||
double degree = (Math.atan2(Math.sin(tLng - fLng) * Math.cos(tLat), Math.cos(fLat) * Math.sin(tLat) -
|
||||
Math.sin(fLat) * Math.cos(tLat) * Math.cos(tLng - fLng))) * 180.0 / Math.PI;
|
||||
if (degree >= 0) {
|
||||
return degree;
|
||||
} else {
|
||||
return 360 + degree;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据角度获取指定距离点的经纬度
|
||||
*/
|
||||
public static MogoLatLng getNewLocation(double lon, double lat, double distance, double angle) {
|
||||
mRadLo = lon * Math.PI / 180.;
|
||||
mRadLa = lat * Math.PI / 180.;
|
||||
Ec = radius_s + (radius_b - radius_s) * (90. - lat) / 90;
|
||||
Ed = Ec * Math.cos(mRadLa);
|
||||
|
||||
double dx = distance * Math.sin(Math.toRadians(angle));
|
||||
double dy = distance * Math.cos(Math.toRadians(angle));
|
||||
double lon_new = (dx / Ed + mRadLo) * 180. / Math.PI;
|
||||
double lat_new = (dy / Ec + mRadLa) * 180. / Math.PI;
|
||||
return new MogoLatLng(lat_new, lon_new);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.mogo.commons.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.Scroller;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020/10/19
|
||||
*
|
||||
* 描述
|
||||
*/
|
||||
class ViewPagerSpeedScroller extends Scroller {
|
||||
|
||||
private int mFixedDuration = 1500;
|
||||
|
||||
public ViewPagerSpeedScroller( Context context ) {
|
||||
super( context );
|
||||
}
|
||||
|
||||
public ViewPagerSpeedScroller( Context context, Interpolator interpolator ) {
|
||||
super( context, interpolator );
|
||||
}
|
||||
|
||||
public ViewPagerSpeedScroller( Context context, Interpolator interpolator, boolean flywheel ) {
|
||||
super( context, interpolator, flywheel );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startScroll( int startX, int startY, int dx, int dy ) {
|
||||
startScroll( startX, startY, dx, dy, mFixedDuration );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startScroll( int startX, int startY, int dx, int dy, int duration ) {
|
||||
super.startScroll( startX, startY, dx, dy, mFixedDuration );
|
||||
}
|
||||
|
||||
public void setFixedDuration( int duration ) {
|
||||
this.mFixedDuration = duration;
|
||||
}
|
||||
|
||||
public static void attach( Context context, Object pager, int duration ) {
|
||||
try {
|
||||
Field filed = pager.getClass().getDeclaredField( "mScroller" );
|
||||
filed.setAccessible( true );
|
||||
ViewPagerSpeedScroller scroller = new ViewPagerSpeedScroller( context, new DecelerateInterpolator() );
|
||||
scroller.setFixedDuration( duration );
|
||||
filed.set( pager, scroller );
|
||||
|
||||
Field field = pager.getClass().getDeclaredField( "mTouchSlop" );
|
||||
field.setAccessible( true );
|
||||
field.setInt( pager, 4 );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user