Merge remote-tracking branch 'origin/feature/v1.0.0' into feature/v1.0.0
# Conflicts: # modules/mogo-module-common/src/main/java/com/mogo/module/common/MogoModulePaths.java
@@ -14,6 +14,7 @@ import com.mogo.map.navi.IMogoNaviListener;
|
||||
import com.mogo.module.common.MogoModulePaths;
|
||||
import com.mogo.service.module.IMogoModuleLifecycle;
|
||||
import com.mogo.service.module.IMogoModuleProvider;
|
||||
import com.mogo.service.module.ModuleType;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
@@ -57,7 +58,7 @@ public class AppsFragmentProvider implements IMogoModuleProvider {
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return IMogoModuleProvider.TYPE_FRAGMENT;
|
||||
return ModuleType.TYPE_APP_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:behavior_hideable="false"
|
||||
app:behavior_peekHeight="50dp"
|
||||
app:behavior_peekHeight="76dp"
|
||||
app:layout_behavior="@string/bottom_sheet_behavior" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/module_apps_id_app_icon"
|
||||
android:layout_width="75dp"
|
||||
android:layout_height="75dp" />
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/module_apps_id_app_name"
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.mogo.module.common;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-03
|
||||
* <p>
|
||||
* 模块类型
|
||||
*/
|
||||
public interface ModuleType {
|
||||
|
||||
/**
|
||||
* 卡片类型 - fragment
|
||||
*/
|
||||
int TYPE_CARD_FRAGMENT = 1;
|
||||
|
||||
/**
|
||||
* 卡片类型 - view
|
||||
*/
|
||||
@Deprecated
|
||||
int TYPE_CARD_VIEW = 2;
|
||||
|
||||
/**
|
||||
* 服务类型的模块
|
||||
*/
|
||||
int TYPE_SERVICE = 3;
|
||||
|
||||
/**
|
||||
* APP 列表模块
|
||||
*/
|
||||
int TYPE_APP_LIST = 4;
|
||||
|
||||
/**
|
||||
* 小智语音形象
|
||||
*/
|
||||
int TYPE_VOICE = 5;
|
||||
|
||||
/**
|
||||
* 地图模块
|
||||
*/
|
||||
int TYPE_MAP = 6;
|
||||
|
||||
/**
|
||||
* 导航模块
|
||||
*/
|
||||
int TYPE_NAVI = 7;
|
||||
|
||||
/**
|
||||
* 小智、天气、时间等
|
||||
*/
|
||||
int TYPE_EXTENSION = 8;
|
||||
}
|
||||
@@ -18,6 +18,10 @@ public class MogoModule {
|
||||
*/
|
||||
private String mName;
|
||||
|
||||
/**
|
||||
* @param path 模块加载路径
|
||||
* @param name 模块名称
|
||||
*/
|
||||
public MogoModule( String path, String name ) {
|
||||
this.mPath = path;
|
||||
this.mName = name;
|
||||
|
||||
@@ -29,22 +29,26 @@ public class MogoModulePaths {
|
||||
@Keep
|
||||
public static final String PATH_MODULE_APPS = "/appslist/ui";
|
||||
|
||||
|
||||
/**
|
||||
* 添加卡片模块
|
||||
*
|
||||
* @param path
|
||||
*/
|
||||
@Deprecated
|
||||
public static void addModule( String path ) {
|
||||
throw new IllegalArgumentException( "this method can't be invoked." );
|
||||
}
|
||||
/**
|
||||
* 搜索页面模块实例化路径
|
||||
*/
|
||||
@Keep
|
||||
public static final String PATH_MODULE_SEARCH= "navi/search/ui";
|
||||
|
||||
|
||||
|
||||
public static void addModule( String path ) {
|
||||
if ( TextUtils.isEmpty( path.replace( " ", "" ) ) ) {
|
||||
throw new IllegalArgumentException( "module path can't be empty or null or blank" );
|
||||
}
|
||||
mMogoModules.add( new MogoModule( path, "" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加卡片模块
|
||||
*
|
||||
* @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" );
|
||||
|
||||
1046
modules/mogo-module-common/src/main/res/values-ldpi/dimens.xml
Normal file
1056
modules/mogo-module-common/src/main/res/values-xhdpi/dimens.xml
Normal file
1
modules/mogo-module-extensions/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
9
modules/mogo-module-extensions/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# launcher头部模块
|
||||
|
||||
## 小智语音
|
||||
|
||||
## 通知
|
||||
|
||||
## 天气
|
||||
|
||||
## 时间
|
||||
60
modules/mogo-module-extensions/build.gradle
Normal file
@@ -0,0 +1,60 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'com.alibaba.arouter'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
buildToolsVersion rootProject.ext.android.buildToolsVersion
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
versionCode Integer.valueOf(VERSION_CODE)
|
||||
versionName getValueFromRootProperties("${project.name.replace("-", "_").toUpperCase()}_VERSION")
|
||||
|
||||
javaCompileOptions {
|
||||
annotationProcessorOptions {
|
||||
arguments = [AROUTER_MODULE_NAME: project.getName()]
|
||||
}
|
||||
}
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles 'consumer-rules.pro'
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
implementation rootProject.ext.dependencies.androidxconstraintlayout
|
||||
implementation rootProject.ext.dependencies.arouter
|
||||
annotationProcessor rootProject.ext.dependencies.aroutercompiler
|
||||
implementation rootProject.ext.dependencies.rxjava
|
||||
implementation rootProject.ext.dependencies.rxandroid
|
||||
if (Boolean.valueOf(RELEASE)) {
|
||||
api rootProject.ext.dependencies.mogomap
|
||||
api rootProject.ext.dependencies.mogomapapi
|
||||
api rootProject.ext.dependencies.mogoutils
|
||||
api rootProject.ext.dependencies.mogocommons
|
||||
api rootProject.ext.dependencies.mogoserviceapi
|
||||
implementation rootProject.ext.dependencies.modulecommon
|
||||
} else {
|
||||
api project(":libraries:mogo-map")
|
||||
api project(":libraries:mogo-map-api")
|
||||
api project(":foudations:mogo-utils")
|
||||
api project(":foudations:mogo-commons")
|
||||
api project(':services:mogo-service-api')
|
||||
implementation project(':modules:mogo-module-common')
|
||||
}
|
||||
}
|
||||
|
||||
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
|
||||
0
modules/mogo-module-extensions/consumer-rules.pro
Normal file
3
modules/mogo-module-extensions/gradle.properties
Normal file
@@ -0,0 +1,3 @@
|
||||
GROUP=com.mogo.module
|
||||
POM_ARTIFACT_ID=module-extensions
|
||||
VERSION_CODE=1
|
||||
21
modules/mogo-module-extensions/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.mogo.module.extensions;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith( AndroidJUnit4.class )
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
|
||||
assertEquals( "com.mogo.module.extensions.test", appContext.getPackageName() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mogo.module.extensions" />
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.mogo.module.extensions;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.mogo.commons.mvp.MvpFragment;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-05
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class ExtensionsFragment extends MvpFragment< ExtensionsView, ExtensionsPresenter > implements ExtensionsView {
|
||||
|
||||
private View mVoiceIcon;
|
||||
private View mVoiceMsg;
|
||||
|
||||
private TextView mTime;
|
||||
private TextView mDate;
|
||||
|
||||
private View mWeatherContainer;
|
||||
private ImageView mWeatherIcon;
|
||||
private TextView mWeatherTemp;
|
||||
private TextView mWeatherDesc;
|
||||
|
||||
private View mMsgContainer;
|
||||
private TextView mMsgCounter;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.module_ext_layout_extensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
mVoiceIcon = findViewById( R.id.module_ext_id_voice );
|
||||
mVoiceMsg = findViewById( R.id.module_ext_id_voice_msg );
|
||||
|
||||
mVoiceIcon.setOnClickListener( new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View v ) {
|
||||
mVoiceMsg.performClick();
|
||||
}
|
||||
} );
|
||||
mVoiceMsg.setOnClickListener( new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View v ) {
|
||||
|
||||
}
|
||||
} );
|
||||
|
||||
mTime = findViewById( R.id.module_ext_id_time );
|
||||
mDate = findViewById( R.id.module_ext_id_date );
|
||||
|
||||
mWeatherContainer = findViewById( R.id.module_ext_id_weather_container );
|
||||
mWeatherIcon = findViewById( R.id.module_ext_id_weather_icon );
|
||||
mWeatherTemp = findViewById( R.id.module_ext_id_weather_temp );
|
||||
mWeatherDesc = findViewById( R.id.module_ext_id_weather_desc );
|
||||
|
||||
mMsgContainer = findViewById( R.id.module_ext_id_msg );
|
||||
mMsgCounter = findViewById( R.id.module_ext_id_msg_counter );
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected ExtensionsPresenter createPresenter() {
|
||||
return new ExtensionsPresenter( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated( @Nullable Bundle savedInstanceState ) {
|
||||
super.onActivityCreated( savedInstanceState );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderTime( String date, String time ) {
|
||||
mDate.setText( date );
|
||||
mTime.setText( time );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderWeatherInfo( String temp, String desc, int iconId ) {
|
||||
boolean hidden = false;
|
||||
if ( iconId != 0 ) {
|
||||
mWeatherIcon.setImageResource( iconId );
|
||||
mWeatherIcon.setVisibility( View.VISIBLE );
|
||||
} else {
|
||||
mWeatherIcon.setVisibility( View.GONE );
|
||||
hidden |= true;
|
||||
}
|
||||
hidden |= TextUtils.isEmpty( temp );
|
||||
hidden |= TextUtils.isEmpty( desc );
|
||||
mWeatherTemp.setText( temp );
|
||||
mWeatherDesc.setText( desc );
|
||||
mWeatherContainer.setVisibility( hidden ? View.GONE : View.VISIBLE );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.mogo.module.extensions;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-05
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class ExtensionsModuleConst {
|
||||
|
||||
public static final String PATH_EXTENSION = "/extension/ui";
|
||||
|
||||
|
||||
public static final String TYPE = "extension";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.mogo.module.extensions;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.alibaba.android.arouter.facade.annotation.Route;
|
||||
import com.mogo.map.listener.IMogoMapListener;
|
||||
import com.mogo.map.location.IMogoLocationListener;
|
||||
import com.mogo.map.navi.IMogoNaviListener;
|
||||
import com.mogo.service.module.IMogoModuleLifecycle;
|
||||
import com.mogo.service.module.IMogoModuleProvider;
|
||||
import com.mogo.service.module.ModuleType;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-05
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
@Route( path = ExtensionsModuleConst.PATH_EXTENSION )
|
||||
public class ExtensionsModuleProvider implements IMogoModuleProvider {
|
||||
|
||||
@Override
|
||||
public Fragment createFragment( Context context, Bundle data ) {
|
||||
ExtensionsFragment fragment = new ExtensionsFragment();
|
||||
fragment.setArguments( data );
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createView( Context context ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getModuleName() {
|
||||
return ExtensionsModuleConst.TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoModuleLifecycle getCardLifecycle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoMapListener getMapListener() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return ModuleType.TYPE_EXTENSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoNaviListener getNaviListener() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoLocationListener getLocationListener() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init( Context context ) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.mogo.module.extensions;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
|
||||
import com.mogo.commons.mvp.Presenter;
|
||||
import com.mogo.module.extensions.weather.Phenomena;
|
||||
import com.mogo.module.extensions.weather.WeatherCallback;
|
||||
import com.mogo.module.extensions.weather.WeatherInfo;
|
||||
import com.mogo.module.extensions.weather.WeatherModel;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-05
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class ExtensionsPresenter extends Presenter< ExtensionsView > implements WeatherCallback {
|
||||
|
||||
private static final String TAG = "ExtensionsPresenter";
|
||||
|
||||
private String[] mWeeks;
|
||||
|
||||
private WeatherModel mWeatherModel;
|
||||
|
||||
/**
|
||||
* 接收时间变化的广播
|
||||
*/
|
||||
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive( Context context, Intent intent ) {
|
||||
try {
|
||||
refreshTimeAndDate();
|
||||
} catch ( Exception e ) {
|
||||
Logger.e( TAG, "error. ", e );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public ExtensionsPresenter( ExtensionsView view ) {
|
||||
super( view );
|
||||
mWeeks = getContext().getResources().getStringArray( R.array.module_ext_str_arr_week );
|
||||
mWeatherModel = new WeatherModel( getContext() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate( @NonNull LifecycleOwner owner ) {
|
||||
super.onCreate( owner );
|
||||
registerTimerReceiver();
|
||||
mWeatherModel.init( this );
|
||||
mWeatherModel.queryWeatherInformation();
|
||||
refreshTimeAndDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册时间变化监听
|
||||
*/
|
||||
private void registerTimerReceiver() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction( Intent.ACTION_TIME_TICK );
|
||||
filter.addAction( Intent.ACTION_TIME_CHANGED );
|
||||
filter.addAction( Intent.ACTION_TIMEZONE_CHANGED );
|
||||
filter.addAction( Intent.ACTION_CONFIGURATION_CHANGED );
|
||||
getContext().registerReceiver( mReceiver, filter );
|
||||
}
|
||||
|
||||
private void refreshTimeAndDate() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
int hour = calendar.get( Calendar.HOUR_OF_DAY );
|
||||
int minute = calendar.get( Calendar.MINUTE );
|
||||
|
||||
int month = calendar.get( Calendar.MONTH );
|
||||
int day = calendar.get( Calendar.DAY_OF_MONTH );
|
||||
int week = calendar.get( Calendar.DAY_OF_WEEK );
|
||||
|
||||
String timeStr = getContext().getResources().getString( R.string.module_ext_str_time_format, hour, minute > 9 ? String.valueOf( minute ) : "0" + minute );
|
||||
String dateStr = getContext().getResources().getString( R.string.module_ext_str_date_format, month + 1, day, mWeeks[week - 1] );
|
||||
mView.renderTime( dateStr, timeStr );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWeatherLoaded( WeatherInfo weatherInfo ) {
|
||||
if ( weatherInfo == null ) {
|
||||
return;
|
||||
}
|
||||
String temp = getContext().getResources().getString( R.string.module_ext_str_weather_temp_format, weatherInfo.getTemperature() );
|
||||
Phenomena phenomena = Phenomena.getById( weatherInfo.getPhenomena() );
|
||||
String desc = phenomena == null ? "" : phenomena.nameCn;
|
||||
int resId = 0;
|
||||
mView.renderWeatherInfo( temp, desc, resId );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy( @NonNull LifecycleOwner owner ) {
|
||||
super.onDestroy( owner );
|
||||
if ( mWeatherModel != null ) {
|
||||
mWeatherModel.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.mogo.module.extensions;
|
||||
|
||||
import com.mogo.commons.mvp.IView;
|
||||
import com.mogo.module.extensions.weather.WeatherInfo;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-05
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public interface ExtensionsView extends IView {
|
||||
|
||||
/**
|
||||
* 刷新日期、时间
|
||||
*
|
||||
* @param date 日期
|
||||
* @param time 时间
|
||||
*/
|
||||
void renderTime( String date, String time );
|
||||
|
||||
/**
|
||||
* 天气信息
|
||||
*
|
||||
* @param desc 天气描述:晴转多云
|
||||
* @param temp 温度
|
||||
* @param iconId 图标
|
||||
*/
|
||||
void renderWeatherInfo( String temp, String desc, int iconId );
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.mogo.module.extensions.weather;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Lzq
|
||||
*/
|
||||
public enum Phenomena {
|
||||
Sunny( "00", "晴", "Sunny" ),
|
||||
Cloudy( "01", "多云", "Cloudy" ),
|
||||
Overcast( "02", "阴", "Overcast" ),
|
||||
|
||||
Shower( "03", "阵雨", "Shower" ),
|
||||
Thundershower( "04", "雷阵雨", "Thundershower" ),
|
||||
ThundershowerWithHail( "05", "雷阵雨伴有冰雹", "Thundershower with hail" ),
|
||||
Sleet( "06", "雨夹雪", "Sleet" ),
|
||||
LightRain( "07", "小雨", "Light rain" ),
|
||||
ModerateRain( "08", "中雨", "Moderate rain" ),
|
||||
HeavyRain( "09", "大雨", "Heavy rain" ),
|
||||
Storm( "10", "暴雨", "Storm" ),
|
||||
HeavyStorm( "11", "大暴雨", "Heavy storm" ),
|
||||
SevereStorm( "12", "特大暴雨", "Severe storm" ),
|
||||
|
||||
SnowFlurry( "13", "阵雪", "Snow flurry" ),
|
||||
LightSnow( "14", "小雪", "Light snow" ),
|
||||
ModerateSnow( "15", "中雪", "Moderate snow" ),
|
||||
HeavySnow( "16", "大雪", "Heavy snow" ),
|
||||
Snowstorm( "17", "暴雪", "Snowstorm" ),
|
||||
|
||||
Foggy( "18", "雾", "Foggy" ),
|
||||
IceRain( "19", "冻雨", "Ice rain" ),
|
||||
Duststorm( "20", "沙尘暴", "Duststorm" ),
|
||||
|
||||
LightToModerateRain( "21", "小到中雨", "Light to moderate rain" ),
|
||||
ModerateToHeavyRain( "22", "中到大雨", "Moderate to heavy rain" ),
|
||||
HeavyRainToStorm( "23", "大到大雨", "Heavy rain to storm" ),
|
||||
StormToHeavyStorm( "24", "暴雨到大暴雨", "Storm to heavy storm" ),
|
||||
HeavyToSevereStorm( "25", "大暴雨到特大暴雨", "Heavy to severe storm" ),
|
||||
|
||||
LightToModerateSnow( "26", "小到中雪", "Light to moderate snow" ),
|
||||
ModerateToHeavySnow( "27", "中到大雪", "Moderate to heavy snow" ),
|
||||
HeavySnowToSnowStorm( "28", "大到暴雪", "Heavy snow to snowstorm" ),
|
||||
|
||||
Dust( "29", "浮尘", "Dust" ),
|
||||
Sand( "30", "扬沙", "Sand" ),
|
||||
SandStorm( "31", "强沙尘暴", "Sandstorm" ),
|
||||
|
||||
Densefog( "32", "浓雾", "Dense fog" ),
|
||||
StrongFog( "49", "强浓雾", "Strong fog" ),
|
||||
DenseFog( "57", "大雾", "Dense fog" ),
|
||||
ExtraHeavyFog( "58", "特强浓雾", "Extra heavy fog" ),
|
||||
|
||||
Haze( "53", "霾", "Haze" ),
|
||||
ModerateHaze( "54", "中度霾", "Moderate haze" ),
|
||||
Severehaze( "55", "重度霾", "Severe haze" ),
|
||||
SevereHaze( "56", "严重霾", "Severe haze" ),
|
||||
|
||||
Unknown( "99", "无", "Unknown" ),
|
||||
|
||||
Rain( "301", "雨", "rain" ),
|
||||
Snow( "302", "雪", "snow" );
|
||||
|
||||
public final String id;
|
||||
public final String nameCn;
|
||||
public final String nameEn;
|
||||
|
||||
Phenomena( String id, String nameCn, String nameEn ) {
|
||||
this.id = id;
|
||||
this.nameCn = nameCn;
|
||||
this.nameEn = nameEn;
|
||||
}
|
||||
|
||||
static Map< String, Phenomena > mPhenomenas;
|
||||
|
||||
static {
|
||||
if ( mPhenomenas == null ) {
|
||||
synchronized ( Phenomena.class ) {
|
||||
if ( mPhenomenas == null ) {
|
||||
mPhenomenas = new HashMap<>();
|
||||
for ( Phenomena weather : Phenomena.values() ) {
|
||||
mPhenomenas.put( weather.id, weather );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized Phenomena getById( String id ) {
|
||||
if ( TextUtils.isEmpty( id ) ) {
|
||||
return null;
|
||||
}
|
||||
return mPhenomenas.get( id );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.mogo.module.extensions.weather;
|
||||
|
||||
public interface WeatherCallback {
|
||||
void onWeatherLoaded( WeatherInfo weatherInfo );
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.mogo.module.extensions.weather;
|
||||
|
||||
/**
|
||||
* 天气
|
||||
*/
|
||||
public class WeatherConstants {
|
||||
|
||||
public final static String WEATHER_URI = "content://com.zhidao.weather/weatherinfo";
|
||||
|
||||
/**
|
||||
* 天气
|
||||
*/
|
||||
public static final String TEMPERATURE = "observetemperature";
|
||||
/**
|
||||
* 气象
|
||||
*/
|
||||
public static final String PHENOMENA = "observephenomena";
|
||||
/**
|
||||
* 风向
|
||||
*/
|
||||
public static final String WIND_DIRECTION = "observewinddirection";
|
||||
/**
|
||||
* 风力
|
||||
*/
|
||||
public static final String WIND_FORCE = "observewindforce";
|
||||
|
||||
/**
|
||||
* 天气消息加载完毕
|
||||
*/
|
||||
public static final int MSG_WEATHER_LOADED = 0x1000;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
package com.mogo.module.extensions.weather;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 天气
|
||||
*/
|
||||
public class WeatherInfo implements Parcelable {
|
||||
/**
|
||||
* 温度
|
||||
*/
|
||||
private String temperature;
|
||||
|
||||
/**
|
||||
* 描述信息
|
||||
*/
|
||||
private String phenomena;
|
||||
|
||||
/**
|
||||
* 风向
|
||||
*/
|
||||
private String windDirection;
|
||||
|
||||
/**
|
||||
* 风力
|
||||
*/
|
||||
private String windForce;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeatherInfo{" +
|
||||
"temperature='" + temperature + '\'' +
|
||||
", phenomena='" + phenomena + '\'' +
|
||||
", windDirection='" + windDirection + '\'' +
|
||||
", windForce='" + windForce + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( Object o ) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( !( o instanceof WeatherInfo ) ) {
|
||||
return false;
|
||||
}
|
||||
WeatherInfo that = ( WeatherInfo ) o;
|
||||
return Objects.equals( temperature, that.temperature ) &&
|
||||
Objects.equals( phenomena, that.phenomena ) &&
|
||||
Objects.equals( windDirection, that.windDirection ) &&
|
||||
Objects.equals( windForce, that.windForce );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash( temperature, phenomena, windDirection, windForce );
|
||||
}
|
||||
|
||||
public WeatherInfo() {
|
||||
}
|
||||
|
||||
public WeatherInfo( String temperature, String phenomena, String windDirection, String windForce ) {
|
||||
this.temperature = temperature;
|
||||
this.phenomena = phenomena;
|
||||
this.windDirection = windDirection;
|
||||
this.windForce = windForce;
|
||||
}
|
||||
|
||||
public String getTemperature() {
|
||||
return temperature;
|
||||
}
|
||||
|
||||
public void setTemperature( String temperature ) {
|
||||
this.temperature = temperature;
|
||||
}
|
||||
|
||||
public String getPhenomena() {
|
||||
return phenomena;
|
||||
}
|
||||
|
||||
public void setPhenomena( String phenomena ) {
|
||||
this.phenomena = phenomena;
|
||||
}
|
||||
|
||||
public String getWindDirection() {
|
||||
return windDirection;
|
||||
}
|
||||
|
||||
public void setWindDirection( String windDirection ) {
|
||||
this.windDirection = windDirection;
|
||||
}
|
||||
|
||||
public String getWindForce() {
|
||||
return windForce;
|
||||
}
|
||||
|
||||
public void setWindForce( String windForce ) {
|
||||
this.windForce = windForce;
|
||||
}
|
||||
|
||||
public boolean isLegal() {
|
||||
return !TextUtils.isEmpty( phenomena )
|
||||
&& !TextUtils.isEmpty( temperature );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel( Parcel dest, int flags ) {
|
||||
dest.writeString( this.temperature );
|
||||
dest.writeString( this.phenomena );
|
||||
dest.writeString( this.windDirection );
|
||||
dest.writeString( this.windForce );
|
||||
}
|
||||
|
||||
protected WeatherInfo( Parcel in ) {
|
||||
this.temperature = in.readString();
|
||||
this.phenomena = in.readString();
|
||||
this.windDirection = in.readString();
|
||||
this.windForce = in.readString();
|
||||
}
|
||||
|
||||
public static final Creator< WeatherInfo > CREATOR = new Creator< WeatherInfo >() {
|
||||
@Override
|
||||
public WeatherInfo createFromParcel( Parcel source ) {
|
||||
return new WeatherInfo( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeatherInfo[] newArray( int size ) {
|
||||
return new WeatherInfo[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
package com.mogo.module.extensions.weather;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.mogo.utils.ThreadPoolService;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-05
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class WeatherModel {
|
||||
|
||||
private static final String TAG = "WeatherModel";
|
||||
|
||||
private Context mContext;
|
||||
|
||||
private Uri mWeatherUri;
|
||||
private Handler mHandler;
|
||||
private ContentResolver mContentResolver;
|
||||
private ContentObserver mContentObserver;
|
||||
private WeatherCallback mCallback;
|
||||
|
||||
public WeatherModel( Context context ) {
|
||||
this.mContext = context;
|
||||
}
|
||||
|
||||
public void init( WeatherCallback callback ) {
|
||||
mCallback = callback;
|
||||
mWeatherUri = Uri.parse( WeatherConstants.WEATHER_URI );
|
||||
mContentResolver = mContext.getContentResolver();
|
||||
mHandler = new Handler( Looper.getMainLooper() ) {
|
||||
@Override
|
||||
public void handleMessage( @NonNull Message msg ) {
|
||||
if ( msg.what == WeatherConstants.MSG_WEATHER_LOADED ) {
|
||||
if ( mCallback != null ) {
|
||||
mCallback.onWeatherLoaded( ( ( WeatherInfo ) msg.obj ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
mContentObserver = new ContentObserver( mHandler ) {
|
||||
@Override
|
||||
public void onChange( boolean selfChange, Uri uri ) {
|
||||
super.onChange( selfChange, uri );
|
||||
try {
|
||||
queryWeatherInformation();
|
||||
} catch ( Exception e ) {
|
||||
Logger.e( TAG, "error. ", e );
|
||||
}
|
||||
}
|
||||
};
|
||||
try {
|
||||
mContentResolver.registerContentObserver( mWeatherUri, false, mContentObserver );
|
||||
} catch ( Exception e ) {
|
||||
Logger.e( TAG, "error when query weather info.", e );
|
||||
}
|
||||
}
|
||||
|
||||
public void queryWeatherInformation() {
|
||||
|
||||
if ( mCallback == null ) {
|
||||
Logger.e( TAG, "WeatherModel#init should invoked " );
|
||||
return;
|
||||
}
|
||||
startNewThreadToQuery();
|
||||
}
|
||||
|
||||
|
||||
private void startNewThreadToQuery() {
|
||||
ThreadPoolService.execute( new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if ( mContentResolver == null ) {
|
||||
return;
|
||||
}
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = mContentResolver.query( mWeatherUri, null, null, null, null, null );
|
||||
} catch ( Exception e ) {
|
||||
return;
|
||||
}
|
||||
if ( cursor == null ) {
|
||||
return;
|
||||
}
|
||||
WeatherInfo weatherInfo = new WeatherInfo();
|
||||
if ( cursor.moveToFirst() ) {
|
||||
int index = cursor.getColumnIndex( WeatherConstants.TEMPERATURE );
|
||||
if ( index != -1 ) {
|
||||
weatherInfo.setTemperature( cursor.getString( index ) );
|
||||
}
|
||||
index = cursor.getColumnIndex( WeatherConstants.PHENOMENA );
|
||||
if ( index != -1 ) {
|
||||
weatherInfo.setPhenomena( cursor.getString( index ) );
|
||||
}
|
||||
index = cursor.getColumnIndex( WeatherConstants.WIND_DIRECTION );
|
||||
if ( index != -1 ) {
|
||||
weatherInfo.setWindDirection( cursor.getString( index ) );
|
||||
}
|
||||
index = cursor.getColumnIndex( WeatherConstants.WIND_FORCE );
|
||||
if ( index != -1 ) {
|
||||
weatherInfo.setWindForce( cursor.getString( index ) );
|
||||
}
|
||||
Message msg = Message.obtain();
|
||||
msg.obj = weatherInfo;
|
||||
msg.what = WeatherConstants.MSG_WEATHER_LOADED;
|
||||
mHandler.sendMessage( msg );
|
||||
}
|
||||
cursor.close();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if ( mContentResolver != null && mContentObserver != null ) {
|
||||
mContentResolver.unregisterContentObserver( mContentObserver );
|
||||
}
|
||||
mContext = null;
|
||||
mWeatherUri = null;
|
||||
mHandler = null;
|
||||
mContentResolver = null;
|
||||
mContentObserver = null;
|
||||
mCallback = null;
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 834 B |
|
After Width: | Height: | Size: 7.1 KiB |
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape>
|
||||
<corners android:radius="90dp" />
|
||||
<solid android:color="#DA2E55" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
||||
@@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="35dp"
|
||||
android:paddingRight="35dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/module_ext_id_voice"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/module_ext_ic_voice"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/module_ext_id_voice_msg"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/module_ext_str_voice_msg"
|
||||
android:textColor="@color/module_ext_color_voice_text"
|
||||
android:textSize="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/module_ext_id_voice"
|
||||
app:layout_constraintLeft_toRightOf="@+id/module_ext_id_voice"
|
||||
app:layout_constraintTop_toTopOf="@+id/module_ext_id_voice" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/module_ext_id_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="24dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="10:10" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/module_ext_id_date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="40dp"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="14dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@+id/module_ext_id_time"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="11月20日 周三" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/module_ext_id_weather_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="13dp"
|
||||
android:gravity="center"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@+id/module_ext_id_date"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/module_ext_id_weather_icon"
|
||||
android:layout_width="22dp"
|
||||
android:layout_height="22dp"
|
||||
tools:src="@drawable/module_ext_ic_voice" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/module_ext_id_weather_temp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="9dp"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="17dp"
|
||||
tools:text="28°" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/module_ext_id_weather_desc"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="13dp"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="14dp"
|
||||
tools:text="晴转多云" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="/"
|
||||
android:textColor="#FFFFFF" />
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/module_ext_id_msg"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="14dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@+id/module_ext_id_weather_container"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/module_ext_ic_message" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/module_ext_id_msg_counter"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_gravity="right"
|
||||
android:background="@drawable/module_ext_drawable_msg_bkg"
|
||||
android:gravity="center"
|
||||
android:textColor="#FFFFFF"
|
||||
android:visibility="invisible"
|
||||
android:textSize="10dp"
|
||||
tools:text="···" />
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="module_ext_color_voice_text">#FFFFFF</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,16 @@
|
||||
<resources>
|
||||
<string name="app_name">mogo-module-extensions</string>
|
||||
<string name="module_ext_str_voice_msg">你好,蘑菇2.0开启智慧互联新世界</string>
|
||||
<string name="module_ext_str_date_format">%1$d月%2$d日 %3$s</string>
|
||||
<string name="module_ext_str_time_format">%1$d:%2$s</string>
|
||||
<string name="module_ext_str_weather_temp_format">%s° </string>
|
||||
<string-array name="module_ext_str_arr_week">
|
||||
<item>周日</item>
|
||||
<item>周一</item>
|
||||
<item>周二</item>
|
||||
<item>周三</item>
|
||||
<item>周四</item>
|
||||
<item>周五</item>
|
||||
<item>周六</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.mogo.module.extensions;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals( 4, 2 + 2 );
|
||||
}
|
||||
}
|
||||
@@ -42,17 +42,21 @@ dependencies {
|
||||
implementation rootProject.ext.dependencies.modulemap
|
||||
implementation rootProject.ext.dependencies.mogoserviceapi
|
||||
implementation rootProject.ext.dependencies.mogoservice
|
||||
implementation rootProject.ext.dependencies.moduleservice
|
||||
implementation rootProject.ext.dependencies.moduleapps
|
||||
implementation rootProject.ext.dependencies.mogoconnection
|
||||
implementation rootProject.ext.dependencies.moduleextensions
|
||||
} else {
|
||||
implementation project(":foudations:mogo-utils")
|
||||
implementation project(":foudations:mogo-commons")
|
||||
implementation project(':modules:mogo-module-common')
|
||||
implementation project(':modules:mogo-module-map')
|
||||
implementation project(':modules:mogo-module-service')
|
||||
implementation project(':services:mogo-service-api')
|
||||
implementation project(':services:mogo-service')
|
||||
implementation project(':modules:mogo-module-apps')
|
||||
implementation project(':foudations:mogo-connection')
|
||||
implementation project(':modules:mogo-module-extensions')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,11 +13,15 @@ import com.mogo.map.location.IMogoLocationListener;
|
||||
import com.mogo.map.location.MogoLocation;
|
||||
import com.mogo.map.marker.IMogoMarker;
|
||||
import com.mogo.map.marker.IMogoMarkerClickListener;
|
||||
import com.mogo.module.common.MogoModule;
|
||||
import com.mogo.module.common.MogoModulePaths;
|
||||
import com.mogo.module.extensions.ExtensionsModuleConst;
|
||||
import com.mogo.module.main.cards.CardModulesAdapter;
|
||||
import com.mogo.module.main.cards.MogoModulesHandler;
|
||||
import com.mogo.module.main.cards.MogoModulesManager;
|
||||
import com.mogo.module.main.cards.OrientedViewPager;
|
||||
import com.mogo.module.main.cards.VerticalStackTransformer;
|
||||
import com.mogo.module.service.ServiceConst;
|
||||
import com.mogo.service.MogoServicePaths;
|
||||
import com.mogo.service.connection.IMogoSocketManager;
|
||||
import com.mogo.service.map.IMogoMapService;
|
||||
@@ -99,11 +103,20 @@ public class MainActivity extends MvpActivity< MainView, MainPresenter > impleme
|
||||
protected void onCreate( @Nullable Bundle savedInstanceState ) {
|
||||
super.onCreate( savedInstanceState );
|
||||
|
||||
MogoModulePaths.addModule( new MogoModule( MogoModulePaths.PATH_MODULE_APPS, MogoModulePaths.PATH_MODULE_APPS ) );
|
||||
MogoModulePaths.addModule( new MogoModule( MogoModulePaths.PATH_MODULE_MAP, MogoModulePaths.PATH_MODULE_MAP ) );
|
||||
MogoModulePaths.addModule( new MogoModule( ServiceConst.PATH_REFRESH_STRATEGY, ServiceConst.PATH_REFRESH_STRATEGY ) );
|
||||
MogoModulePaths.addModule( new MogoModule( ExtensionsModuleConst.PATH_EXTENSION, ExtensionsModuleConst.TYPE ) );
|
||||
|
||||
mMogoModuleHandler = new MogoModulesManager( this );
|
||||
mMogoMapService = ( IMogoMapService ) ARouter.getInstance().build( MogoServicePaths.PATH_SERVICES_MAP ).navigation();
|
||||
if ( mMogoMapService != null ) {
|
||||
mMogoMapService.getHostListenerRegister().registerHostMapListener( mMogoModuleHandler );
|
||||
mMogoMapService.getHostListenerRegister().registerHostNaviListener( mMogoModuleHandler );
|
||||
mMogoMapService.getHostListenerRegister().registerMarkerClickListener( this );
|
||||
}
|
||||
|
||||
mMogoSocketManager = ( IMogoSocketManager ) ARouter.getInstance().build( MogoServicePaths.PATH_SOCKET_MANAGER ).navigation();
|
||||
mMogoSocketManager.init( getApplicationContext(), AppConstants.SOCKET_APP_ID );
|
||||
|
||||
mMogoModuleHandler.loadModules();
|
||||
mMogoModuleHandler.onMapLoadedCallback( new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -111,21 +124,17 @@ public class MainActivity extends MvpActivity< MainView, MainPresenter > impleme
|
||||
loadModules();
|
||||
}
|
||||
} );
|
||||
|
||||
mMogoMapService = ( IMogoMapService ) ARouter.getInstance().build( MogoServicePaths.PATH_SERVICES_MAP ).navigation();
|
||||
if ( mMogoMapService != null ) {
|
||||
mMogoMapService.getHostListenerRegister().registerHostMapListener( mMogoModuleHandler );
|
||||
mMogoMapService.getHostListenerRegister().registerHostNaviListener( mMogoModuleHandler );
|
||||
mMogoMapService.getHostListenerRegister().registerMarkerClickListener( this );
|
||||
}
|
||||
// 加载地图,触发地图加载完毕回调,在初始化其他卡片模块,保证卡片模块可以正确获取地图相关服务。
|
||||
mMogoModuleHandler.loadMap( R.id.module_main_id_map_fragment_container );
|
||||
mMogoModuleHandler.loadAppsList( R.id.module_main_id_fragment_container );
|
||||
mMogoModuleHandler.loadExtensions( R.id.module_main_id_header_fragment_container );
|
||||
|
||||
mLocationClient = mMogoMapService.getSingletonLocationClient( getApplicationContext() );
|
||||
mLocationClient.addLocationListener( this );
|
||||
mLocationClient.start();
|
||||
|
||||
mMogoModuleHandler.loadAppsList( R.id.module_main_id_fragment_container );
|
||||
mMogoSocketManager = ( IMogoSocketManager ) ARouter.getInstance().build( MogoServicePaths.PATH_SOCKET_MANAGER ).navigation();
|
||||
mMogoSocketManager.init( getApplicationContext(), AppConstants.SOCKET_APP_ID );
|
||||
}
|
||||
|
||||
private void loadModules() {
|
||||
|
||||
@@ -24,6 +24,8 @@ public interface MogoModulesHandler extends IMogoMapListener,
|
||||
|
||||
void onMapLoadedCallback( Runnable callback );
|
||||
|
||||
void loadModules();
|
||||
|
||||
/**
|
||||
* 加载卡片
|
||||
*
|
||||
@@ -31,20 +33,6 @@ public interface MogoModulesHandler extends IMogoMapListener,
|
||||
*/
|
||||
List< IMogoModuleProvider > loadCardsModule();
|
||||
|
||||
/**
|
||||
* 加载小智语音
|
||||
*
|
||||
* @param containerId 容器id
|
||||
*/
|
||||
void loadAIAssist( int containerId );
|
||||
|
||||
/**
|
||||
* 加载天气
|
||||
*
|
||||
* @param containerId 容器id
|
||||
*/
|
||||
void loadWeather( int containerId );
|
||||
|
||||
/**
|
||||
* 加载地图
|
||||
*
|
||||
@@ -59,6 +47,13 @@ public interface MogoModulesHandler extends IMogoMapListener,
|
||||
*/
|
||||
void loadAppsList( int containerId );
|
||||
|
||||
/**
|
||||
* 加载头部信息
|
||||
*
|
||||
* @param containerId
|
||||
*/
|
||||
void loadExtensions( int containerId );
|
||||
|
||||
/**
|
||||
* 设置某一个module可用
|
||||
*
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.mogo.module.main.cards;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.text.TextUtils;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
@@ -18,8 +21,11 @@ import com.mogo.map.uicontroller.EnumMapUI;
|
||||
import com.mogo.module.common.MogoModule;
|
||||
import com.mogo.module.common.MogoModulePaths;
|
||||
import com.mogo.module.main.MainActivity;
|
||||
import com.mogo.module.main.receiver.MogoReceiver;
|
||||
import com.mogo.module.service.ServiceConst;
|
||||
import com.mogo.service.module.IMogoModuleLifecycle;
|
||||
import com.mogo.service.module.IMogoModuleProvider;
|
||||
import com.mogo.service.module.ModuleType;
|
||||
import com.mogo.utils.ResourcesHelper;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
@@ -43,17 +49,20 @@ public class MogoModulesManager implements MogoModulesHandler,
|
||||
private static final String TAG = "MogoModulesManager";
|
||||
|
||||
private MainActivity mActivity;
|
||||
private final Map< String, IMogoModuleProvider > mCardProviders = new HashMap<>();
|
||||
private IMogoModuleProvider mMapProvider;
|
||||
private IMogoModuleProvider mAppsListProvider;
|
||||
|
||||
private Map< MogoModule, IMogoModuleProvider > mModuleProviders = new HashMap<>();
|
||||
|
||||
private String mEnableModuleName = null;
|
||||
private Runnable mMapLoadedCallback;
|
||||
|
||||
private BroadcastReceiver mReceiver;
|
||||
|
||||
public MogoModulesManager( MainActivity activity ) {
|
||||
if ( activity == null ) {
|
||||
throw new NullPointerException( "activity can't be null." );
|
||||
}
|
||||
this.mActivity = activity;
|
||||
registerReceiver();
|
||||
}
|
||||
|
||||
private Context getContext() {
|
||||
@@ -64,6 +73,19 @@ public class MogoModulesManager implements MogoModulesHandler,
|
||||
return mActivity.getApplicationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadModules() {
|
||||
final List< MogoModule > modules = MogoModulePaths.getModules();
|
||||
if ( modules != null && !modules.isEmpty() ) {
|
||||
for ( MogoModule module : modules ) {
|
||||
IMogoModuleProvider provider = load( module.getPath() );
|
||||
if ( provider != null ) {
|
||||
mModuleProviders.put( module, provider );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapLoadedCallback( Runnable callback ) {
|
||||
mMapLoadedCallback = callback;
|
||||
@@ -73,40 +95,40 @@ public class MogoModulesManager implements MogoModulesHandler,
|
||||
public List< IMogoModuleProvider > loadCardsModule() {
|
||||
final List< MogoModule > modules = MogoModulePaths.getModules();
|
||||
final ArrayList< IMogoModuleProvider > providers = new ArrayList<>();
|
||||
if ( modules != null && !modules.isEmpty() ) {
|
||||
for ( MogoModule module : modules ) {
|
||||
IMogoModuleProvider provider = load( module.getPath() );
|
||||
for ( MogoModule module : modules ) {
|
||||
IMogoModuleProvider provider = mModuleProviders.get( module );
|
||||
if ( provider.getType() == ModuleType.TYPE_CARD_FRAGMENT ) {
|
||||
providers.add( provider );
|
||||
mCardProviders.put( provider.getModuleName(), provider );
|
||||
}
|
||||
}
|
||||
return providers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAIAssist( int containerId ) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadWeather( int containerId ) {
|
||||
|
||||
}
|
||||
|
||||
private IMogoModuleProvider getModuleProvider( String tag ) {
|
||||
return mCardProviders.get( tag );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadMap( int containerId ) {
|
||||
mMapProvider = load( MogoModulePaths.PATH_MODULE_MAP );
|
||||
addFragment( mMapProvider, containerId );
|
||||
loadModuleByType( ModuleType.TYPE_MAP, containerId );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAppsList( int containerId ) {
|
||||
mAppsListProvider = load( MogoModulePaths.PATH_MODULE_APPS );
|
||||
addFragment( mAppsListProvider, containerId );
|
||||
loadModuleByType( ModuleType.TYPE_APP_LIST, containerId );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadExtensions( int containerId ) {
|
||||
loadModuleByType( ModuleType.TYPE_EXTENSION, containerId );
|
||||
}
|
||||
|
||||
private void loadModuleByType( int type, int containerId ) {
|
||||
if ( mModuleProviders.isEmpty() ) {
|
||||
return;
|
||||
}
|
||||
for ( IMogoModuleProvider value : mModuleProviders.values() ) {
|
||||
if ( value.getType() == type ) {
|
||||
addFragment( value, containerId );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IMogoModuleProvider load( String path ) {
|
||||
@@ -131,14 +153,18 @@ public class MogoModulesManager implements MogoModulesHandler,
|
||||
@Override
|
||||
public void setEnable( String module ) {
|
||||
mEnableModuleName = module;
|
||||
final Set< Map.Entry< String, IMogoModuleProvider > > entries = mCardProviders.entrySet();
|
||||
final Set< Map.Entry< MogoModule, IMogoModuleProvider > > entries = mModuleProviders.entrySet();
|
||||
if ( !entries.isEmpty() ) {
|
||||
for ( Map.Entry< String, IMogoModuleProvider > entry : entries ) {
|
||||
final String key = entry.getKey();
|
||||
for ( Map.Entry< MogoModule, IMogoModuleProvider > entry : entries ) {
|
||||
final MogoModule key = entry.getKey();
|
||||
final IMogoModuleProvider provider = entry.getValue();
|
||||
if ( provider.getType() != ModuleType.TYPE_CARD_FRAGMENT ) {
|
||||
// 仅卡片需要生命周期
|
||||
continue;
|
||||
}
|
||||
final IMogoModuleLifecycle lifecycle = provider.getCardLifecycle();
|
||||
if ( lifecycle != null ) {
|
||||
if ( TextUtils.equals( key, mEnableModuleName ) ) {
|
||||
if ( TextUtils.equals( key.getName(), mEnableModuleName ) ) {
|
||||
lifecycle.onPerform();
|
||||
} else {
|
||||
lifecycle.onDisable();
|
||||
@@ -151,134 +177,259 @@ public class MogoModulesManager implements MogoModulesHandler,
|
||||
|
||||
@Override
|
||||
public void onMapLoaded() {
|
||||
|
||||
if ( mMapLoadedCallback != null ) {
|
||||
mMapLoadedCallback.run();
|
||||
mMapLoadedCallback = null;
|
||||
}
|
||||
|
||||
if ( mEnableModuleName != null ) {
|
||||
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
|
||||
if ( provider != null && provider.getMapListener() != null ) {
|
||||
provider.getMapListener().onMapLoaded();
|
||||
for ( IMogoModuleProvider value : mModuleProviders.values() ) {
|
||||
if ( value.getMapListener() != null ) {
|
||||
value.getMapListener().onMapLoaded();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTouch( MotionEvent motionEvent ) {
|
||||
if ( mEnableModuleName != null ) {
|
||||
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
|
||||
if ( provider != null && provider.getMapListener() != null ) {
|
||||
provider.getMapListener().onTouch( motionEvent );
|
||||
for ( IMogoModuleProvider value : mModuleProviders.values() ) {
|
||||
if ( value.getType() == ModuleType.TYPE_CARD_FRAGMENT ) {
|
||||
if ( mEnableModuleName != null && TextUtils.equals( value.getModuleName(), mEnableModuleName ) ) {
|
||||
if ( value.getMapListener() != null ) {
|
||||
value.getMapListener().onTouch( motionEvent );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( value.getMapListener() != null ) {
|
||||
value.getMapListener().onTouch( motionEvent );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPOIClick( MogoPoi poi ) {
|
||||
if ( mEnableModuleName != null ) {
|
||||
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
|
||||
if ( provider != null && provider.getMapListener() != null ) {
|
||||
provider.getMapListener().onPOIClick( poi );
|
||||
for ( IMogoModuleProvider value : mModuleProviders.values() ) {
|
||||
if ( value.getType() == ModuleType.TYPE_CARD_FRAGMENT ) {
|
||||
if ( mEnableModuleName != null && TextUtils.equals( value.getModuleName(), mEnableModuleName ) ) {
|
||||
if ( value.getMapListener() != null ) {
|
||||
value.getMapListener().onPOIClick( poi );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( value.getMapListener() != null ) {
|
||||
value.getMapListener().onPOIClick( poi );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapClick( MogoLatLng latLng ) {
|
||||
if ( mEnableModuleName != null ) {
|
||||
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
|
||||
if ( provider != null && provider.getMapListener() != null ) {
|
||||
provider.getMapListener().onMapClick( latLng );
|
||||
for ( IMogoModuleProvider value : mModuleProviders.values() ) {
|
||||
if ( value.getType() == ModuleType.TYPE_CARD_FRAGMENT ) {
|
||||
if ( mEnableModuleName != null && TextUtils.equals( value.getModuleName(), mEnableModuleName ) ) {
|
||||
if ( value.getMapListener() != null ) {
|
||||
value.getMapListener().onMapClick( latLng );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( value.getMapListener() != null ) {
|
||||
value.getMapListener().onMapClick( latLng );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLockMap( boolean isLock ) {
|
||||
if ( mEnableModuleName != null ) {
|
||||
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
|
||||
if ( provider != null && provider.getMapListener() != null ) {
|
||||
provider.getMapListener().onLockMap( isLock );
|
||||
for ( IMogoModuleProvider value : mModuleProviders.values() ) {
|
||||
if ( value.getType() == ModuleType.TYPE_CARD_FRAGMENT ) {
|
||||
if ( mEnableModuleName != null && TextUtils.equals( value.getModuleName(), mEnableModuleName ) ) {
|
||||
if ( value.getMapListener() != null ) {
|
||||
value.getMapListener().onLockMap( isLock );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( value.getMapListener() != null ) {
|
||||
value.getMapListener().onLockMap( isLock );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapModeChanged( EnumMapUI ui ) {
|
||||
if ( mEnableModuleName != null ) {
|
||||
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
|
||||
if ( provider != null && provider.getMapListener() != null ) {
|
||||
provider.getMapListener().onMapModeChanged( ui );
|
||||
for ( IMogoModuleProvider value : mModuleProviders.values() ) {
|
||||
if ( value.getType() == ModuleType.TYPE_CARD_FRAGMENT ) {
|
||||
if ( mEnableModuleName != null && TextUtils.equals( value.getModuleName(), mEnableModuleName ) ) {
|
||||
if ( value.getMapListener() != null ) {
|
||||
value.getMapListener().onMapModeChanged( ui );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( value.getMapListener() != null ) {
|
||||
value.getMapListener().onMapModeChanged( ui );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapChanged( MogoLatLng location, float zoom, float tilt, float bearing ) {
|
||||
for ( IMogoModuleProvider value : mModuleProviders.values() ) {
|
||||
if ( value.getType() == ModuleType.TYPE_CARD_FRAGMENT ) {
|
||||
if ( mEnableModuleName != null && TextUtils.equals( value.getModuleName(), mEnableModuleName ) ) {
|
||||
if ( value.getMapListener() != null ) {
|
||||
value.getMapListener().onMapChanged( location, zoom, tilt, bearing );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( value.getMapListener() != null ) {
|
||||
value.getMapListener().onMapChanged( location, zoom, tilt, bearing );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitNaviFailure() {
|
||||
if ( mEnableModuleName != null ) {
|
||||
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
|
||||
if ( provider != null && provider.getNaviListener() != null ) {
|
||||
provider.getNaviListener().onInitNaviFailure();
|
||||
for ( IMogoModuleProvider value : mModuleProviders.values() ) {
|
||||
if ( value.getType() == ModuleType.TYPE_CARD_FRAGMENT ) {
|
||||
if ( mEnableModuleName != null && TextUtils.equals( value.getModuleName(), mEnableModuleName ) ) {
|
||||
if ( value.getNaviListener() != null ) {
|
||||
value.getNaviListener().onInitNaviFailure();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( value.getNaviListener() != null ) {
|
||||
value.getNaviListener().onInitNaviFailure();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitNaviSuccess() {
|
||||
if ( mEnableModuleName != null ) {
|
||||
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
|
||||
if ( provider != null && provider.getNaviListener() != null ) {
|
||||
provider.getNaviListener().onInitNaviSuccess();
|
||||
for ( IMogoModuleProvider value : mModuleProviders.values() ) {
|
||||
if ( value.getType() == ModuleType.TYPE_CARD_FRAGMENT ) {
|
||||
if ( mEnableModuleName != null && TextUtils.equals( value.getModuleName(), mEnableModuleName ) ) {
|
||||
if ( value.getNaviListener() != null ) {
|
||||
value.getNaviListener().onInitNaviSuccess();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( value.getNaviListener() != null ) {
|
||||
value.getNaviListener().onInitNaviSuccess();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNaviInfoUpdate( MogoNaviInfo naviinfo ) {
|
||||
if ( mEnableModuleName != null ) {
|
||||
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
|
||||
if ( provider != null && provider.getNaviListener() != null ) {
|
||||
provider.getNaviListener().onNaviInfoUpdate( naviinfo );
|
||||
for ( IMogoModuleProvider value : mModuleProviders.values() ) {
|
||||
if ( value.getType() == ModuleType.TYPE_CARD_FRAGMENT ) {
|
||||
if ( mEnableModuleName != null && TextUtils.equals( value.getModuleName(), mEnableModuleName ) ) {
|
||||
if ( value.getNaviListener() != null ) {
|
||||
value.getNaviListener().onNaviInfoUpdate( naviinfo );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( value.getNaviListener() != null ) {
|
||||
value.getNaviListener().onNaviInfoUpdate( naviinfo );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartNavi() {
|
||||
Logger.i( TAG, "导航已开始" );
|
||||
if ( mEnableModuleName != null ) {
|
||||
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
|
||||
if ( provider != null && provider.getNaviListener() != null ) {
|
||||
provider.getNaviListener().onStartNavi();
|
||||
for ( IMogoModuleProvider value : mModuleProviders.values() ) {
|
||||
if ( value.getType() == ModuleType.TYPE_CARD_FRAGMENT ) {
|
||||
if ( mEnableModuleName != null && TextUtils.equals( value.getModuleName(), mEnableModuleName ) ) {
|
||||
if ( value.getNaviListener() != null ) {
|
||||
value.getNaviListener().onStartNavi();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( value.getNaviListener() != null ) {
|
||||
value.getNaviListener().onStartNavi();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopNavi() {
|
||||
Logger.i( TAG, "导航已停止" );
|
||||
if ( mEnableModuleName != null ) {
|
||||
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
|
||||
if ( provider != null && provider.getNaviListener() != null ) {
|
||||
provider.getNaviListener().onStopNavi();
|
||||
for ( IMogoModuleProvider value : mModuleProviders.values() ) {
|
||||
if ( value.getType() == ModuleType.TYPE_CARD_FRAGMENT ) {
|
||||
if ( mEnableModuleName != null && TextUtils.equals( value.getModuleName(), mEnableModuleName ) ) {
|
||||
if ( value.getNaviListener() != null ) {
|
||||
value.getNaviListener().onStopNavi();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( value.getNaviListener() != null ) {
|
||||
value.getNaviListener().onStopNavi();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationChanged( MogoLocation location ) {
|
||||
if ( mEnableModuleName != null ) {
|
||||
IMogoModuleProvider provider = getModuleProvider( mEnableModuleName );
|
||||
if ( provider != null && provider.getLocationListener() != null ) {
|
||||
provider.getLocationListener().onLocationChanged( location );
|
||||
for ( IMogoModuleProvider value : mModuleProviders.values() ) {
|
||||
if ( value.getType() == ModuleType.TYPE_CARD_FRAGMENT ) {
|
||||
if ( mEnableModuleName != null && TextUtils.equals( value.getModuleName(), mEnableModuleName ) ) {
|
||||
if ( value.getLocationListener() != null ) {
|
||||
value.getLocationListener().onLocationChanged( location );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( value.getLocationListener() != null ) {
|
||||
value.getLocationListener().onLocationChanged( location );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void registerReceiver() {
|
||||
mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive( Context context, Intent intent ) {
|
||||
final String action = intent.getAction();
|
||||
if ( TextUtils.equals( action, Intent.ACTION_POWER_CONNECTED ) ) {
|
||||
for ( IMogoModuleProvider value : mModuleProviders.values() ) {
|
||||
if ( value.getCardLifecycle() != null ) {
|
||||
value.getCardLifecycle().accOn();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( TextUtils.equals( action, Intent.ACTION_POWER_DISCONNECTED ) ) {
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
IntentFilter inputFilter = new IntentFilter();
|
||||
inputFilter.addAction( Intent.ACTION_POWER_CONNECTED );
|
||||
inputFilter.addAction( Intent.ACTION_POWER_DISCONNECTED );
|
||||
getApplicationContext().registerReceiver( mReceiver, inputFilter );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
|
||||
if ( mReceiver != null ) {
|
||||
try {
|
||||
getApplicationContext().unregisterReceiver( mReceiver );
|
||||
} catch ( Exception e ) {
|
||||
}
|
||||
}
|
||||
mReceiver = null;
|
||||
mActivity = null;
|
||||
if ( mModuleProviders != null ) {
|
||||
mModuleProviders.clear();
|
||||
}
|
||||
mModuleProviders = null;
|
||||
mMapLoadedCallback = null;
|
||||
mEnableModuleName = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.mogo.map.navi.IMogoNaviListener;
|
||||
import com.mogo.module.main.R;
|
||||
import com.mogo.service.module.IMogoModuleLifecycle;
|
||||
import com.mogo.service.module.IMogoModuleProvider;
|
||||
import com.mogo.service.module.ModuleType;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
@@ -80,7 +81,7 @@ public class PlaceholderFragmentProvider implements IMogoModuleProvider {
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return TYPE_FRAGMENT;
|
||||
return ModuleType.TYPE_CARD_FRAGMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,6 +5,10 @@ import android.view.View;
|
||||
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Nate on 2016/7/22.
|
||||
*/
|
||||
public abstract class VerticalBaseTransformer implements ViewPager.PageTransformer {
|
||||
/**
|
||||
* Called each {@link #transformPage(View, float)}.
|
||||
@@ -13,7 +17,7 @@ public abstract class VerticalBaseTransformer implements ViewPager.PageTransform
|
||||
* @param position Position of page relative to the current front-and-center position of the pager. 0 is front and
|
||||
* center. 1 is one full page position to the right, and -1 is one page position to the left.
|
||||
*/
|
||||
protected abstract void onTransform( View page, float position );
|
||||
protected abstract void onTransform(View page, float position);
|
||||
|
||||
/**
|
||||
* Apply a property transformation to the given page. For most use cases, this method should not be overridden.
|
||||
@@ -24,10 +28,10 @@ public abstract class VerticalBaseTransformer implements ViewPager.PageTransform
|
||||
* center. 1 is one full page position to the right, and -1 is one page position to the left.
|
||||
*/
|
||||
@Override
|
||||
public void transformPage( View page, float position ) {
|
||||
onPreTransform( page, position );
|
||||
onTransform( page, position );
|
||||
onPostTransform( page, position );
|
||||
public void transformPage(View page, float position) {
|
||||
onPreTransform(page, position);
|
||||
onTransform(page, position);
|
||||
onPostTransform(page, position);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,24 +65,24 @@ public abstract class VerticalBaseTransformer implements ViewPager.PageTransform
|
||||
* @param position Position of page relative to the current front-and-center position of the pager. 0 is front and
|
||||
* center. 1 is one full page position to the right, and -1 is one page position to the left.
|
||||
*/
|
||||
protected void onPreTransform( View page, float position ) {
|
||||
protected void onPreTransform(View page, float position) {
|
||||
final float width = page.getWidth();
|
||||
final float height = page.getHeight();
|
||||
|
||||
page.setRotationX( 0 );
|
||||
page.setRotationY( 0 );
|
||||
page.setRotation( 0 );
|
||||
page.setScaleX( 1 );
|
||||
page.setScaleY( 1 );
|
||||
page.setPivotX( 0 );
|
||||
page.setPivotY( 0 );
|
||||
page.setTranslationX( 0 );
|
||||
page.setTranslationY( isPagingEnabled() ? 0f : -height * position );
|
||||
page.setRotationX(0);
|
||||
page.setRotationY(0);
|
||||
page.setRotation(0);
|
||||
page.setScaleX(1);
|
||||
page.setScaleY(1);
|
||||
page.setPivotX(0);
|
||||
page.setPivotY(0);
|
||||
page.setTranslationX(0);
|
||||
page.setTranslationY(isPagingEnabled() ? 0f : -height * position);
|
||||
|
||||
if ( hideOffscreenPages() ) {
|
||||
page.setAlpha( position <= -1f || position >= 1f ? 0f : 1f );
|
||||
if (hideOffscreenPages()) {
|
||||
page.setAlpha(position <= -1f || position >= 1f ? 0f : 1f);
|
||||
} else {
|
||||
page.setAlpha( 1f );
|
||||
page.setAlpha(1f);
|
||||
}
|
||||
|
||||
/*final float normalizedposition = Math.abs(Math.abs(position) - 1);
|
||||
@@ -92,7 +96,7 @@ public abstract class VerticalBaseTransformer implements ViewPager.PageTransform
|
||||
* @param position Position of page relative to the current front-and-center position of the pager. 0 is front and
|
||||
* center. 1 is one full page position to the right, and -1 is one page position to the left.
|
||||
*/
|
||||
protected void onPostTransform( View page, float position ) {
|
||||
protected void onPostTransform(View page, float position) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,7 +106,7 @@ public abstract class VerticalBaseTransformer implements ViewPager.PageTransform
|
||||
* @param min
|
||||
* @return
|
||||
*/
|
||||
protected static final float min( float val, float min ) {
|
||||
protected static final float min(float val, float min) {
|
||||
return val < min ? min : val;
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,8 @@ import com.mogo.utils.WindowUtils;
|
||||
public class VerticalStackTransformer extends VerticalBaseTransformer {
|
||||
|
||||
private Context context;
|
||||
private int spaceBetweenFirAndSecWith = 10 * 2;//第一张卡片和第二张卡片宽度差 dp单位
|
||||
private int spaceBetweenFirAndSecHeight = 10;//第一张卡片和第二张卡片高度差 dp单位
|
||||
private int spaceBetweenFirAndSecWith = 5 * 2;//第一张卡片和第二张卡片宽度差 dp单位
|
||||
private int spaceBetweenFirAndSecHeight = 5;//第一张卡片和第二张卡片高度差 dp单位
|
||||
|
||||
public VerticalStackTransformer( Context context ) {
|
||||
this.context = context;
|
||||
@@ -26,10 +26,12 @@ public class VerticalStackTransformer extends VerticalBaseTransformer {
|
||||
protected void onTransform( View page, float position ) {
|
||||
if ( position <= 0.0f ) {
|
||||
page.setAlpha( 1.0f );
|
||||
Log.e( "onTransform", "position <= 0.0f ==>" + position );
|
||||
page.setTranslationY( 0f );
|
||||
//控制停止滑动切换的时候,只有最上面的一张卡片可以点击
|
||||
page.setClickable( true );
|
||||
} else if ( position <= 3.0f ) {
|
||||
} else {
|
||||
Log.e( "onTransform", "position <= 3.0f ==>" + position );
|
||||
float scale = ( float ) ( page.getWidth() - WindowUtils.dip2px( context, spaceBetweenFirAndSecWith * position ) ) / ( float ) ( page.getWidth() );
|
||||
//控制下面卡片的可见度
|
||||
page.setAlpha( 1.0f );
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.mogo.module.main.receiver;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.text.TextUtils;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-02
|
||||
* <p>
|
||||
* 广播接收者
|
||||
* <p>
|
||||
* {@link Intent#ACTION_POWER_CONNECTED}
|
||||
* {@link Intent#ACTION_POWER_DISCONNECTED}
|
||||
*/
|
||||
public class MogoReceiver extends BroadcastReceiver {
|
||||
|
||||
public static void register( Context context ) {
|
||||
if ( context == null ) {
|
||||
return;
|
||||
}
|
||||
IntentFilter inputFilter = new IntentFilter();
|
||||
inputFilter.addAction( Intent.ACTION_POWER_CONNECTED );
|
||||
inputFilter.addAction( Intent.ACTION_POWER_DISCONNECTED );
|
||||
context.getApplicationContext().registerReceiver( new MogoReceiver(), inputFilter );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive( Context context, Intent intent ) {
|
||||
final String action = intent.getAction();
|
||||
if ( TextUtils.equals( action, Intent.ACTION_POWER_CONNECTED ) ) {
|
||||
|
||||
}
|
||||
if ( TextUtils.equals( action, Intent.ACTION_POWER_DISCONNECTED ) ) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,26 +3,28 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#0C0C0C"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 小智语音-->
|
||||
<FrameLayout
|
||||
android:id="@+id/module_main_id_ai_fragment_container"
|
||||
android:id="@+id/module_main_id_header_fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="75dp"
|
||||
android:background="#f00"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="35dp"
|
||||
android:layout_marginTop="5dp">
|
||||
<!-- 卡片-->
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/module_main_id_fragment_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="@dimen/dp_660"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
@@ -30,17 +32,16 @@
|
||||
android:id="@+id/module_main_id_cards_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="50dp"
|
||||
android:padding="10dp" />
|
||||
|
||||
android:layout_marginBottom="90dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingBottom="10dp" />
|
||||
</FrameLayout>
|
||||
|
||||
<!-- 地图-->
|
||||
<FrameLayout
|
||||
android:id="@+id/module_main_id_map_fragment_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="2"
|
||||
app:layout_constraintLeft_toRightOf="@+id/module_main_id_fragment_container"
|
||||
app:layout_constraintRight_toRightOf="parent" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -102,7 +102,7 @@ public class MapFragment extends MvpFragment< MapView, MapPresenter > implements
|
||||
//设置拖拽手势是否可用。
|
||||
uiSettings.setScrollGesturesEnabled( true );
|
||||
//设置倾斜手势是否可用。
|
||||
uiSettings.setTiltGesturesEnabled( false );
|
||||
uiSettings.setTiltGesturesEnabled( true );
|
||||
//设置缩放按钮是否可见。
|
||||
uiSettings.setZoomControlsEnabled( false );
|
||||
//设置双指缩放手势是否可用。
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.mogo.map.navi.IMogoNaviListener;
|
||||
import com.mogo.module.common.MogoModulePaths;
|
||||
import com.mogo.service.module.IMogoModuleLifecycle;
|
||||
import com.mogo.service.module.IMogoModuleProvider;
|
||||
import com.mogo.service.module.ModuleType;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
@@ -46,7 +47,7 @@ public class MapFragmentProvider implements IMogoModuleProvider {
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return IMogoModuleProvider.TYPE_FRAGMENT;
|
||||
return ModuleType.TYPE_MAP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
1
modules/mogo-module-service/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
60
modules/mogo-module-service/build.gradle
Normal file
@@ -0,0 +1,60 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'com.alibaba.arouter'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
buildToolsVersion rootProject.ext.android.buildToolsVersion
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
versionCode Integer.valueOf(VERSION_CODE)
|
||||
versionName getValueFromRootProperties("${project.name.replace("-", "_").toUpperCase()}_VERSION")
|
||||
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles 'consumer-rules.pro'
|
||||
|
||||
javaCompileOptions {
|
||||
annotationProcessorOptions {
|
||||
arguments = [AROUTER_MODULE_NAME: project.getName()]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
implementation rootProject.ext.dependencies.androidxconstraintlayout
|
||||
implementation rootProject.ext.dependencies.arouter
|
||||
annotationProcessor rootProject.ext.dependencies.aroutercompiler
|
||||
implementation rootProject.ext.dependencies.rxjava
|
||||
implementation rootProject.ext.dependencies.rxandroid
|
||||
if (Boolean.valueOf(RELEASE)) {
|
||||
api rootProject.ext.dependencies.mogomap
|
||||
api rootProject.ext.dependencies.mogomapapi
|
||||
api rootProject.ext.dependencies.mogoutils
|
||||
api rootProject.ext.dependencies.mogocommons
|
||||
api rootProject.ext.dependencies.mogoserviceapi
|
||||
implementation rootProject.ext.dependencies.modulecommon
|
||||
} else {
|
||||
api project(":libraries:mogo-map")
|
||||
api project(":libraries:mogo-map-api")
|
||||
api project(":foudations:mogo-utils")
|
||||
api project(":foudations:mogo-commons")
|
||||
api project(':services:mogo-service-api')
|
||||
implementation project(':modules:mogo-module-common')
|
||||
}
|
||||
}
|
||||
|
||||
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
|
||||
0
modules/mogo-module-service/consumer-rules.pro
Normal file
3
modules/mogo-module-service/gradle.properties
Normal file
@@ -0,0 +1,3 @@
|
||||
GROUP=com.mogo.module
|
||||
POM_ARTIFACT_ID=module-service
|
||||
VERSION_CODE=1
|
||||
21
modules/mogo-module-service/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
2
modules/mogo-module-service/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,2 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mogo.module.service" />
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.mogo.module.service;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-03
|
||||
* <p>
|
||||
* 自动刷新策略
|
||||
*/
|
||||
public class AutoRefreshStrategy {
|
||||
|
||||
public static final long ONE_MINUTE = 5 * 1_000L;
|
||||
|
||||
/**
|
||||
* 距离(米)
|
||||
*/
|
||||
private int distance = 2_000;
|
||||
|
||||
/**
|
||||
* 时间间距(s)
|
||||
*/
|
||||
private long interval = 3 * ONE_MINUTE;
|
||||
|
||||
/**
|
||||
* 用户打断后的延时(s)
|
||||
*/
|
||||
private long interruptInterval = 1 * ONE_MINUTE;
|
||||
|
||||
/**
|
||||
* 距离(米)
|
||||
*/
|
||||
public int getDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间间距(s)
|
||||
*/
|
||||
public long getInterval() {
|
||||
return interval;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户打断后的延时
|
||||
*/
|
||||
public long getInterruptInterval() {
|
||||
return interruptInterval;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.mogo.module.service;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-03
|
||||
* <p>
|
||||
* 手动刷新策略
|
||||
*/
|
||||
public class CustomRefreshStrategy {
|
||||
|
||||
/**
|
||||
* 缩小倍数
|
||||
*/
|
||||
private float zoomOutLevel = 2;
|
||||
|
||||
public float getZoomOutLevel() {
|
||||
return zoomOutLevel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,431 @@
|
||||
package com.mogo.module.service;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.alibaba.android.arouter.facade.annotation.Route;
|
||||
import com.alibaba.android.arouter.launcher.ARouter;
|
||||
import com.mogo.map.MogoLatLng;
|
||||
import com.mogo.map.listener.IMogoMapListener;
|
||||
import com.mogo.map.location.IMogoLocationListener;
|
||||
import com.mogo.map.location.MogoLocation;
|
||||
import com.mogo.map.marker.IMogoMarker;
|
||||
import com.mogo.map.marker.IMogoMarkerManager;
|
||||
import com.mogo.map.marker.MogoMarkerOptions;
|
||||
import com.mogo.map.model.MogoPoi;
|
||||
import com.mogo.map.navi.IMogoNaviListener;
|
||||
import com.mogo.map.navi.MogoNaviInfo;
|
||||
import com.mogo.map.uicontroller.EnumMapUI;
|
||||
import com.mogo.map.uicontroller.IMogoMapUIController;
|
||||
import com.mogo.module.service.network.RefreshCallback;
|
||||
import com.mogo.module.service.network.RefreshModel;
|
||||
import com.mogo.service.MogoServicePaths;
|
||||
import com.mogo.service.map.IMogoMapService;
|
||||
import com.mogo.service.module.IMogoModuleLifecycle;
|
||||
import com.mogo.service.module.IMogoModuleProvider;
|
||||
import com.mogo.service.module.ModuleType;
|
||||
import com.mogo.service.statusmanager.IMogoStatusChangedListener;
|
||||
import com.mogo.service.statusmanager.IMogoStatusManager;
|
||||
import com.mogo.service.statusmanager.StatusDescriptor;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-03
|
||||
* <p>
|
||||
* 数据刷新策略
|
||||
*/
|
||||
@Route( path = ServiceConst.PATH_REFRESH_STRATEGY )
|
||||
public class MogoServiceProvider implements IMogoModuleProvider,
|
||||
IMogoMapListener,
|
||||
IMogoLocationListener,
|
||||
IMogoNaviListener,
|
||||
IMogoStatusChangedListener {
|
||||
|
||||
private static final String TAG = "MogoRefreshStrategyProvider";
|
||||
|
||||
/**
|
||||
* 自动刷新策略
|
||||
*/
|
||||
private AutoRefreshStrategy mAutoRefreshStrategy = new AutoRefreshStrategy();
|
||||
private MogoLatLng mLastAutoRefreshLocation = null;
|
||||
private long mLastRefreshTime = 0;
|
||||
|
||||
private IMogoMarkerManager mMarkerManager;
|
||||
private IMogoMapUIController mUiController;
|
||||
|
||||
/**
|
||||
* 是否已计算出地图显示状态
|
||||
*/
|
||||
private boolean mIsMapStatusOk = false;
|
||||
|
||||
/**
|
||||
* 地图显示是横屏还是竖屏:根据地图右上角和左下角坐标计算
|
||||
*/
|
||||
boolean mIsVertical = false;
|
||||
|
||||
/**
|
||||
* 手动刷新策略
|
||||
*/
|
||||
private CustomRefreshStrategy mCustomRefreshStrategy = new CustomRefreshStrategy();
|
||||
private float mLastZoomLevel = 0;
|
||||
private RefreshModel mRefreshModel;
|
||||
private long mRefreshRemainingTime = Long.MAX_VALUE;
|
||||
// 上次手动操作的中心点坐标
|
||||
private MogoLatLng mLastCustomRefreshCenterLocation;
|
||||
|
||||
private IMogoMapService mMogoMapService;
|
||||
private IMogoMarker mCameraCenterMarker = null;
|
||||
private IMogoStatusManager mStatusManager;
|
||||
|
||||
/**
|
||||
* 地图视图初始化
|
||||
*/
|
||||
private boolean mIsCameraInited = true;
|
||||
|
||||
private Handler mHandler = new Handler( Looper.getMainLooper() ) {
|
||||
@Override
|
||||
public void handleMessage( @NonNull Message msg ) {
|
||||
super.handleMessage( msg );
|
||||
switch ( msg.what ) {
|
||||
case ServiceConst.MSG_TYPE_REFRESH_DECREASE:
|
||||
mRefreshRemainingTime -= ServiceConst.DECREASE_INTERVAL;
|
||||
if ( mRefreshRemainingTime == 0 ) {
|
||||
notifyRefreshData( mAutoRefreshCallback );
|
||||
} else {
|
||||
mHandler.sendEmptyMessageDelayed( msg.what, ServiceConst.DECREASE_INTERVAL );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
private Context mContext;
|
||||
|
||||
/**
|
||||
* 地图视图西南角坐标
|
||||
*/
|
||||
private MogoLatLng mCameraSouthWestPosition;
|
||||
|
||||
/**
|
||||
* 地图视图东北角坐标
|
||||
*/
|
||||
private MogoLatLng mCameraNorthEastPosition;
|
||||
|
||||
/**
|
||||
* 手动刷新回调
|
||||
*/
|
||||
private RefreshCallback mCustomRefreshCallback = new RefreshCallback() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
// 用户手动操作地图刷新成功后,设置状态为 true,引发延时策略
|
||||
mStatusManager.setUserInteractionStatus( ServiceConst.TYPE, true, true );
|
||||
mStatusManager.setUserInteractionStatus( ServiceConst.TYPE, false, false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail() {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 自动刷新回调
|
||||
*/
|
||||
private RefreshCallback mAutoRefreshCallback = new RefreshCallback() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
invokeAutoRefreshStrategy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail() {
|
||||
invokeAutoRefreshStrategy();
|
||||
}
|
||||
|
||||
private void invokeAutoRefreshStrategy() {
|
||||
mRefreshRemainingTime = mAutoRefreshStrategy.getInterval();
|
||||
mHandler.removeMessages( ServiceConst.MSG_TYPE_REFRESH_DECREASE );
|
||||
mHandler.sendEmptyMessageDelayed( ServiceConst.MSG_TYPE_REFRESH_DECREASE, ServiceConst.DECREASE_INTERVAL );
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public final Fragment createFragment( Context context, Bundle data ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final View createView( Context context ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final IMogoModuleLifecycle getCardLifecycle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoMapListener getMapListener() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return ModuleType.TYPE_SERVICE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoNaviListener getNaviListener() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoLocationListener getLocationListener() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getModuleName() {
|
||||
return ServiceConst.TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init( Context context ) {
|
||||
mContext = context;
|
||||
mRefreshModel = new RefreshModel( context );
|
||||
mMogoMapService = ( IMogoMapService ) ARouter.getInstance().build( MogoServicePaths.PATH_SERVICES_MAP ).navigation( context );
|
||||
mMarkerManager = mMogoMapService.getMarkerManager( context );
|
||||
mUiController = mMogoMapService.getMapUIController();
|
||||
mStatusManager = ( IMogoStatusManager ) ARouter.getInstance().build( MogoServicePaths.PATH_STATUS_MANAGER ).navigation( context );
|
||||
mStatusManager.registerStatusChangedListener( ServiceConst.TYPE, StatusDescriptor.USER_INTERACTED, this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapLoaded() {
|
||||
refreshCameraPosition();
|
||||
}
|
||||
|
||||
private void initMapStatus() {
|
||||
if ( mIsMapStatusOk ) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
float width = getMapCameraFactWidth();
|
||||
float height = getMapCameraFactHeight();
|
||||
mIsVertical = width < height;
|
||||
Logger.i( TAG, "map status is vertical : " + mIsVertical );
|
||||
mIsMapStatusOk = true;
|
||||
} catch ( Exception e ) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 地图视图对应的实际宽度
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private float getMapCameraFactWidth() {
|
||||
return Utils.calculateLineDistance( mCameraNorthEastPosition, new MogoLatLng( mCameraNorthEastPosition.lat, mCameraSouthWestPosition.lng ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* 地图视图对应的实际高度
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private float getMapCameraFactHeight() {
|
||||
return Utils.calculateLineDistance( mCameraSouthWestPosition, new MogoLatLng( mCameraNorthEastPosition.lat, mCameraSouthWestPosition.lng ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新视图范围坐标
|
||||
*/
|
||||
private void refreshCameraPosition() {
|
||||
mCameraSouthWestPosition = mUiController.getCameraSouthWestPosition();
|
||||
mCameraNorthEastPosition = mUiController.getCameraNorthEastPosition();
|
||||
|
||||
initMapStatus();
|
||||
|
||||
if ( mIsVertical ) {
|
||||
float width = getMapCameraFactWidth();
|
||||
Logger.i( TAG, "current zoom level width: %f m", width );
|
||||
} else {
|
||||
float height = getMapCameraFactHeight();
|
||||
Logger.i( TAG, "current zoom level height: %f m", height );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTouch( MotionEvent motionEvent ) {
|
||||
switch ( motionEvent.getActionMasked() ) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
if ( mLastZoomLevel == 0 ) {
|
||||
mLastZoomLevel = mUiController.getZoomLevel();
|
||||
Logger.i( TAG, "初始化缩放级别 为:%f", mLastZoomLevel );
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void stopAutoRefreshStrategy() {
|
||||
mHandler.removeMessages( ServiceConst.MSG_TYPE_REFRESH_DECREASE );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPOIClick( MogoPoi poi ) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapClick( MogoLatLng latLng ) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLockMap( boolean isLock ) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapModeChanged( EnumMapUI ui ) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapChanged( MogoLatLng latLng, float zoom, float tilt, float bearing ) {
|
||||
|
||||
|
||||
if ( mIsCameraInited ) {
|
||||
mLastCustomRefreshCenterLocation = latLng;
|
||||
mIsCameraInited = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( mCameraCenterMarker == null ) {
|
||||
mCameraCenterMarker = mMarkerManager.addMarker( ServiceConst.TYPE,
|
||||
new MogoMarkerOptions()
|
||||
.icon( BitmapFactory.decodeResource( mContext.getResources(), R.drawable.ic_search_poi_location ) )
|
||||
.latitude( latLng.lat )
|
||||
.longitude( latLng.lng )
|
||||
.owner( ServiceConst.TYPE )
|
||||
);
|
||||
} else {
|
||||
mCameraCenterMarker.setPosition( latLng.lat, latLng.lng );
|
||||
}
|
||||
|
||||
if ( mLastZoomLevel != zoom ) {
|
||||
refreshCameraPosition();
|
||||
}
|
||||
|
||||
// 手动刷新触发
|
||||
if ( mLastZoomLevel - zoom > mCustomRefreshStrategy.getZoomOutLevel() ) {
|
||||
// 缩放级别缩小
|
||||
notifyRefreshData( mCustomRefreshCallback );
|
||||
mLastCustomRefreshCenterLocation = latLng;
|
||||
mLastZoomLevel = zoom;
|
||||
} else if ( mLastZoomLevel == zoom ) {
|
||||
// 手动平移
|
||||
if ( invokeRefreshWhenTranslationByUser( latLng ) ) {
|
||||
notifyRefreshData( mCustomRefreshCallback );
|
||||
mLastCustomRefreshCenterLocation = latLng;
|
||||
}
|
||||
}
|
||||
Logger.d( TAG, "current map status: %s, zoom = %f, tilt = %f, bearing = %f", latLng, zoom, tilt, bearing );
|
||||
}
|
||||
|
||||
/**
|
||||
* 平移地图刷新策略
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private boolean invokeRefreshWhenTranslationByUser( MogoLatLng latLng ) {
|
||||
try {
|
||||
float factor = 0.0f;
|
||||
if ( mIsVertical ) {
|
||||
factor = getMapCameraFactWidth();
|
||||
} else {
|
||||
factor = getMapCameraFactHeight();
|
||||
}
|
||||
if ( factor == 0.0f ) {
|
||||
return false;
|
||||
}
|
||||
float distance = Utils.calculateLineDistance( latLng, mLastCustomRefreshCenterLocation );
|
||||
return distance > factor;
|
||||
} catch ( Exception e ) {
|
||||
Logger.w( TAG, "warming. ", e );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationChanged( MogoLocation location ) {
|
||||
if ( location == null ) {
|
||||
return;
|
||||
}
|
||||
// 自动刷新触发
|
||||
if ( mLastAutoRefreshLocation == null ) {
|
||||
mLastAutoRefreshLocation = new MogoLatLng( location.getLatitude(), location.getLongitude() );
|
||||
notifyRefreshData( mAutoRefreshCallback );
|
||||
} else {
|
||||
float distance = Utils.calculateLineDistance( mLastAutoRefreshLocation, new MogoLatLng( location.getLatitude(), location.getLongitude() ) );
|
||||
if ( distance > mAutoRefreshStrategy.getDistance() ) {
|
||||
notifyRefreshData( mAutoRefreshCallback );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新数据
|
||||
*/
|
||||
private void notifyRefreshData( RefreshCallback callback ) {
|
||||
Logger.d( TAG, mAutoRefreshCallback == callback ? "触发自动刷新" : "触发手动刷新" );
|
||||
mRefreshModel.refreshData( callback );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitNaviFailure() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitNaviSuccess() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNaviInfoUpdate( MogoNaviInfo naviinfo ) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartNavi() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopNavi() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged( StatusDescriptor descriptor, boolean isTrue ) {
|
||||
if ( descriptor == StatusDescriptor.USER_INTERACTED && isTrue ) {
|
||||
Logger.i( TAG, "用户状态改变,自动刷新时间延时" );
|
||||
mRefreshRemainingTime += mAutoRefreshStrategy.getInterruptInterval();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.mogo.module.service;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-03
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class ServiceConst {
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
public static final String TYPE = "STRATEGY_REFRESH";
|
||||
|
||||
/**
|
||||
* 刷新策略模块地址
|
||||
*/
|
||||
public static final String PATH_REFRESH_STRATEGY = "/strategy/refresh";
|
||||
|
||||
/**
|
||||
* 倒计时消息
|
||||
*/
|
||||
public static final int MSG_TYPE_REFRESH_DECREASE = 0x100;
|
||||
/**
|
||||
* 倒计时间隔
|
||||
*/
|
||||
public static final int DECREASE_INTERVAL = 1_000;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.mogo.module.service;
|
||||
|
||||
import com.amap.api.maps.AMapException;
|
||||
import com.amap.api.maps.model.LatLng;
|
||||
import com.mogo.map.MogoLatLng;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-03
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class Utils {
|
||||
|
||||
public static float calculateLineDistance( MogoLatLng point1, MogoLatLng point2 ) {
|
||||
if ( point1 != null && point2 != null ) {
|
||||
try {
|
||||
double var2 = point1.lng;
|
||||
double var4 = point1.lat;
|
||||
double var6 = point2.lng;
|
||||
double var8 = point2.lat;
|
||||
var2 *= 0.01745329251994329D;
|
||||
var4 *= 0.01745329251994329D;
|
||||
var6 *= 0.01745329251994329D;
|
||||
var8 *= 0.01745329251994329D;
|
||||
double var10 = Math.sin( var2 );
|
||||
double var12 = Math.sin( var4 );
|
||||
double var14 = Math.cos( var2 );
|
||||
double var16 = Math.cos( var4 );
|
||||
double var18 = Math.sin( var6 );
|
||||
double var20 = Math.sin( var8 );
|
||||
double var22 = Math.cos( var6 );
|
||||
double var24 = Math.cos( var8 );
|
||||
double[] var28 = new double[3];
|
||||
double[] var29 = new double[3];
|
||||
var28[0] = var16 * var14;
|
||||
var28[1] = var16 * var10;
|
||||
var28[2] = var12;
|
||||
var29[0] = var24 * var22;
|
||||
var29[1] = var24 * var18;
|
||||
var29[2] = var20;
|
||||
return ( float ) ( Math.asin( Math.sqrt( ( var28[0] - var29[0] ) * ( var28[0] - var29[0] ) + ( var28[1] - var29[1] ) * ( var28[1] - var29[1] ) + ( var28[2] - var29[2] ) * ( var28[2] - var29[2] ) ) / 2.0D ) * 1.27420015798544E7D );
|
||||
} catch ( Throwable var26 ) {
|
||||
var26.printStackTrace();
|
||||
return 0.0F;
|
||||
}
|
||||
} else {
|
||||
return 0.0F;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.mogo.module.service.network;
|
||||
|
||||
import com.mogo.commons.data.BaseData;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.QueryMap;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-03
|
||||
* <p>
|
||||
* 接口描述
|
||||
*/
|
||||
public interface RefreshApiService {
|
||||
|
||||
@GET( "" )
|
||||
Observable< BaseData > refreshData( @QueryMap Map< String, Object > params );
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.mogo.module.service.network;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-03
|
||||
* <p>
|
||||
* 刷新回调
|
||||
*/
|
||||
public interface RefreshCallback {
|
||||
|
||||
void onSuccess();
|
||||
|
||||
void onFail();
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.mogo.module.service.network;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.alibaba.android.arouter.launcher.ARouter;
|
||||
import com.mogo.commons.data.BaseData;
|
||||
import com.mogo.commons.network.ParamsProvider;
|
||||
import com.mogo.commons.network.SubscribeImpl;
|
||||
import com.mogo.service.MogoServicePaths;
|
||||
import com.mogo.service.network.IMogoNetwork;
|
||||
import com.mogo.utils.network.RequestOptions;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2020-01-03
|
||||
* <p>
|
||||
* 刷新数据
|
||||
*/
|
||||
public class RefreshModel {
|
||||
|
||||
private final Context mContext;
|
||||
private RefreshApiService mRefreshApiService;
|
||||
|
||||
public RefreshModel( Context context ) {
|
||||
this.mContext = context;
|
||||
IMogoNetwork network = ( IMogoNetwork ) ARouter.getInstance().build( MogoServicePaths.PATH_SERVICES_NETWORK ).navigation( context );
|
||||
this.mRefreshApiService = network.create( RefreshApiService.class, "http://www.baidu.com/" );
|
||||
}
|
||||
|
||||
public void refreshData( final RefreshCallback callback ) {
|
||||
if ( callback != null ) {
|
||||
callback.onSuccess();
|
||||
return;
|
||||
}
|
||||
if ( mRefreshApiService != null ) {
|
||||
final Map< String, Object > params = new ParamsProvider.Builder( mContext ).build();
|
||||
mRefreshApiService.refreshData( params )
|
||||
.subscribeOn( Schedulers.io() )
|
||||
.observeOn( AndroidSchedulers.mainThread() )
|
||||
.subscribe( new SubscribeImpl< BaseData >( RequestOptions.create( mContext ) ) {
|
||||
@Override
|
||||
public void onSuccess( BaseData o ) {
|
||||
super.onSuccess( o );
|
||||
if ( callback != null ) {
|
||||
callback.onSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError( String message, int code ) {
|
||||
super.onError( message, code );
|
||||
if ( callback != null ) {
|
||||
callback.onFail();
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">mogo-module-service</string>
|
||||
</resources>
|
||||
1
modules/mogo-module-tanlu/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
70
modules/mogo-module-tanlu/build.gradle
Normal file
@@ -0,0 +1,70 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'com.alibaba.arouter'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
buildToolsVersion rootProject.ext.android.buildToolsVersion
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
versionCode Integer.valueOf(VERSION_CODE)
|
||||
versionName getValueFromRootProperties("${project.name.replace("-", "_").toUpperCase()}_VERSION")
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles 'consumer-rules.pro'
|
||||
|
||||
javaCompileOptions {
|
||||
annotationProcessorOptions {
|
||||
arguments = [AROUTER_MODULE_NAME: project.getName()]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||
implementation 'androidx.core:core-ktx:1.0.2'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
|
||||
if (Boolean.valueOf(RELEASE)) {
|
||||
implementation rootProject.ext.dependencies.mogomap
|
||||
implementation rootProject.ext.dependencies.mogoutils
|
||||
implementation rootProject.ext.dependencies.mogocommons
|
||||
implementation rootProject.ext.dependencies.mogoserviceapi
|
||||
implementation rootProject.ext.dependencies.modulecommon
|
||||
} else {
|
||||
implementation project(":libraries:mogo-map")
|
||||
implementation project(":foudations:mogo-utils")
|
||||
api project(":foudations:mogo-commons")
|
||||
implementation project(':services:mogo-service-api')
|
||||
implementation project(':modules:mogo-module-common')
|
||||
}
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
implementation rootProject.ext.dependencies.androidxconstraintlayout
|
||||
implementation rootProject.ext.dependencies.arouter
|
||||
annotationProcessor rootProject.ext.dependencies.aroutercompiler
|
||||
|
||||
implementation 'com.shuyu:gsyVideoPlayer-armv7a:7.1.1'
|
||||
implementation 'com.shuyu:gsyVideoPlayer-arm64:7.1.1'
|
||||
implementation 'com.shuyu:gsyVideoPlayer-java:7.1.1'
|
||||
|
||||
}
|
||||
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
0
modules/mogo-module-tanlu/consumer-rules.pro
Normal file
3
modules/mogo-module-tanlu/gradle.properties
Normal file
@@ -0,0 +1,3 @@
|
||||
GROUP=com.mogo.module
|
||||
POM_ARTIFACT_ID=module-tanlu
|
||||
VERSION_CODE=1
|
||||
21
modules/mogo-module-tanlu/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.zhidao.tanlu;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
|
||||
assertEquals("com.zhidao.tanlu.test", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
12
modules/mogo-module-tanlu/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mogo.tanlu">
|
||||
|
||||
<application>
|
||||
<activity
|
||||
android:name=".video.FullMediaActivity"
|
||||
android:hardwareAccelerated="true">
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.mogo.tanlu.constant
|
||||
|
||||
const val REQUESTCODE_MAINACTIVITY = 0
|
||||
const val REQUESTCODE_MEDIAACTIVITY = 1
|
||||
|
||||
//EXTRA_STATE
|
||||
const val AUTO_NAVI_START = 8 //开始导航
|
||||
const val AUTO_NAVI_END = 9 //结束导航
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.mogo.tanlu.constant;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2019-12-24
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class TanluConstants {
|
||||
|
||||
public static final String TAG = "/tanlu/ui";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
package com.mogo.tanlu.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.alibaba.android.arouter.launcher.ARouter;
|
||||
import com.mogo.commons.mvp.IView;
|
||||
import com.mogo.commons.mvp.MvpFragment;
|
||||
import com.mogo.commons.mvp.Presenter;
|
||||
import com.mogo.map.MogoLatLng;
|
||||
import com.mogo.map.listener.IMogoMapListener;
|
||||
import com.mogo.map.location.IMogoLocationListener;
|
||||
import com.mogo.map.location.MogoLocation;
|
||||
import com.mogo.map.marker.IMogoMarker;
|
||||
import com.mogo.map.marker.IMogoMarkerClickListener;
|
||||
import com.mogo.map.model.MogoPoi;
|
||||
import com.mogo.map.search.geo.MogoPoiItem;
|
||||
import com.mogo.map.search.poisearch.IMogoPoiSearchListener;
|
||||
import com.mogo.map.search.poisearch.MogoPoiResult;
|
||||
import com.mogo.map.uicontroller.EnumMapUI;
|
||||
import com.mogo.service.MogoServicePaths;
|
||||
import com.mogo.service.imageloader.IMogoImageloader;
|
||||
import com.mogo.service.module.IMogoModuleLifecycle;
|
||||
import com.mogo.tanlu.R;
|
||||
import com.mogo.tanlu.video.FullMediaActivity;
|
||||
import com.mogo.tanlu.video.SimpleCoverVideoPlayer;
|
||||
import com.mogo.tanlu.view.AutoZoomInImageView;
|
||||
import com.mogo.utils.TipToast;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder;
|
||||
|
||||
import static com.mogo.tanlu.video.VideoInitKt.initVideo;
|
||||
|
||||
/**
|
||||
* @author lixiaopeng
|
||||
* @description 探路卡片
|
||||
* @since 2020-01-02
|
||||
*/
|
||||
public class TanluCardViewFragment extends MvpFragment<IView, Presenter<IView>>
|
||||
implements IView,
|
||||
IMogoMarkerClickListener,
|
||||
IMogoModuleLifecycle,
|
||||
IMogoMapListener,
|
||||
IMogoPoiSearchListener,
|
||||
IMogoLocationListener,
|
||||
View.OnClickListener {
|
||||
|
||||
private static final String TAG = "liyz";
|
||||
|
||||
//map
|
||||
private IMogoMarker mPoiMarker;
|
||||
private int position = -1;
|
||||
|
||||
//media
|
||||
private GSYVideoOptionBuilder gsyVideoOptionBuilder = new GSYVideoOptionBuilder();
|
||||
// private String videoUrl = "";
|
||||
private String videoUrl = "http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8";
|
||||
private String imageUrl = "https://oimagec4.ydstatic.com/image?id=-5397300958976572132&product=adpublish&w=520&h=347";
|
||||
SimpleCoverVideoPlayer simpleCoverVideoPlayer;
|
||||
AutoZoomInImageView autoZoomInImageView;
|
||||
private IMogoImageloader mogoImageloader;
|
||||
private TextView mPreviousTv;
|
||||
private TextView mNextTv;
|
||||
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.tanlu_item_main_media_recycler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
initVideo();
|
||||
position = getArguments().getInt("position");
|
||||
simpleCoverVideoPlayer = findViewById(R.id.video_player_main);
|
||||
autoZoomInImageView = findViewById(R.id.tanlu_photo_imageView);
|
||||
mPreviousTv = findViewById(R.id.tv_previous_res);
|
||||
mNextTv = findViewById(R.id.tv_next_res);
|
||||
mPreviousTv.setOnClickListener(this);
|
||||
mNextTv.setOnClickListener(this);
|
||||
|
||||
simpleCoverVideoPlayer.setVisibility(View.VISIBLE);
|
||||
autoZoomInImageView.setVisibility(View.GONE);
|
||||
|
||||
//视频配置
|
||||
gsyVideoOptionBuilder.setUrl(videoUrl).setCacheWithPlay(false).setPlayTag(TAG)
|
||||
.build(simpleCoverVideoPlayer);
|
||||
// simpleCoverVideoPlayer.getStartButton().performClick();
|
||||
simpleCoverVideoPlayer.getStartButton().setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Logger.d(TAG, "simpleCoverVideoPlayer onClick -------> ");
|
||||
FullMediaActivity.Companion.launch(getActivity(), videoUrl, "image");
|
||||
}
|
||||
});
|
||||
|
||||
//图片配置
|
||||
mogoImageloader = (IMogoImageloader) ARouter.getInstance().build(MogoServicePaths.PATH_UTILS_IMAGE_LOADER).navigation();
|
||||
|
||||
//当前定位信息
|
||||
TanluServiceHandler.getPoiSearch().setPoiSearchListener(this);
|
||||
// mLocation = TanluServiceHandler.getLocationClient().getLastKnowLocation();
|
||||
|
||||
TanluServiceHandler.getLocationClient().addLocationListener(new IMogoLocationListener() {
|
||||
@Override
|
||||
public void onLocationChanged(MogoLocation location) {
|
||||
// mLocation = location;
|
||||
Logger.d(TAG, "demo模块定位,定位间隔4s");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
getViewLifecycleOwner().getLifecycle().addObserver(mPresenter);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @param view
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
int id = view.getId();
|
||||
if (id == R.id.tv_previous_res) { //上一个
|
||||
//判断是图片还是视频,第一个时,上一个不可点击
|
||||
simpleCoverVideoPlayer.setVisibility(View.VISIBLE);
|
||||
autoZoomInImageView.setVisibility(View.GONE);
|
||||
//视频配置
|
||||
gsyVideoOptionBuilder.setUrl(videoUrl).setCacheWithPlay(false).setPlayTag(TAG)
|
||||
.build(simpleCoverVideoPlayer);
|
||||
|
||||
} else if (id == R.id.tv_next_res) { //下一个
|
||||
//判断是图片还是视频,最后一个时,下一个不可点击
|
||||
//图片显示
|
||||
autoZoomInImageView.setVisibility(View.VISIBLE);
|
||||
simpleCoverVideoPlayer.setVisibility(View.GONE);
|
||||
mogoImageloader.displayImage(imageUrl, autoZoomInImageView);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* marker点击事件 TODO
|
||||
*
|
||||
* @param marker
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean onMarkerClicked(IMogoMarker marker) {
|
||||
marker.getObject();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Presenter createPresenter() {
|
||||
return new Presenter(this) {
|
||||
};
|
||||
}
|
||||
|
||||
//TODO C位事件,如何获取数据,需要有默认数据
|
||||
@Override
|
||||
public void onPerform() {
|
||||
Logger.d(TAG, "卡片2有效");
|
||||
|
||||
}
|
||||
|
||||
//TODO 离开C位事件
|
||||
@Override
|
||||
public void onDisable() {
|
||||
Logger.d(TAG, "卡片2无效");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accOn() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapLoaded() {
|
||||
Logger.d(TAG, "地图加载事件");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTouch(MotionEvent motionEvent) {
|
||||
// Logger.d( TAG, "地图触摸事件" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPOIClick(MogoPoi poi) {
|
||||
if (poi != null) {
|
||||
TipToast.shortTip(poi.getName());
|
||||
}
|
||||
TanluServiceHandler.getPoiSearch().searchPOIIdAsyn(poi.getPoiId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPoiSearched(MogoPoiResult result, int errorCode) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPoiItemSearched(MogoPoiItem item, int errorCode) {
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onLocationChanged(MogoLocation location) {
|
||||
// if (location.getErrCode() == 0) {
|
||||
// Logger.d(TAG, "onLocationChanged 当前位置 -->" + location.getAddress());
|
||||
// } else {
|
||||
// Logger.d(TAG, "onLocationChanged 定位失败 -->" + location.getErrInfo());
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onMapClick(MogoLatLng latLng) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLockMap(boolean isLock) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapModeChanged(EnumMapUI ui) {
|
||||
Logger.d(TAG, ui.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapChanged(MogoLatLng location, float zoom, float tilt, float bearing) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
Logger.w(TAG, "onDestroyView position=" + position);
|
||||
super.onDestroyView();
|
||||
getViewLifecycleOwner().getLifecycle().removeObserver(mPresenter);
|
||||
TanluServiceHandler.getLocationClient().removeLocationListener(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.mogo.tanlu.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.alibaba.android.arouter.facade.annotation.Route;
|
||||
import com.mogo.map.listener.IMogoMapListener;
|
||||
import com.mogo.map.location.IMogoLocationListener;
|
||||
import com.mogo.map.navi.IMogoNaviListener;
|
||||
import com.mogo.service.module.IMogoModuleLifecycle;
|
||||
import com.mogo.service.module.IMogoModuleProvider;
|
||||
import com.mogo.service.module.ModuleType;
|
||||
import com.mogo.tanlu.constant.TanluConstants;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2019-12-24
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
@Route( path = TanluConstants.TAG )
|
||||
public class TanluCardViewProvider implements IMogoModuleProvider {
|
||||
|
||||
private static final String TAG = "TanluCardViewProvider";
|
||||
private TanluCardViewFragment fragment;
|
||||
|
||||
@Override
|
||||
public Fragment createFragment( Context context, Bundle data ) {
|
||||
fragment = new TanluCardViewFragment();
|
||||
fragment.setArguments( data );
|
||||
Logger.i( TAG, "createFragment" );
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init( Context context ) {
|
||||
TanluServiceHandler.init( context );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModuleName() {
|
||||
return "CARD_TYPE_ROAD_CODITION";
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoModuleLifecycle getCardLifecycle() {
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createView( Context context ) {
|
||||
// don't
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoMapListener getMapListener() {
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return ModuleType.TYPE_CARD_FRAGMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoNaviListener getNaviListener() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMogoLocationListener getLocationListener() {
|
||||
return fragment;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.mogo.tanlu.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mogo.map.marker.IMogoInfoWindowAdapter;
|
||||
import com.mogo.map.marker.IMogoMarker;
|
||||
import com.mogo.map.marker.MogoMarkerOptions;
|
||||
import com.mogo.map.navi.IMogoNavi;
|
||||
import com.mogo.map.navi.MogoNaviConfig;
|
||||
import com.mogo.map.search.geo.MogoPoiItem;
|
||||
import com.mogo.service.imageloader.IMogoImageLoaderListener;
|
||||
import com.mogo.service.imageloader.IMogoImageloader;
|
||||
import com.mogo.service.imageloader.MogoImageView;
|
||||
import com.mogo.tanlu.R;
|
||||
import com.mogo.utils.WindowUtils;
|
||||
import com.mogo.utils.logger.Logger;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2019-12-24
|
||||
* <p>
|
||||
* 描述
|
||||
*/
|
||||
public class TanluInfoWindowAdapter implements IMogoInfoWindowAdapter {
|
||||
|
||||
private static final String TAG = "DemoInfoWindowAdapter";
|
||||
|
||||
private Context mContext;
|
||||
private IMogoNavi mNavi;
|
||||
private IMogoImageloader mImageloader;
|
||||
|
||||
public TanluInfoWindowAdapter(Context mContext, IMogoNavi mNavi, IMogoImageloader iMogoImageloader ) {
|
||||
this.mContext = mContext;
|
||||
this.mNavi = mNavi;
|
||||
this.mImageloader = iMogoImageloader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getInfoWindow( IMogoMarker marker ) {
|
||||
if ( marker.getObject() instanceof MogoPoiItem ) {
|
||||
View view = LayoutInflater.from( mContext ).inflate( R.layout.tanlu_poi_info_window, null );
|
||||
renderPoiVew( view, marker, ( ( MogoPoiItem ) marker.getObject() ) );
|
||||
return view;
|
||||
} else {
|
||||
View view = LayoutInflater.from( mContext ).inflate( R.layout.tanlu_info_window, null );
|
||||
renderView( view, marker );
|
||||
return view;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void renderView( View view, final IMogoMarker marker ) {
|
||||
final TextView time = view.findViewById( R.id.demo_module_id_iw_time );
|
||||
Button refresh = view.findViewById( R.id.demo_module_id_iw_refresh );
|
||||
time.setText( new SimpleDateFormat( "yyyyMMdd HHMMSS" ).format( new Date() ) );
|
||||
refresh.setOnClickListener( new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View v ) {
|
||||
marker.showInfoWindow();
|
||||
}
|
||||
} );
|
||||
Button navi2 = view.findViewById( R.id.demo_module_id_iw_navito );
|
||||
navi2.setOnClickListener( new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View v ) {
|
||||
if ( mNavi != null ) {
|
||||
mNavi.naviTo( marker.getPosition(), new MogoNaviConfig() );
|
||||
}
|
||||
}
|
||||
} );
|
||||
Button stopNavi = view.findViewById( R.id.demo_module_id_iw_navi_stop );
|
||||
stopNavi.setOnClickListener( new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View v ) {
|
||||
if ( mNavi != null ) {
|
||||
mNavi.stopNavi();
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
private void renderPoiVew( View view, final IMogoMarker marker, MogoPoiItem item ) {
|
||||
final TextView time = view.findViewById( R.id.demo_module_id_iw_poi_title );
|
||||
time.setText( item.getTitle() );
|
||||
Button navi2 = view.findViewById( R.id.demo_module_id_iw_poi_navito );
|
||||
navi2.setOnClickListener( new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View v ) {
|
||||
if ( mNavi != null ) {
|
||||
mNavi.naviTo( marker.getPosition(), new MogoNaviConfig() );
|
||||
}
|
||||
marker.hideInfoWindow();
|
||||
marker.remove();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
public View getMarkerView( final MogoMarkerOptions options ) {
|
||||
final View view = LayoutInflater.from( mContext ).inflate( R.layout.tanlu_bubble_marker, null );
|
||||
final MogoImageView icon = view.findViewById( R.id.icon );
|
||||
mImageloader.displayImage( "http://imgnews.gmw.cn/attachement/jpg/site2/20191229/00d86176ed0b1f71f4580f.jpg", icon, WindowUtils.dip2px( mContext, 50 ), WindowUtils.dip2px( mContext, 50 ),
|
||||
new IMogoImageLoaderListener() {
|
||||
@Override
|
||||
public void onStart() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted( Bitmap bitmap ) {
|
||||
// 刷新图标
|
||||
Logger.d( TAG, "loaded." );
|
||||
options.icon( view );
|
||||
options.notifyObservers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure( Exception e ) {
|
||||
|
||||
}
|
||||
} );
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.mogo.tanlu.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.alibaba.android.arouter.launcher.ARouter;
|
||||
import com.mogo.map.location.IMogoLocationClient;
|
||||
import com.mogo.map.marker.IMogoMarkerManager;
|
||||
import com.mogo.map.navi.IMogoNavi;
|
||||
import com.mogo.map.search.poisearch.IMogoPoiSearch;
|
||||
import com.mogo.map.search.poisearch.query.MogoPoiSearchQuery;
|
||||
import com.mogo.map.uicontroller.IMogoMapUIController;
|
||||
import com.mogo.service.MogoServicePaths;
|
||||
import com.mogo.service.imageloader.IMogoImageloader;
|
||||
import com.mogo.service.map.IMogoMapService;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2019-12-30
|
||||
* <p>
|
||||
* 持有服务接口实例
|
||||
*/
|
||||
public class TanluServiceHandler {
|
||||
|
||||
private static IMogoMapService mMapService;
|
||||
private static IMogoPoiSearch mPoiSearch;
|
||||
private static IMogoLocationClient mLocationClient;
|
||||
private static IMogoMarkerManager mMarkerManager;
|
||||
private static IMogoNavi mNavi;
|
||||
private static IMogoMapUIController mMapUIController;
|
||||
private static IMogoImageloader mImageloader;
|
||||
|
||||
public static void init( Context context ) {
|
||||
mMapService = ( IMogoMapService ) ARouter.getInstance().build( MogoServicePaths.PATH_SERVICES_MAP ).navigation( context );
|
||||
mMapService = ( IMogoMapService ) ARouter.getInstance().build( MogoServicePaths.PATH_SERVICES_MAP ).navigation( context );
|
||||
mImageloader = ( IMogoImageloader ) ARouter.getInstance().build( MogoServicePaths.PATH_UTILS_IMAGE_LOADER ).navigation( context );
|
||||
mPoiSearch = mMapService.getPoiSearch( context, new MogoPoiSearchQuery() );
|
||||
mLocationClient = mMapService.getLocationClient( context );
|
||||
mMarkerManager = mMapService.getMarkerManager( context );
|
||||
mNavi = mMapService.getNavi( context );
|
||||
mMapUIController = mMapService.getMapUIController();
|
||||
}
|
||||
|
||||
public static IMogoMapService getMapService() {
|
||||
return mMapService;
|
||||
}
|
||||
|
||||
public static IMogoPoiSearch getPoiSearch() {
|
||||
return mPoiSearch;
|
||||
}
|
||||
|
||||
public static IMogoLocationClient getLocationClient() {
|
||||
return mLocationClient;
|
||||
}
|
||||
|
||||
public static IMogoMarkerManager getMarkerManager() {
|
||||
return mMarkerManager;
|
||||
}
|
||||
|
||||
public static IMogoNavi getNavi() {
|
||||
return mNavi;
|
||||
}
|
||||
|
||||
public static IMogoMapUIController getMapUIController() {
|
||||
return mMapUIController;
|
||||
}
|
||||
|
||||
public static IMogoImageloader getImageloader() {
|
||||
return mImageloader;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.mogo.tanlu.model;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author lixiaopeng
|
||||
* @description 列表数据
|
||||
* @since 2020-01-05
|
||||
*/
|
||||
public class Information implements Parcelable {
|
||||
private int type;
|
||||
private Double lon;
|
||||
private Double lat;
|
||||
private String addr;
|
||||
private Long generateTime;
|
||||
private String cityName;
|
||||
private ArrayList<Items> items;
|
||||
private int distance;
|
||||
private String nickName;
|
||||
private String headImgUrl;
|
||||
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(this.type);
|
||||
dest.writeValue(this.lon);
|
||||
dest.writeValue(this.lat);
|
||||
dest.writeString(this.addr);
|
||||
dest.writeValue(this.generateTime);
|
||||
dest.writeString(this.cityName);
|
||||
dest.writeTypedList(this.items);
|
||||
dest.writeInt(this.distance);
|
||||
dest.writeString(this.nickName);
|
||||
dest.writeString(this.headImgUrl);
|
||||
}
|
||||
|
||||
public Information() {
|
||||
}
|
||||
|
||||
protected Information(Parcel in) {
|
||||
this.type = in.readInt();
|
||||
this.lon = (Double) in.readValue(Double.class.getClassLoader());
|
||||
this.lat = (Double) in.readValue(Double.class.getClassLoader());
|
||||
this.addr = in.readString();
|
||||
this.generateTime = (Long) in.readValue(Long.class.getClassLoader());
|
||||
this.cityName = in.readString();
|
||||
this.items = in.createTypedArrayList(Items.CREATOR);
|
||||
this.distance = in.readInt();
|
||||
this.nickName = in.readString();
|
||||
this.headImgUrl = in.readString();
|
||||
}
|
||||
|
||||
public static final Creator<Information> CREATOR = new Creator<Information>() {
|
||||
@Override
|
||||
public Information createFromParcel(Parcel source) {
|
||||
return new Information(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Information[] newArray(int size) {
|
||||
return new Information[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.mogo.tanlu.model
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import com.amap.api.maps.model.LatLng
|
||||
|
||||
fun Informations.toLatLng(): LatLng {
|
||||
return LatLng(lat, lon)
|
||||
}
|
||||
|
||||
class Informations(
|
||||
var type: Int,
|
||||
var lon: Double,
|
||||
var lat: Double,
|
||||
var addr: String?,
|
||||
var generateTime: Long,
|
||||
var cityName: String?,
|
||||
// var items: ArrayList<Items>,
|
||||
var distance: Int,
|
||||
var nickName: String?,
|
||||
var headImgUrl: String?
|
||||
) :
|
||||
Parcelable {
|
||||
|
||||
var position = 0
|
||||
|
||||
constructor(parcel: Parcel) : this(
|
||||
parcel.readInt(),
|
||||
parcel.readDouble(),
|
||||
parcel.readDouble(),
|
||||
parcel.readString(),
|
||||
parcel.readLong(),
|
||||
parcel.readString(),
|
||||
// parcel.readArrayList(Items::class.java.classLoader) as ArrayList<Items>,
|
||||
parcel.readInt(),
|
||||
parcel.readString(),
|
||||
parcel.readString()
|
||||
)
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(type)
|
||||
parcel.writeDouble(lon)
|
||||
parcel.writeDouble(lat)
|
||||
parcel.writeString(addr)
|
||||
parcel.writeLong(generateTime)
|
||||
parcel.writeString(cityName)
|
||||
// parcel.writeList(items)
|
||||
parcel.writeInt(distance)
|
||||
parcel.writeString(nickName)
|
||||
parcel.writeString(headImgUrl)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<Informations> {
|
||||
override fun createFromParcel(parcel: Parcel): Informations {
|
||||
return Informations(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<Informations?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.mogo.tanlu.model
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class Items(var url: String? = null, var thumbnail: String? = null) : Parcelable {
|
||||
constructor(parcel: Parcel) : this(
|
||||
parcel.readString(),
|
||||
parcel.readString()
|
||||
) {
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeString(url)
|
||||
parcel.writeString(thumbnail)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<Items> {
|
||||
override fun createFromParcel(parcel: Parcel): Items {
|
||||
return Items(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<Items?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.mogo.tanlu.model.global
|
||||
|
||||
import com.mogo.tanlu.model.Information
|
||||
import java.util.ArrayList
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2019-12-02
|
||||
*
|
||||
* 共享的情报列表,避免在点击大屏查看视频时intent序列化造成的开销
|
||||
*/
|
||||
object GlobalSharedInformation {
|
||||
|
||||
var informationList: ArrayList<Information>? = null
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.mogo.tanlu.util
|
||||
|
||||
|
||||
|
||||
const val SPACE_TIME = 1000
|
||||
var lastClickTime = 0L
|
||||
var viewId: Int = 0
|
||||
|
||||
fun isDoubleClick(view: Int): Boolean {
|
||||
val time = System.currentTimeMillis()
|
||||
val timeD = time - lastClickTime
|
||||
if (timeD < SPACE_TIME && viewId == view) {
|
||||
return true
|
||||
}
|
||||
lastClickTime = time
|
||||
viewId = view
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
fun isDoubleClickTime(view: Int,spaceTime:Int): Boolean {
|
||||
val time = System.currentTimeMillis()
|
||||
val timeD = time - lastClickTime
|
||||
if (timeD < spaceTime && viewId == view) {
|
||||
return true
|
||||
}
|
||||
lastClickTime = time
|
||||
viewId = view
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.mogo.tanlu.util
|
||||
|
||||
import android.os.Message
|
||||
import android.view.View
|
||||
import androidx.constraintlayout.widget.Group
|
||||
|
||||
class HideControl {
|
||||
|
||||
companion object {
|
||||
const val MSG_HIDE = 0x01
|
||||
}
|
||||
|
||||
private var mHideHandler: HideHandler = HideHandler()
|
||||
var view1: Group? = null
|
||||
var view2: Group? = null
|
||||
|
||||
val hideRunable = Runnable {
|
||||
mHideHandler.obtainMessage(MSG_HIDE).sendToTarget()
|
||||
}
|
||||
|
||||
private inner class HideHandler : android.os.Handler() {
|
||||
override fun handleMessage(msg: Message) {
|
||||
super.handleMessage(msg)
|
||||
when (msg.what) {
|
||||
MSG_HIDE -> {
|
||||
view1?.let {
|
||||
it.visibility = View.GONE
|
||||
}
|
||||
view2?.let {
|
||||
it.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun startHideTimer(view1: Group,view2: Group? = null) {
|
||||
this.view1 = view1
|
||||
this.view2 = view2
|
||||
mHideHandler.removeCallbacks(hideRunable)
|
||||
if (view1.visibility == View.GONE) {
|
||||
view1.visibility = View.VISIBLE
|
||||
}
|
||||
if (view2?.visibility == View.GONE) {
|
||||
view2.visibility = View.VISIBLE
|
||||
}
|
||||
mHideHandler.postDelayed(hideRunable, 3000)
|
||||
}
|
||||
|
||||
fun resetHideTimer() {
|
||||
if(view1 != null){
|
||||
view1!!.visibility = View.VISIBLE
|
||||
}
|
||||
if(view2 != null){
|
||||
view2!!.visibility = View.VISIBLE
|
||||
}
|
||||
mHideHandler.removeCallbacks(hideRunable)
|
||||
mHideHandler.postDelayed(hideRunable, 3000)
|
||||
}
|
||||
|
||||
fun endHideTime() {
|
||||
mHideHandler.removeCallbacks(hideRunable)
|
||||
if (view1 != null) {
|
||||
view1 = null
|
||||
}
|
||||
if (view2 != null) {
|
||||
view2 = null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package com.mogo.tanlu.video
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.mogo.tanlu.R
|
||||
import com.mogo.tanlu.model.Informations
|
||||
import com.mogo.tanlu.util.HideControl
|
||||
import com.mogo.utils.logger.Logger
|
||||
import com.shuyu.gsyvideoplayer.GSYVideoManager
|
||||
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
|
||||
import kotlinx.android.synthetic.main.tanlu_activity_media_full.*
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* 全屏显示适配
|
||||
*/
|
||||
|
||||
class FullMediaActivity : AppCompatActivity(), View.OnClickListener {
|
||||
companion object {
|
||||
const val PARAM_MEDIA_DATA = "PARAM_MEDIA_DATA"
|
||||
const val PARAM_MEDIA_POSITION_CALLBACK = "PARAM_MEDIA_POSITION_CALLBACK"
|
||||
const val TAG = "FullMediaActivity"
|
||||
|
||||
const val PARAM_VIDEO_URL = "param_video_url"
|
||||
const val PARAM_THUMB_URL = "param_thumb_url"
|
||||
|
||||
|
||||
// fun launch(context: Activity, strategyInfo: List<Informations>, position: Int) {
|
||||
// val intent = Intent(context, FullMediaActivity::class.java)
|
||||
// intent.putExtra(PARAM_MEDIA_POSITION, position)
|
||||
// // 使用全局静态对象代替,避免序列化开销
|
||||
// GlobalSharedInformation.informationList = strategyInfo as ArrayList<Informations>
|
||||
// context.startActivityForResult(intent, REQUESTCODE_MAINACTIVITY)
|
||||
// context.overridePendingTransition(0, 0)
|
||||
// }
|
||||
|
||||
fun launch(context: Activity, videoUrl: String, thumbnail: String) {
|
||||
val intent = Intent(context, FullMediaActivity::class.java)
|
||||
intent.putExtra(PARAM_VIDEO_URL, videoUrl)
|
||||
intent.putExtra(PARAM_THUMB_URL, thumbnail)
|
||||
context.startActivity(intent)
|
||||
context.overridePendingTransition(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
private var strategyInfo: ArrayList<Informations> = arrayListOf()
|
||||
private var currentImgPosition: Int = 0
|
||||
private var currentPosition: Int = 50
|
||||
private var control = HideControl()
|
||||
private var gsyVideoOptionBuilder = GSYVideoOptionBuilder()
|
||||
private var videoUrl: String? = null
|
||||
private var thumbUrl: String? = null
|
||||
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.tanlu_activity_media_full)
|
||||
handleIntent()
|
||||
setListener()
|
||||
}
|
||||
|
||||
private fun handleIntent() {
|
||||
var intent = intent
|
||||
|
||||
videoUrl = intent.getStringExtra(PARAM_VIDEO_URL)
|
||||
thumbUrl = intent.getStringExtra(PARAM_THUMB_URL)
|
||||
|
||||
Logger.e("liyz", "videoUrl = $videoUrl --->thumbUrl = $thumbUrl")
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
updateInformation()
|
||||
GSYVideoManager.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
GSYVideoManager.onPause()
|
||||
}
|
||||
|
||||
//需要监听完成事件
|
||||
private fun setListener() {
|
||||
iv_media_back.setOnClickListener(this)
|
||||
|
||||
//重置timer
|
||||
video_view.addSingleClickListener(object :
|
||||
MediaCoverVideoPlayer.SingleClickListener {
|
||||
override fun onClick() {
|
||||
control.resetHideTimer()
|
||||
}
|
||||
})
|
||||
|
||||
//视频播放完成
|
||||
video_view.onCompletionListener(object :
|
||||
MediaCoverVideoPlayer.CompletionListener {
|
||||
override fun onCompletion() {
|
||||
GSYVideoManager.releaseAllVideos()
|
||||
finish()
|
||||
}
|
||||
})
|
||||
|
||||
video_view.loadCoverImage(thumbUrl!!)
|
||||
//设置url,点击播放
|
||||
gsyVideoOptionBuilder.setUrl(videoUrl).setCacheWithPlay(true)
|
||||
.setPlayTag(TAG).build(video_view)
|
||||
video_view.startButton.performClick()
|
||||
}
|
||||
|
||||
|
||||
private fun updateInformation() {
|
||||
tv_media_title_content.text = "北京市"
|
||||
tv_media_title_time.text = "2020-1-6"
|
||||
}
|
||||
|
||||
|
||||
override fun onClick(view: View) {
|
||||
view?.let {
|
||||
when (view) {
|
||||
iv_media_back -> {
|
||||
handleBack()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
GSYVideoManager.releaseAllVideos()
|
||||
overridePendingTransition(0, 0)
|
||||
}
|
||||
|
||||
private fun handleBack() {
|
||||
Logger.d("liyz", "handleBack ------> finish ")
|
||||
finish()
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
super.onBackPressed()
|
||||
handleBack()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package com.mogo.tanlu.video
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.mogo.tanlu.R
|
||||
import com.shuyu.gsyvideoplayer.GSYVideoManager
|
||||
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
|
||||
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
|
||||
import com.shuyu.gsyvideoplayer.video.base.GSYVideoViewBridge
|
||||
|
||||
|
||||
/**
|
||||
* 全屏播放
|
||||
*/
|
||||
class MediaCoverVideoPlayer : StandardGSYVideoPlayer {
|
||||
|
||||
private lateinit var coverImage: ImageView
|
||||
private lateinit var start: ImageView
|
||||
private lateinit var fullscreen: ImageView
|
||||
private lateinit var singleClickListener: SingleClickListener
|
||||
private lateinit var completionListener: CompletionListener
|
||||
|
||||
constructor(context: Context?) : super(context)
|
||||
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
|
||||
constructor(context: Context?, fullFlag: Boolean?) : super(context, fullFlag)
|
||||
|
||||
interface SingleClickListener {
|
||||
fun onClick()
|
||||
}
|
||||
|
||||
interface CompletionListener {
|
||||
fun onCompletion()
|
||||
}
|
||||
|
||||
override fun init(context: Context) {
|
||||
super.init(context)
|
||||
coverImage = findViewById(R.id.thumbImage)
|
||||
start = findViewById(R.id.start)
|
||||
fullscreen = findViewById(R.id.fullscreen)
|
||||
if (mThumbImageViewLayout != null
|
||||
&& (mCurrentState == -1 || mCurrentState == GSYVideoView.CURRENT_STATE_NORMAL || mCurrentState == GSYVideoView.CURRENT_STATE_ERROR)
|
||||
) {
|
||||
mThumbImageViewLayout.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
fun addSingleClickListener(singleClickListener: SingleClickListener) {
|
||||
this.singleClickListener = singleClickListener
|
||||
}
|
||||
|
||||
fun onCompletionListener(completionListener: CompletionListener) {
|
||||
this.completionListener = completionListener
|
||||
}
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.tanlu_item_video_cover_media
|
||||
}
|
||||
|
||||
override fun getGSYVideoManager(): GSYVideoViewBridge {
|
||||
GSYVideoManager.instance().initContext(context.applicationContext)
|
||||
return GSYVideoManager.instance()
|
||||
}
|
||||
|
||||
override fun setProgressAndTime(
|
||||
progress: Int,
|
||||
secProgress: Int,
|
||||
currentTime: Int,
|
||||
totalTime: Int
|
||||
) {
|
||||
super.setProgressAndTime(progress, secProgress, currentTime, totalTime)
|
||||
if (progress != 0) {
|
||||
mProgressBar.progress = progress
|
||||
}
|
||||
}
|
||||
|
||||
fun loadCoverImage(url: String) {
|
||||
Glide.with(context)
|
||||
.load(url)
|
||||
.into(coverImage)
|
||||
}
|
||||
|
||||
override fun updateStartImage() {
|
||||
when (mCurrentState) {
|
||||
GSYVideoView.CURRENT_STATE_PLAYING -> start.setImageResource(R.drawable.selector_bg_btn_pause)
|
||||
GSYVideoView.CURRENT_STATE_ERROR -> start.setImageResource(R.mipmap.main_video_refresh_btn)
|
||||
else -> start.setImageResource(R.drawable.selector_bg_btn_play)
|
||||
}
|
||||
}
|
||||
|
||||
fun setFullClickListener(listener: OnClickListener) {
|
||||
fullscreen.setOnClickListener(listener)
|
||||
}
|
||||
|
||||
override fun onClickUiToggle() {
|
||||
super.onClickUiToggle()
|
||||
singleClickListener.let {
|
||||
it.onClick()
|
||||
}
|
||||
}
|
||||
|
||||
override fun changeUiToCompleteShow() {
|
||||
super.changeUiToCompleteShow()
|
||||
setViewShowState(mBottomContainer, View.INVISIBLE)
|
||||
}
|
||||
|
||||
override fun onAutoCompletion() {
|
||||
super.onAutoCompletion()
|
||||
mProgressBar.progress = 0
|
||||
}
|
||||
|
||||
override fun showWifiDialog() {
|
||||
//直接播放,不显示WIFI对话框
|
||||
startPlayLogic()
|
||||
}
|
||||
|
||||
override fun onClick(v: View?) {
|
||||
super.onClick(v)
|
||||
v?.let {
|
||||
when (v) {
|
||||
start -> {
|
||||
|
||||
}
|
||||
else -> {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPrepared() {
|
||||
super.onPrepared()
|
||||
}
|
||||
|
||||
/**
|
||||
* 多次回调? TODO
|
||||
*/
|
||||
override fun onCompletion() {
|
||||
Log.d("liyz", "onCompletion --------->")
|
||||
// completionListener.let {
|
||||
// it.onCompletion()
|
||||
// }
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
mFullPauseBitmap?.let {
|
||||
if (!it.isRecycled) {
|
||||
it.recycle()
|
||||
}
|
||||
}
|
||||
mFullPauseBitmap = null
|
||||
Log.d("MediaCoverVideoPlayer", "recycle.")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.mogo.tanlu.video
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.Surface
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.mogo.tanlu.R
|
||||
import com.shuyu.gsyvideoplayer.GSYVideoManager
|
||||
import com.shuyu.gsyvideoplayer.utils.GSYVideoType
|
||||
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
|
||||
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
|
||||
import com.shuyu.gsyvideoplayer.video.base.GSYVideoViewBridge
|
||||
|
||||
|
||||
class SimpleCoverVideoPlayer : StandardGSYVideoPlayer {
|
||||
private lateinit var coverImage: ImageView
|
||||
private lateinit var start: ImageView
|
||||
private lateinit var fullscreen: ImageView
|
||||
|
||||
constructor(context: Context?) : super(context)
|
||||
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
|
||||
constructor(context: Context?, fullFlag: Boolean?) : super(context, fullFlag)
|
||||
|
||||
override fun init(context: Context) {
|
||||
super.init(context)
|
||||
coverImage = findViewById(R.id.thumbImage)
|
||||
start = findViewById(R.id.start)
|
||||
fullscreen = findViewById(R.id.fullscreen)
|
||||
if (mThumbImageViewLayout != null
|
||||
&& (mCurrentState == -1 || mCurrentState == GSYVideoView.CURRENT_STATE_NORMAL || mCurrentState == GSYVideoView.CURRENT_STATE_ERROR)
|
||||
) {
|
||||
mThumbImageViewLayout.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.tanlu_item_video_cover
|
||||
}
|
||||
|
||||
override fun getGSYVideoManager(): GSYVideoViewBridge {
|
||||
GSYVideoManager.instance().initContext(context.applicationContext)
|
||||
return GSYVideoManager.instance()
|
||||
}
|
||||
|
||||
override fun setProgressAndTime(
|
||||
progress: Int,
|
||||
secProgress: Int,
|
||||
currentTime: Int,
|
||||
totalTime: Int
|
||||
) {
|
||||
super.setProgressAndTime(progress, secProgress, currentTime, totalTime)
|
||||
if (progress != 0) {
|
||||
mProgressBar.progress = progress
|
||||
}
|
||||
}
|
||||
|
||||
// fun loadCoverImage(url: String, mContext: Context) {
|
||||
// Glide.with(mContext.applicationContext)
|
||||
// .load(url)
|
||||
// .error(R.color.color_303447)
|
||||
// .into(coverImage)
|
||||
// }
|
||||
|
||||
override fun updateStartImage() {
|
||||
when (mCurrentState) {
|
||||
GSYVideoView.CURRENT_STATE_PLAYING -> start.setImageResource(R.drawable.selector_bg_btn_pause)
|
||||
GSYVideoView.CURRENT_STATE_ERROR -> start.setImageResource(R.mipmap.main_video_refresh_btn)
|
||||
else -> start.setImageResource(R.drawable.selector_bg_btn_play)
|
||||
}
|
||||
}
|
||||
|
||||
fun setFullClickListener(listener: OnClickListener) {
|
||||
fullscreen.setOnClickListener(listener)
|
||||
}
|
||||
|
||||
override fun changeUiToCompleteShow() {
|
||||
super.changeUiToCompleteShow()
|
||||
setViewShowState(mBottomContainer, View.INVISIBLE)
|
||||
}
|
||||
|
||||
override fun onAutoCompletion() {
|
||||
super.onAutoCompletion()
|
||||
mProgressBar.progress = 0
|
||||
}
|
||||
|
||||
override fun showWifiDialog() {
|
||||
//直接播放,不显示WIFI对话框
|
||||
startPlayLogic()
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
mProgressBar.progress = 0
|
||||
mFullPauseBitmap = null
|
||||
}
|
||||
|
||||
override fun onClick(v: View?) {
|
||||
super.onClick(v)
|
||||
}
|
||||
|
||||
|
||||
override fun onPrepared() {
|
||||
super.onPrepared()
|
||||
}
|
||||
|
||||
override fun onCompletion() {
|
||||
|
||||
}
|
||||
|
||||
override fun onSurfaceUpdated(surface: Surface) {
|
||||
super.onSurfaceUpdated(surface)
|
||||
if (mThumbImageViewLayout != null && mThumbImageViewLayout.visibility == View.VISIBLE) {
|
||||
mThumbImageViewLayout.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun setViewShowState(view: View?, visibility: Int) {
|
||||
if (view === mThumbImageViewLayout && visibility != View.VISIBLE) {
|
||||
return
|
||||
}
|
||||
super.setViewShowState(view, visibility)
|
||||
}
|
||||
|
||||
override fun onSurfaceAvailable(surface: Surface) {
|
||||
super.onSurfaceAvailable(surface)
|
||||
if (GSYVideoType.getRenderType() != GSYVideoType.TEXTURE) {
|
||||
if (mThumbImageViewLayout != null && mThumbImageViewLayout.visibility == View.VISIBLE) {
|
||||
mThumbImageViewLayout.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.mogo.tanlu.video
|
||||
|
||||
import com.shuyu.gsyvideoplayer.GSYVideoManager
|
||||
import com.shuyu.gsyvideoplayer.cache.CacheFactory
|
||||
import com.shuyu.gsyvideoplayer.cache.ProxyCacheManager
|
||||
import com.shuyu.gsyvideoplayer.model.VideoOptionModel
|
||||
import com.shuyu.gsyvideoplayer.player.IjkPlayerManager
|
||||
import com.shuyu.gsyvideoplayer.player.PlayerFactory
|
||||
import com.shuyu.gsyvideoplayer.utils.GSYVideoType
|
||||
import tv.danmaku.ijk.media.player.IjkMediaPlayer
|
||||
|
||||
|
||||
fun initVideo() {
|
||||
PlayerFactory.setPlayManager(IjkPlayerManager::class.java)
|
||||
CacheFactory.setCacheManager(ProxyCacheManager::class.java)
|
||||
var list = mutableListOf<VideoOptionModel>()
|
||||
list.add(VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "enable-accurate-seek", 1))
|
||||
list.add(VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "videotoolbox", 0))
|
||||
GSYVideoManager.instance().optionModelList = list
|
||||
GSYVideoType.enableMediaCodec()
|
||||
GSYVideoType.enableMediaCodecTexture()
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
package com.mogo.tanlu.view
|
||||
|
||||
import android.animation.Animator
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.Context
|
||||
import android.graphics.Matrix
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import com.mogo.service.imageloader.MogoImageView
|
||||
|
||||
class AutoZoomInImageView : MogoImageView {
|
||||
|
||||
companion object {
|
||||
const val TAG = "AutoZoomInImageView"
|
||||
}
|
||||
|
||||
private var mDrawableW: Int = 0
|
||||
private var mDrawableH: Int = 0
|
||||
private var mImageViewW: Int = 0
|
||||
private var mImageViewH: Int = 0
|
||||
private var mDurationMillis = 3000L
|
||||
|
||||
private var mValues = FloatArray(9)
|
||||
var isInit: Boolean = false
|
||||
private var mScaleDelta = 0.2f
|
||||
private var va: ValueAnimator = ValueAnimator.ofFloat(0f, mScaleDelta)
|
||||
|
||||
private lateinit var mDrawable: Drawable
|
||||
private lateinit var mMatrix: Matrix
|
||||
|
||||
private var onStart: (View.() -> Unit)? = null
|
||||
|
||||
private var onUpdate: ((view: View, progress: Float) -> Unit)? = null
|
||||
|
||||
private var onEnd: (View.() -> Unit)? = null
|
||||
|
||||
infix fun onStart(onStart: View.() -> Unit) :AutoZoomInImageView{
|
||||
this.onStart = onStart
|
||||
return this
|
||||
}
|
||||
|
||||
infix fun onUpdate(onUpdate: (view: View, progress: Float) -> Unit) :AutoZoomInImageView{
|
||||
this.onUpdate = onUpdate
|
||||
return this
|
||||
}
|
||||
|
||||
infix fun onEnd(onEnd: View.() -> Unit):AutoZoomInImageView {
|
||||
this.onEnd = onEnd
|
||||
return this
|
||||
}
|
||||
|
||||
constructor(context: Context?) : super(context) {
|
||||
this.scaleType = ScaleType.MATRIX
|
||||
}
|
||||
|
||||
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
|
||||
this.scaleType = ScaleType.MATRIX
|
||||
}
|
||||
|
||||
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
|
||||
context,
|
||||
attrs,
|
||||
defStyleAttr
|
||||
) {
|
||||
this.scaleType = ScaleType.MATRIX
|
||||
}
|
||||
|
||||
|
||||
fun init(): AutoZoomInImageView {
|
||||
initInternalValues()
|
||||
initPicturePosition()
|
||||
isInit = true
|
||||
return this
|
||||
}
|
||||
|
||||
fun init(drawable: Drawable) {
|
||||
initInternalValues(drawable)
|
||||
initPicturePosition()
|
||||
}
|
||||
|
||||
private fun initInternalValues() {
|
||||
mDrawable = drawable
|
||||
|
||||
mDrawableW = mDrawable.intrinsicWidth
|
||||
mDrawableH = mDrawable.intrinsicHeight
|
||||
|
||||
mImageViewW = measuredWidth
|
||||
mImageViewH = measuredHeight
|
||||
|
||||
mMatrix = imageMatrix
|
||||
mMatrix.getValues(mValues)
|
||||
}
|
||||
|
||||
private fun initInternalValues(drawable: Drawable) {
|
||||
mDrawable = drawable
|
||||
|
||||
mDrawableW = mDrawable.intrinsicWidth
|
||||
mDrawableH = mDrawable.intrinsicHeight
|
||||
|
||||
mImageViewW = measuredWidth
|
||||
mImageViewH = measuredHeight
|
||||
|
||||
mMatrix = imageMatrix
|
||||
mMatrix.getValues(mValues)
|
||||
}
|
||||
|
||||
private fun initPicturePosition() {
|
||||
updateMatrixValuesOrigin(
|
||||
mMatrix,
|
||||
mValues,
|
||||
mDrawableW.toFloat(),
|
||||
mDrawableH.toFloat(),
|
||||
mImageViewW.toFloat(),
|
||||
mImageViewH.toFloat()
|
||||
)
|
||||
imageMatrix = mMatrix
|
||||
}
|
||||
|
||||
fun setDurationMillis(durationMillis: Long): AutoZoomInImageView {
|
||||
mDurationMillis = durationMillis
|
||||
return this
|
||||
}
|
||||
|
||||
fun startZoomInByScaleDelta(scaleDelta: Float = 0.2f, duration: Long = 3000) {
|
||||
val oriScaleX = mValues[0]
|
||||
val oriScaleY = mValues[4]
|
||||
|
||||
va.addUpdateListener { animation ->
|
||||
val value = animation.animatedValue as Float
|
||||
onUpdate?.invoke(this@AutoZoomInImageView, value / scaleDelta)
|
||||
updateMatrixValuesSpan(
|
||||
mValues,
|
||||
mDrawableW.toFloat(),
|
||||
mDrawableH.toFloat(),
|
||||
mImageViewW.toFloat(),
|
||||
mImageViewH.toFloat(),
|
||||
oriScaleX,
|
||||
oriScaleY,
|
||||
value
|
||||
)
|
||||
mMatrix.setValues(mValues)
|
||||
imageMatrix = mMatrix
|
||||
}
|
||||
va.addListener(object : Animator.AnimatorListener {
|
||||
override fun onAnimationStart(animation: Animator) {
|
||||
onStart?.invoke(this@AutoZoomInImageView)
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
onEnd?.invoke(this@AutoZoomInImageView)
|
||||
}
|
||||
|
||||
override fun onAnimationCancel(animation: Animator) {}
|
||||
override fun onAnimationRepeat(animation: Animator) {}
|
||||
})
|
||||
va.duration = duration
|
||||
va.start()
|
||||
}
|
||||
|
||||
fun zoomPause() {
|
||||
if (va.isRunning) {
|
||||
Log.d(TAG, "pause")
|
||||
va.pause()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun zoomResume() {
|
||||
if (va.isStarted && va.isPaused) {
|
||||
Log.d(TAG, "resume")
|
||||
va.resume()
|
||||
} else {
|
||||
Log.d(TAG, "restart")
|
||||
va.start()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateMatrixValuesOrigin(
|
||||
outMatrix: Matrix?,
|
||||
outValues: FloatArray?,
|
||||
drawW: Float,
|
||||
drawH: Float,
|
||||
imageW: Float,
|
||||
imageH: Float
|
||||
) {
|
||||
if (outMatrix == null || outValues == null) {
|
||||
throw IllegalArgumentException("please set the source of AutoZoomInImageView's matrix and values")
|
||||
}
|
||||
outMatrix.reset()
|
||||
|
||||
if (imageH * drawW > drawH * imageW) {
|
||||
val scale1 = imageH / drawH
|
||||
val offset1 = (drawW * scale1 - imageW) / 2
|
||||
outMatrix.postScale(scale1, scale1)
|
||||
outMatrix.postTranslate(-offset1, 0f)
|
||||
} else {
|
||||
val scale2 = imageW / drawW
|
||||
val offset2 = (drawH * scale2 - imageH) / 2
|
||||
outMatrix.postScale(scale2, scale2)
|
||||
outMatrix.postTranslate(0f, -offset2)
|
||||
}
|
||||
outMatrix.getValues(outValues)
|
||||
}
|
||||
|
||||
private fun updateMatrixValuesSpan(
|
||||
outValues: FloatArray,
|
||||
drawW: Float, drawH: Float,
|
||||
imageW: Float, imageH: Float,
|
||||
oriScaleX: Float, oriScaleY: Float,
|
||||
scaleDelta: Float
|
||||
) {
|
||||
outValues[0] = oriScaleX * (1 + scaleDelta)
|
||||
outValues[4] = oriScaleY * (1 + scaleDelta)
|
||||
val offsetwidth = (drawW * outValues[0] - imageW) / 2
|
||||
outValues[2] = -offsetwidth
|
||||
val offsetHeight = (drawH * outValues[4] - imageH) / 2
|
||||
outValues[5] = -offsetHeight
|
||||
}
|
||||
}
|
||||
BIN
modules/mogo-module-tanlu/src/main/res/drawable-ldpi/amap_bus.png
Executable file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
modules/mogo-module-tanlu/src/main/res/drawable-ldpi/amap_car.png
Executable file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
modules/mogo-module-tanlu/src/main/res/drawable-ldpi/amap_end.png
Executable file
|
After Width: | Height: | Size: 11 KiB |
BIN
modules/mogo-module-tanlu/src/main/res/drawable-ldpi/amap_man.png
Executable file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
modules/mogo-module-tanlu/src/main/res/drawable-ldpi/amap_ride.png
Executable file
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 347 B |
|
After Width: | Height: | Size: 384 B |
|
After Width: | Height: | Size: 375 B |
|
After Width: | Height: | Size: 354 B |
|
After Width: | Height: | Size: 380 B |
|
After Width: | Height: | Size: 387 B |
|
After Width: | Height: | Size: 382 B |
|
After Width: | Height: | Size: 340 B |
|
After Width: | Height: | Size: 341 B |
|
After Width: | Height: | Size: 323 B |
BIN
modules/mogo-module-tanlu/src/main/res/drawable-ldpi/amap_start.png
Executable file
|
After Width: | Height: | Size: 10 KiB |