Merge branch 'dev_robotaxi-d-app-module_280_220608_2.8.0' into dev_robotaxi-d-app-module_280_taxi_passenger
# Conflicts: # OCH/mogo-och-taxi-passenger/build.gradle # OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModel.java # OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/network/TaxiPassengerServiceApi.java
@@ -47,8 +47,8 @@ dependencies {
|
||||
implementation rootProject.ext.dependencies.kotlinstdlibjdk7
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
implementation rootProject.ext.dependencies.arouter
|
||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.2.1'
|
||||
implementation rootProject.ext.dependencies.androidxrecyclerview
|
||||
implementation rootProject.ext.dependencies.material
|
||||
annotationProcessor rootProject.ext.dependencies.aroutercompiler
|
||||
implementation rootProject.ext.dependencies.rxandroid
|
||||
implementation rootProject.ext.dependencies.androidxconstraintlayout
|
||||
|
||||
@@ -49,10 +49,11 @@ public class BusPassengerTrafficLightView extends IViewTrafficLight {
|
||||
* 展示红绿灯预警
|
||||
*
|
||||
* @param checkLightId 0-都是默认,1-红,2-黄,3-绿
|
||||
* @param lightSource 1:云端下发;2:自车感知
|
||||
*/
|
||||
@Override
|
||||
public void showWarningTrafficLight(int checkLightId) {
|
||||
super.showWarningTrafficLight(checkLightId);
|
||||
public void showWarningTrafficLight(int checkLightId,int lightSource) {
|
||||
super.showWarningTrafficLight(checkLightId,lightSource);
|
||||
mCurrentLightId = checkLightId;
|
||||
updateTrafficLightIcon(checkLightId);
|
||||
}
|
||||
|
||||
@@ -16,12 +16,12 @@ public class BusRoutesResult {
|
||||
private int status;
|
||||
|
||||
//线路轨迹相关字段
|
||||
public String csvFileUrl; //轨迹文件下载的cos url,默认“”
|
||||
public String csvFileMd5; //轨迹文件md5,默认“”
|
||||
public String txtFileUrl; //打点文件下载的cos url,默认“”
|
||||
public String txtFileMd5; //轨迹文件md5,默认“”
|
||||
public String csvFileUrl = ""; //轨迹文件下载的cos url,默认“”
|
||||
public String csvFileMd5 = ""; //轨迹文件md5,默认“”
|
||||
public String txtFileUrl = ""; //打点文件下载的cos url,默认“”
|
||||
public String txtFileMd5 = ""; //轨迹文件md5,默认“”
|
||||
public long contrailSaveTime; //上传轨迹完成时间戳ms:用于MEC本地手动导入轨迹验证时不会被云端轨迹覆盖
|
||||
public String carModel; //[optional] 车型号(如红旗H9),默认“”,暂不加入校验逻辑、用于人工排查问题
|
||||
public String carModel = ""; //[optional] 车型号(如红旗H9),默认“”,暂不加入校验逻辑、用于人工排查问题
|
||||
|
||||
public int getLineId() {
|
||||
return lineId;
|
||||
@@ -48,6 +48,12 @@ public class BusRoutesResult {
|
||||
", lineType=" + lineType +
|
||||
", description='" + description + '\'' +
|
||||
", status=" + status +
|
||||
", csvFileUrl='" + csvFileUrl + '\'' +
|
||||
", csvFileMd5='" + csvFileMd5 + '\'' +
|
||||
", txtFileUrl='" + txtFileUrl + '\'' +
|
||||
", txtFileMd5='" + txtFileMd5 + '\'' +
|
||||
", contrailSaveTime=" + contrailSaveTime +
|
||||
", carModel='" + carModel + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import android.text.TextUtils;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.amap.api.maps.model.LatLng;
|
||||
import com.elegant.network.utils.GsonUtil;
|
||||
import com.mogo.commons.AbsMogoApplication;
|
||||
import com.mogo.commons.debug.DebugConfig;
|
||||
import com.mogo.commons.voice.AIAssist;
|
||||
@@ -508,20 +509,27 @@ public class BusOrderModel {
|
||||
// == CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()) {
|
||||
// ToastUtils.showShort("自动驾驶状态为不可用!");
|
||||
// }
|
||||
AutopilotControlParameters currentAutopilot = new AutopilotControlParameters();
|
||||
currentAutopilot.isSpeakVoice = !isRestart;
|
||||
currentAutopilot.routeID = busRoutesResult.getLineId();
|
||||
currentAutopilot.routeName = busRoutesResult.getName();
|
||||
currentAutopilot.startName = PinYinUtil.getPinYinHeadChar(currentStation.getName());
|
||||
currentAutopilot.endName = PinYinUtil.getPinYinHeadChar(nextStation.getName());
|
||||
currentAutopilot.startLatLon = new AutopilotControlParameters
|
||||
AutopilotControlParameters parameters = new AutopilotControlParameters();
|
||||
parameters.isSpeakVoice = !isRestart;
|
||||
parameters.routeID = busRoutesResult.getLineId();
|
||||
parameters.routeName = busRoutesResult.getName();
|
||||
parameters.startName = PinYinUtil.getPinYinHeadChar(currentStation.getName());
|
||||
parameters.endName = PinYinUtil.getPinYinHeadChar(nextStation.getName());
|
||||
parameters.startLatLon = new AutopilotControlParameters
|
||||
.AutoPilotLonLat( currentStation.getLat(), currentStation.getLon() );
|
||||
currentAutopilot.endLatLon = new AutopilotControlParameters
|
||||
parameters.endLatLon = new AutopilotControlParameters
|
||||
.AutoPilotLonLat( nextStation.getLat(), nextStation.getLon() );
|
||||
currentAutopilot.vehicleType = VEHICLE_TYPE;
|
||||
CallerLogger.INSTANCE.d( M_BUS + TAG, "开启自动驾驶====" + currentAutopilot.toString()
|
||||
parameters.vehicleType = VEHICLE_TYPE;
|
||||
if (parameters.autoPilotLine == null) {
|
||||
parameters.autoPilotLine = new AutopilotControlParameters.AutoPilotLine(
|
||||
busRoutesResult.getLineId(),
|
||||
busRoutesResult.csvFileUrl, busRoutesResult.csvFileMd5,
|
||||
busRoutesResult.txtFileUrl, busRoutesResult.txtFileMd5,
|
||||
busRoutesResult.contrailSaveTime, busRoutesResult.carModel);
|
||||
}
|
||||
CallerLogger.INSTANCE.d( M_BUS + TAG, "开启自动驾驶====" + GsonUtil.jsonFromObject(parameters)
|
||||
+" startLatLon="+currentStation.getName()+",endLatLon="+nextStation.getName());
|
||||
CallerAutoPilotManager.INSTANCE.startAutoPilot(currentAutopilot);
|
||||
CallerAutoPilotManager.INSTANCE.startAutoPilot(parameters);
|
||||
|
||||
triggerStartServiceEvent(isRestart, false);
|
||||
|
||||
|
||||
@@ -148,8 +148,7 @@ public interface IBusApiService {
|
||||
Observable<BusQueryLinesResponse> queryBusLines(@Header ("appId") String appId, @Header("ticket") String ticket, @Query("sn") String sn);
|
||||
|
||||
@Headers( {"Content-type:application/json;charset=UTF-8"} )
|
||||
// @POST( "/autopilot-car-hailing/location/v2/driver/heartbeat" )
|
||||
@POST( "/autopilot-car-hailing/location/v2/driver/bus/heartbeat" )
|
||||
@POST( "/autopilot-car-hailing/location/v2/driver/bus/saveLineCoordinate" )
|
||||
Observable<BaseData> updateOrderRoute(@Header ("appId") String appId, @Header("ticket") String ticket, @Body BusRoutePlanningUpdateReqBean data);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,10 +46,11 @@ public class BusTrafficLightView extends IViewTrafficLight {
|
||||
* 展示红绿灯预警
|
||||
*
|
||||
* @param checkLightId 0-都是默认,1-红,2-黄,3-绿
|
||||
* @param lightSource 1:云端下发;2:自车感知
|
||||
*/
|
||||
@Override
|
||||
public void showWarningTrafficLight(int checkLightId) {
|
||||
super.showWarningTrafficLight(checkLightId);
|
||||
public void showWarningTrafficLight(int checkLightId,int lightSource) {
|
||||
super.showWarningTrafficLight(checkLightId,lightSource);
|
||||
mCurrentLightId = checkLightId;
|
||||
updateTrafficLightIcon(checkLightId);
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ android {
|
||||
dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation 'androidx.core:core-ktx:1.1.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.2.1'
|
||||
implementation rootProject.ext.dependencies.androidxccorektx
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
implementation rootProject.ext.dependencies.material
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
package com.mogo.och.common.module.wigets.sfv;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
import com.elegant.utils.UiThreadHandler;
|
||||
|
||||
public abstract class BaseSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
|
||||
public static final int DEFAULT_FRAME_DURATION_MILLISECOND = 50;
|
||||
|
||||
private HandlerThread handlerThread;
|
||||
private SurfaceViewHandler handler;
|
||||
protected int frameDuration = DEFAULT_FRAME_DURATION_MILLISECOND;
|
||||
private Canvas canvas;
|
||||
private boolean isAlive;
|
||||
|
||||
public BaseSurfaceView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public BaseSurfaceView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public BaseSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
}
|
||||
|
||||
protected int getFrameDuration() {
|
||||
return frameDuration;
|
||||
}
|
||||
|
||||
protected void setFrameDuration(int frameDuration) {
|
||||
this.frameDuration = frameDuration;
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
getHolder().addCallback(this);
|
||||
setBackgroundTransparent();
|
||||
}
|
||||
|
||||
private void setBackgroundTransparent() {
|
||||
getHolder().setFormat(PixelFormat.TRANSLUCENT);
|
||||
setZOrderOnTop(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
isAlive = true;
|
||||
startDrawThread();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
stopDrawThread();
|
||||
isAlive = false;
|
||||
}
|
||||
|
||||
private void stopDrawThread() {
|
||||
isAlive = false;
|
||||
handlerThread.quit();
|
||||
handler = null;
|
||||
}
|
||||
|
||||
private void startDrawThread() {
|
||||
handlerThread = new HandlerThread("SurfaceViewThread");
|
||||
handlerThread.start();
|
||||
handler = new SurfaceViewHandler(handlerThread.getLooper());
|
||||
handler.post(new DrawRunnable());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int originWidth = getMeasuredWidth();
|
||||
int originHeight = getMeasuredHeight();
|
||||
int width = widthMode == MeasureSpec.AT_MOST ? getDefaultWidth() : originWidth;
|
||||
int height = heightMode == MeasureSpec.AT_MOST ? getDefaultHeight() : originHeight;
|
||||
setMeasuredDimension(width, height);
|
||||
Log.v("ttaylor", "BaseSurfaceView.onMeasure()" + " default Width=" + getDefaultWidth() + " default height=" + getDefaultHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* the width is used when wrap_content is set to layout_width
|
||||
* the child knows how big it should be
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected abstract int getDefaultWidth();
|
||||
|
||||
/**
|
||||
* the height is used when wrap_content is set to layout_height
|
||||
* the child knows how big it should be
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected abstract int getDefaultHeight();
|
||||
|
||||
|
||||
private class SurfaceViewHandler extends Handler {
|
||||
|
||||
public SurfaceViewHandler(Looper looper) {
|
||||
super(looper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
super.handleMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private class DrawRunnable implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isAlive) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
canvas = getHolder().lockCanvas();
|
||||
onFrameDraw(canvas);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
getHolder().unlockCanvasAndPost(canvas);
|
||||
onFrameDrawFinish();
|
||||
}
|
||||
|
||||
handler.postDelayed(this, frameDuration);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* it is will be invoked after one frame is drawn
|
||||
*/
|
||||
protected abstract void onFrameDrawFinish();
|
||||
|
||||
/**
|
||||
* draw one frame to the surface by canvas
|
||||
*
|
||||
* @param canvas
|
||||
*/
|
||||
protected abstract void onFrameDraw(Canvas canvas);
|
||||
|
||||
protected void runOnUIThread( Runnable executor ) {
|
||||
if ( executor == null ) {
|
||||
return;
|
||||
}
|
||||
if ( Looper.myLooper() != Looper.getMainLooper() ) {
|
||||
UiThreadHandler.post( executor );
|
||||
} else {
|
||||
executor.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.mogo.och.common.module.wigets.sfv;
|
||||
|
||||
public interface FrameFinishCallback {
|
||||
void onFinishCallback();
|
||||
}
|
||||
@@ -0,0 +1,404 @@
|
||||
package com.mogo.och.common.module.wigets.sfv;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* a SurfaceView which draws bitmaps one after another like frame animation
|
||||
*/
|
||||
public class FrameSurfaceView extends BaseSurfaceView {
|
||||
public static final int INVALID_INDEX = Integer.MAX_VALUE;
|
||||
private int bufferSize = 3;
|
||||
public static final String DECODE_THREAD_NAME = "DecodingThread";
|
||||
public static final int INFINITE = -1;
|
||||
//-1 means repeat infinitely
|
||||
private int repeatTimes;
|
||||
private int repeatedCount;
|
||||
|
||||
/**
|
||||
* the resources of frame animation
|
||||
*/
|
||||
private List<Integer> bitmapIds = new ArrayList<>();
|
||||
/**
|
||||
* the index of bitmap resource which is decoding
|
||||
*/
|
||||
private int bitmapIdIndex;
|
||||
/**
|
||||
* the index of frame which is drawing
|
||||
*/
|
||||
private AtomicInteger frameIndex;
|
||||
/**
|
||||
* decoded bitmaps stores in this queue
|
||||
* consumer is drawing thread, producer is decoding thread.
|
||||
*/
|
||||
private LinkedBlockingQueue decodedBitmaps = new LinkedBlockingQueue(bufferSize);
|
||||
/**
|
||||
* bitmaps already drawn by canvas stores in this queue
|
||||
* consumer is decoding thread, producer is drawing thread.
|
||||
*/
|
||||
private LinkedBlockingQueue drawnBitmaps = new LinkedBlockingQueue(bufferSize);
|
||||
/**
|
||||
* the thread for decoding bitmaps
|
||||
*/
|
||||
private HandlerThread decodeThread;
|
||||
/**
|
||||
* the Runnable describes how to decode one bitmap
|
||||
*/
|
||||
private DecodeRunnable decodeRunnable;
|
||||
/**
|
||||
* this handler helps to decode bitmap one after another
|
||||
*/
|
||||
private Handler handler;
|
||||
private BitmapFactory.Options options;
|
||||
private Paint paint = new Paint();
|
||||
private Rect srcRect;
|
||||
private Rect dstRect = new Rect();
|
||||
private int defaultWidth;
|
||||
private int defaultHeight;
|
||||
|
||||
private FrameFinishCallback frameFinishCallback;
|
||||
|
||||
public FrameSurfaceView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public FrameSurfaceView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public FrameSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public void setRepeatTimes(int repeatTimes) {
|
||||
this.repeatTimes = repeatTimes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
options = new BitmapFactory.Options();
|
||||
options.inMutable = true;
|
||||
decodeThread = new HandlerThread(DECODE_THREAD_NAME);
|
||||
frameIndex = new AtomicInteger();
|
||||
frameIndex.set(INVALID_INDEX);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
dstRect.set(0, 0, getWidth(), getHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDefaultWidth() {
|
||||
return defaultWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDefaultHeight() {
|
||||
return defaultHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFrameDrawFinish() {
|
||||
}
|
||||
|
||||
/**
|
||||
* set the duration of frame animation
|
||||
*
|
||||
* @param duration time in milliseconds
|
||||
*/
|
||||
public void setDuration(int duration) {
|
||||
int frameDuration = duration / bitmapIds.size();
|
||||
setFrameDuration(frameDuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the materials of frame animation which is an array of bitmap resource id
|
||||
*
|
||||
* @param bitmapIds an array of bitmap resource id
|
||||
*/
|
||||
public void setBitmapIds(List<Integer> bitmapIds) {
|
||||
if (bitmapIds == null || bitmapIds.size() == 0) {
|
||||
return;
|
||||
}
|
||||
this.bitmapIds = bitmapIds;
|
||||
//by default, take the first bitmap's dimension into consideration
|
||||
getBitmapDimension(bitmapIds.get(bitmapIdIndex));
|
||||
preloadFrames();
|
||||
decodeRunnable = new DecodeRunnable(bitmapIdIndex, bitmapIds, options);
|
||||
}
|
||||
|
||||
private void getBitmapDimension(int bitmapId) {
|
||||
final BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inJustDecodeBounds = true;
|
||||
BitmapFactory.decodeResource(this.getResources(), bitmapId, options);
|
||||
defaultWidth = options.outWidth;
|
||||
defaultHeight = options.outHeight;
|
||||
srcRect = new Rect(0, 0, defaultWidth, defaultHeight);
|
||||
//we have to re-measure to make defaultWidth in use in onMeasure()
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
* load the first several frames of animation before it is started
|
||||
*/
|
||||
private void preloadFrames() {
|
||||
decodeAndPutBitmap(bitmapIds.get(bitmapIdIndex++), options, new LinkedBitmap());
|
||||
decodeAndPutBitmap(bitmapIds.get(bitmapIdIndex++), options, new LinkedBitmap());
|
||||
}
|
||||
|
||||
/**
|
||||
* recycle the bitmap used by frame animation.
|
||||
* Usually it should be invoked when the ui of frame animation is no longer visible
|
||||
*/
|
||||
public void destroy() {
|
||||
if (drawnBitmaps != null) {
|
||||
drawnBitmaps.clear();
|
||||
}
|
||||
if (decodeThread != null) {
|
||||
decodeThread.quit();
|
||||
decodeThread = null;
|
||||
}
|
||||
if (handler != null) {
|
||||
handler = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFrameDraw(Canvas canvas) {
|
||||
clearCanvas(canvas);
|
||||
if (!isStart()) {
|
||||
return;
|
||||
}
|
||||
if (!isFinish()) {
|
||||
drawOneFrame(canvas);
|
||||
} else {
|
||||
onFrameAnimationEnd();
|
||||
if (repeatTimes != 0 && repeatTimes == INFINITE) {
|
||||
start();
|
||||
} else if (repeatedCount < repeatTimes) {
|
||||
start();
|
||||
repeatedCount++;
|
||||
} else {
|
||||
repeatedCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* draw a single frame which is a bitmap
|
||||
*
|
||||
* @param canvas
|
||||
*/
|
||||
private void drawOneFrame(Canvas canvas) {
|
||||
LinkedBitmap linkedBitmap = getDecodedBitmap();
|
||||
if (linkedBitmap != null) {
|
||||
canvas.drawBitmap(linkedBitmap.bitmap, srcRect, dstRect, paint);
|
||||
}
|
||||
putDrawnBitmap(linkedBitmap);
|
||||
frameIndex.incrementAndGet();
|
||||
if(isFinish()&&frameFinishCallback!=null){
|
||||
runOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
frameFinishCallback.onFinishCallback();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* invoked when frame animation is done
|
||||
*/
|
||||
private void onFrameAnimationEnd() {
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* reset the index of frame, preparing for the next frame animation
|
||||
*/
|
||||
public void reset() {
|
||||
frameIndex.set(INVALID_INDEX);
|
||||
}
|
||||
|
||||
/**
|
||||
* whether frame animation is finished
|
||||
*
|
||||
* @return true: animation is finished, false: animation is doing
|
||||
*/
|
||||
private boolean isFinish() {
|
||||
return frameIndex.get() >= bitmapIds.size() - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* whether frame animation is started
|
||||
*
|
||||
* @return true: animation is started, false: animation is not started
|
||||
*/
|
||||
private boolean isStart() {
|
||||
return frameIndex.get() != INVALID_INDEX;
|
||||
}
|
||||
|
||||
/**
|
||||
* start frame animation from the first frame
|
||||
*/
|
||||
public void start() {
|
||||
frameIndex.compareAndSet(INVALID_INDEX, 0);
|
||||
if (decodeThread == null) {
|
||||
decodeThread = new HandlerThread(DECODE_THREAD_NAME);
|
||||
}
|
||||
if (!decodeThread.isAlive()) {
|
||||
decodeThread.start();
|
||||
}
|
||||
if (handler == null) {
|
||||
handler = new Handler(decodeThread.getLooper());
|
||||
}
|
||||
if (decodeRunnable != null) {
|
||||
decodeRunnable.setIndex(0);
|
||||
}
|
||||
handler.post(decodeRunnable);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* clear out the drawing on canvas,preparing for the next frame
|
||||
* * @param canvas
|
||||
*/
|
||||
private void clearCanvas(Canvas canvas) {
|
||||
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
|
||||
canvas.drawPaint(paint);
|
||||
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
|
||||
}
|
||||
|
||||
/**
|
||||
* decode bitmap by BitmapFactory.decodeStream(), it is about twice faster than BitmapFactory.decodeResource()
|
||||
*
|
||||
* @param resId the bitmap resource
|
||||
* @param options
|
||||
* @return
|
||||
*/
|
||||
private Bitmap decodeBitmap(int resId, BitmapFactory.Options options) {
|
||||
options.inScaled = false;
|
||||
InputStream inputStream = getResources().openRawResource(resId);
|
||||
return BitmapFactory.decodeStream(inputStream, null, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* reuse bitmap in drawnBitmaps to decode new bitmap
|
||||
*
|
||||
* @param resId
|
||||
* @param options
|
||||
*/
|
||||
private void decodedBitmapByReuse(int resId, BitmapFactory.Options options) {
|
||||
LinkedBitmap linkedBitmap = getDrawnBitmap();
|
||||
if (linkedBitmap == null) {
|
||||
linkedBitmap = new LinkedBitmap();
|
||||
}
|
||||
options.inBitmap = linkedBitmap.bitmap;
|
||||
decodeAndPutBitmap(resId, options, linkedBitmap);
|
||||
}
|
||||
|
||||
/**
|
||||
* decode bitmap and put it into decodedBitmaps
|
||||
*
|
||||
* @param resId
|
||||
* @param options
|
||||
* @param linkedBitmap
|
||||
*/
|
||||
private void decodeAndPutBitmap(int resId, BitmapFactory.Options options, LinkedBitmap linkedBitmap) {
|
||||
Bitmap bitmap = decodeBitmap(resId, options);
|
||||
linkedBitmap.bitmap = bitmap;
|
||||
try {
|
||||
decodedBitmaps.put(linkedBitmap);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void putDrawnBitmap(LinkedBitmap bitmap) {
|
||||
drawnBitmaps.offer(bitmap);
|
||||
}
|
||||
|
||||
/**
|
||||
* get bitmap which already drawn by canvas
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private LinkedBitmap getDrawnBitmap() {
|
||||
LinkedBitmap bitmap = null;
|
||||
try {
|
||||
bitmap = drawnBitmaps.take();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* get decoded bitmap in the decoded bitmap queue
|
||||
* it might block due to new bitmap is not ready
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private LinkedBitmap getDecodedBitmap() {
|
||||
LinkedBitmap bitmap = null;
|
||||
try {
|
||||
bitmap = decodedBitmaps.take();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public FrameFinishCallback getFrameFinishCallback() {
|
||||
return frameFinishCallback;
|
||||
}
|
||||
|
||||
public void setFrameFinishCallback(FrameFinishCallback frameFinishCallback) {
|
||||
this.frameFinishCallback = frameFinishCallback;
|
||||
}
|
||||
|
||||
private class DecodeRunnable implements Runnable {
|
||||
|
||||
private int index;
|
||||
private List<Integer> bitmapIds;
|
||||
private BitmapFactory.Options options;
|
||||
|
||||
public DecodeRunnable(int index, List<Integer> bitmapIds, BitmapFactory.Options options) {
|
||||
this.index = index;
|
||||
this.bitmapIds = bitmapIds;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
decodedBitmapByReuse(bitmapIds.get(index), options);
|
||||
index++;
|
||||
if (index < bitmapIds.size()) {
|
||||
handler.post(this);
|
||||
} else {
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.mogo.och.common.module.wigets.sfv;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
/**
|
||||
* a structure used by LinkedBlockingQueue to keep bitmap
|
||||
*/
|
||||
public class LinkedBitmap {
|
||||
public Bitmap bitmap;
|
||||
public LinkedBitmap next;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
package com.mogo.och.common.module.wigets.sfv;
|
||||
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class LinkedBlockingQueue {
|
||||
/**
|
||||
* Current number of elements
|
||||
*/
|
||||
private final AtomicInteger count = new AtomicInteger();
|
||||
/**
|
||||
* Lock held by take, poll, etc
|
||||
*/
|
||||
private final ReentrantLock takeLock = new ReentrantLock();
|
||||
|
||||
/**
|
||||
* Wait queue for waiting takes
|
||||
*/
|
||||
private final Condition notEmpty = takeLock.newCondition();
|
||||
|
||||
/**
|
||||
* Lock held by put, offer, etc
|
||||
*/
|
||||
private final ReentrantLock putLock = new ReentrantLock();
|
||||
|
||||
/**
|
||||
* Wait queue for waiting puts
|
||||
*/
|
||||
private final Condition notFull = putLock.newCondition();
|
||||
/**
|
||||
* The capacity bound, or Integer.MAX_VALUE if none
|
||||
*/
|
||||
private final int capacity;
|
||||
/**
|
||||
* the first element in the queue
|
||||
*/
|
||||
private LinkedBitmap head;
|
||||
/**
|
||||
* the last element int the queue
|
||||
*/
|
||||
private LinkedBitmap tail;
|
||||
|
||||
|
||||
public LinkedBlockingQueue(int capacity) {
|
||||
if (capacity <= 0) throw new IllegalArgumentException();
|
||||
this.capacity = capacity;
|
||||
}
|
||||
|
||||
public void put(LinkedBitmap bitmap) throws InterruptedException {
|
||||
if (bitmap == null) throw new NullPointerException();
|
||||
// Note: convention in all put/take/etc is to preset local var
|
||||
// holding count negative to indicate failure unless set.
|
||||
int c = -1;
|
||||
final ReentrantLock putLock = this.putLock;
|
||||
final AtomicInteger count = this.count;
|
||||
putLock.lockInterruptibly();
|
||||
try {
|
||||
/*
|
||||
* Note that count is used in wait guard even though it is
|
||||
* not protected by lock. This works because count can
|
||||
* only decrease at this point (all other puts are shut
|
||||
* out by lock), and we (or some other waiting put) are
|
||||
* signalled if it ever changes from capacity. Similarly
|
||||
* for all other uses of count in other wait guards.
|
||||
*/
|
||||
while (count.get() == capacity) {
|
||||
notFull.await();
|
||||
}
|
||||
enqueue(bitmap);
|
||||
c = count.getAndIncrement();
|
||||
if (c + 1 < capacity)
|
||||
notFull.signal();
|
||||
} finally {
|
||||
putLock.unlock();
|
||||
}
|
||||
if (c == 0)
|
||||
signalNotEmpty();
|
||||
}
|
||||
|
||||
public boolean offer(LinkedBitmap bitmap) {
|
||||
if (bitmap == null) throw new NullPointerException();
|
||||
final AtomicInteger count = this.count;
|
||||
if (count.get() == capacity)
|
||||
return false;
|
||||
int c = -1;
|
||||
final ReentrantLock putLock = this.putLock;
|
||||
putLock.lock();
|
||||
try {
|
||||
if (count.get() < capacity) {
|
||||
enqueue(bitmap);
|
||||
c = count.getAndIncrement();
|
||||
if (c + 1 < capacity)
|
||||
notFull.signal();
|
||||
}
|
||||
} finally {
|
||||
putLock.unlock();
|
||||
}
|
||||
if (c == 0)
|
||||
signalNotEmpty();
|
||||
return c >= 0;
|
||||
}
|
||||
|
||||
public LinkedBitmap take() throws InterruptedException {
|
||||
LinkedBitmap x;
|
||||
int c = -1;
|
||||
final AtomicInteger count = this.count;
|
||||
final ReentrantLock takeLock = this.takeLock;
|
||||
takeLock.lockInterruptibly();
|
||||
try {
|
||||
while (count.get() == 0) {
|
||||
notEmpty.await();
|
||||
}
|
||||
x = dequeue();
|
||||
c = count.getAndDecrement();
|
||||
if (c > 1)
|
||||
notEmpty.signal();
|
||||
} finally {
|
||||
takeLock.unlock();
|
||||
}
|
||||
if (c == capacity)
|
||||
signalNotFull();
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* insert element into the end of queue
|
||||
*
|
||||
* @param bitmap
|
||||
*/
|
||||
private void enqueue(LinkedBitmap bitmap) {
|
||||
if (head == null) {
|
||||
head = bitmap;
|
||||
tail = bitmap;
|
||||
bitmap.next = null;
|
||||
} else {
|
||||
tail.next = bitmap;
|
||||
bitmap.next = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get and remove the first element of the queue
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private LinkedBitmap dequeue() {
|
||||
LinkedBitmap p = head;
|
||||
if (p == null) {
|
||||
return null;
|
||||
} else {
|
||||
head = head.next;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals a waiting take. Called only from put/offer (which do not
|
||||
* otherwise ordinarily lock takeLock.)
|
||||
*/
|
||||
private void signalNotEmpty() {
|
||||
final ReentrantLock takeLock = this.takeLock;
|
||||
takeLock.lock();
|
||||
try {
|
||||
notEmpty.signal();
|
||||
} finally {
|
||||
takeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals a waiting put. Called only from take/poll.
|
||||
*/
|
||||
private void signalNotFull() {
|
||||
final ReentrantLock putLock = this.putLock;
|
||||
putLock.lock();
|
||||
try {
|
||||
notFull.signal();
|
||||
} finally {
|
||||
putLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* recycle the bitmaps one by one
|
||||
*/
|
||||
public void clear() {
|
||||
LinkedBitmap p = head;
|
||||
if (p == null) {
|
||||
return;
|
||||
}
|
||||
while (p != null) {
|
||||
if (p.bitmap != null) {
|
||||
p.bitmap.recycle();
|
||||
}
|
||||
p.bitmap = null;
|
||||
p = p.next;
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getCount() {
|
||||
return count.get();
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ dependencies {
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
implementation rootProject.ext.dependencies.arouter
|
||||
implementation rootProject.ext.dependencies.androidxrecyclerview
|
||||
implementation 'com.google.android.material:material:1.2.1'
|
||||
implementation rootProject.ext.dependencies.material
|
||||
implementation rootProject.ext.dependencies.flexbox
|
||||
annotationProcessor rootProject.ext.dependencies.aroutercompiler
|
||||
implementation rootProject.ext.dependencies.rxandroid
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.mogo.och.taxi.passenger.bean;
|
||||
|
||||
/**
|
||||
* Created by pangfan on 2021/8/19
|
||||
* 司机端准备好或者乘客已验证上车请求参数
|
||||
*/
|
||||
public class TaxiPassengerStartReqBean {
|
||||
|
||||
public String orderNo;
|
||||
public String sn;
|
||||
public TaxiPassengerStartReqBean.Result loc;
|
||||
|
||||
public static class Result {
|
||||
public Double lat;
|
||||
public Double lon;
|
||||
}
|
||||
|
||||
public TaxiPassengerStartReqBean(String sn, String orderNo, TaxiPassengerStartReqBean.Result point) {
|
||||
this.sn = sn;
|
||||
this.orderNo = orderNo;
|
||||
this.loc = point;
|
||||
}
|
||||
}
|
||||
@@ -22,4 +22,6 @@ public interface IOCHTaxiPassengerOrderStatusCallback {
|
||||
//当前路名字
|
||||
void onCurrentRoadName(String currentRoadName);
|
||||
|
||||
// 司机已确认开启自动驾驶环境
|
||||
void onDriverHasCheckedPilotCondition(boolean isBoarded);
|
||||
}
|
||||
|
||||
@@ -42,5 +42,21 @@ class TaxiPassengerConst {
|
||||
|
||||
//实时查询订单剩余时间 和 剩余里程 轮询间隔2s
|
||||
const val LOOP_CALCULATEROUTE_2S = 2 * 1000L
|
||||
|
||||
// 开始服务启动自动驾驶等待时间(埋点上传)
|
||||
const val LOOP_PERIOD_15S = 15 * 1000L
|
||||
|
||||
// 埋点key:接管后点击'自动驾驶'按钮启动
|
||||
const val EVENT_KEY_RESTART_AUTOPILOT = "event_key_och_taxi_restart_autopilot"
|
||||
// 埋点key:开始服务开启自动驾驶(成功/失败)
|
||||
const val EVENT_KEY_START_SERVICE = "event_key_och_taxi_start_service"
|
||||
const val EVENT_PARAM_SN = "sn"
|
||||
const val EVENT_PARAM_TIME = "time"
|
||||
const val EVENT_PARAM_START_NAME = "start_name"
|
||||
const val EVENT_PARAM_END_NAME = "end_name"
|
||||
const val EVENT_PARAM_ORDER_NUMBER = "order_num"
|
||||
const val EVENT_PARAM_START_RESULT = "start_autopilot" // true/false
|
||||
const val EVENT_PARAM_PLATE_NUM = "plate_number" // 车牌号
|
||||
const val EVENT_PARAM_ENV_ONLINE = "env_online" // 是否线上环境:true/false
|
||||
}
|
||||
}
|
||||
@@ -14,12 +14,13 @@ import com.elegant.network.utils.GsonUtil;
|
||||
import com.mogo.aicloud.services.socket.MogoAiCloudSocketManager;
|
||||
import com.mogo.cloud.commons.utils.CoordinateUtils;
|
||||
import com.mogo.commons.debug.DebugConfig;
|
||||
import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters;
|
||||
import com.mogo.eagle.core.data.autopilot.AutopilotStatusInfo;
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig;
|
||||
import com.mogo.eagle.core.data.map.MogoLatLng;
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotPlanningListener;
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
|
||||
import com.mogo.eagle.core.function.api.v2x.LimitingVelocityListener;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotPlanningListenerManager;
|
||||
import com.mogo.eagle.core.function.call.v2x.CallLimitingVelocityListenerManager;
|
||||
@@ -32,11 +33,13 @@ import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
|
||||
import com.mogo.map.navi.IMogoCarLocationChangedListener2;
|
||||
import com.mogo.module.common.MogoApisHandler;
|
||||
import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil;
|
||||
import com.mogo.och.common.module.utils.PinYinUtil;
|
||||
import com.mogo.och.taxi.passenger.bean.TaxiPassengerBaseRespBean;
|
||||
import com.mogo.och.taxi.passenger.bean.TaxiPassengerOrderQueryRemainingResp;
|
||||
import com.mogo.och.taxi.passenger.bean.TaxiPassengerOrderQueryRespBean;
|
||||
import com.mogo.och.taxi.passenger.bean.TaxiPassengerOrdersInServiceQueryRespBean;
|
||||
import com.mogo.och.taxi.passenger.bean.TaxiPassengerQueryOrderRouteResp;
|
||||
import com.mogo.och.taxi.passenger.bean.TaxiPassengerStartReqBean;
|
||||
import com.mogo.och.taxi.passenger.bean.TaxiPassengerScoreUpdateOrderReqBean;
|
||||
import com.mogo.och.taxi.passenger.callback.IOCHTaxiPassengerADASStatusCallback;
|
||||
import com.mogo.och.taxi.passenger.callback.IOCHTaxiPassengerAutopilotPlanningCallback;
|
||||
@@ -51,6 +54,7 @@ import com.mogo.och.taxi.passenger.constant.TaxiPassengerOrderStatusEnum;
|
||||
import com.mogo.och.taxi.passenger.network.TaxiPassengerServiceCallback;
|
||||
import com.mogo.och.taxi.passenger.network.TaxiPassengerServiceManager;
|
||||
import com.mogo.aicloud.services.socket.IMogoLifecycleListener;
|
||||
import com.mogo.och.taxi.passenger.utils.TaxiPassengerAnalyticsManager;
|
||||
import com.mogo.service.intent.IMogoIntentListener;
|
||||
import com.mogo.service.statusmanager.IMogoStatusChangedListener;
|
||||
import com.mogo.service.statusmanager.StatusDescriptor;
|
||||
@@ -70,7 +74,6 @@ import io.reactivex.plugins.RxJavaPlugins;
|
||||
import mogo.telematics.pad.MessagePad;
|
||||
import mogo_msg.MogoReportMsg;
|
||||
|
||||
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_TAXI;
|
||||
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_TAXI_P;
|
||||
|
||||
/**
|
||||
@@ -158,31 +161,31 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback
|
||||
public void accept(Throwable e) {
|
||||
if (e instanceof UndeliverableException) {
|
||||
e = e.getCause();
|
||||
CallerLogger.INSTANCE.d(M_TAXI + TAG, "UndeliverableException");
|
||||
CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "UndeliverableException");
|
||||
}
|
||||
if ((e instanceof IOException)) {//
|
||||
// fine, irrelevant network problem or API that throws on cancellation
|
||||
CallerLogger.INSTANCE.d(M_TAXI + TAG, "IOException");
|
||||
CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "IOException");
|
||||
return;
|
||||
}
|
||||
if (e instanceof InterruptedException) {
|
||||
// fine, some blocking code was interrupted by a dispose call
|
||||
CallerLogger.INSTANCE.d(M_TAXI + TAG, "InterruptedException");
|
||||
CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "InterruptedException");
|
||||
return;
|
||||
}
|
||||
if ((e instanceof NullPointerException) || (e instanceof IllegalArgumentException)) {
|
||||
// that's likely a bug in the application
|
||||
CallerLogger.INSTANCE.d(M_TAXI + TAG, "NullPointerException or IllegalArgumentException");
|
||||
CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "NullPointerException or IllegalArgumentException");
|
||||
Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
|
||||
return;
|
||||
}
|
||||
if (e instanceof IllegalStateException) {
|
||||
// that's a bug in RxJava or in a custom operator
|
||||
CallerLogger.INSTANCE.d(M_TAXI + TAG, "IllegalStateException");
|
||||
CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "IllegalStateException");
|
||||
Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
|
||||
return;
|
||||
}
|
||||
CallerLogger.INSTANCE.d(M_TAXI + TAG,"Undeliverable exception");
|
||||
CallerLogger.INSTANCE.d(M_TAXI_P + TAG,"Undeliverable exception");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -505,11 +508,11 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback
|
||||
if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {
|
||||
if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotRunning();
|
||||
if (mCurrentOCHOrder != null
|
||||
&& getCurOrderStatus() == TaxiPassengerOrderStatusEnum.ArriveAtStart
|
||||
&& getCurOrderStatus() == TaxiPassengerOrderStatusEnum.UserArriveAtStart
|
||||
&& state != mPrevAPStatus) {
|
||||
// 当高频返回autopilot 2时,不重复调用订单状态变更
|
||||
mPrevAPStatus = state; // 每个状态单独赋值,解决无订单时已经是2的状态导致的新订单来时无法进入此逻辑更新状态
|
||||
// updateOCHOrderStatus(OrderStatusEnum.OnTheWayToEndStation);
|
||||
startServicePilotDone();
|
||||
}
|
||||
} else if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE) {
|
||||
mPrevAPStatus = state;
|
||||
@@ -597,9 +600,9 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback
|
||||
*/
|
||||
public void startOrStopRouteAndWipe(boolean isStart){
|
||||
if (isStart){
|
||||
TaxiPassengerModelLoopManager.getInstance().startOrStopRouteAndWipe();
|
||||
TaxiPassengerModelLoopManager.getInstance().startRouteAndWipe();
|
||||
}else {
|
||||
TaxiPassengerModelLoopManager.getInstance().stopOrStopRouteAndWipe();
|
||||
TaxiPassengerModelLoopManager.getInstance().stopRouteAndWipe();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -781,6 +784,102 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback
|
||||
});
|
||||
}
|
||||
|
||||
public void loopQueryPilotStatus(){
|
||||
if (mCurrentOCHOrder == null) return;
|
||||
TaxiPassengerServiceManager.getInstance().queryPilotStatus(mContext, mCurrentOCHOrder.orderNo,
|
||||
new TaxiPassengerServiceCallback<TaxiPassengerBaseRespBean>() {
|
||||
@Override
|
||||
public void onSuccess(TaxiPassengerBaseRespBean data) {
|
||||
if (data != null && data.code == 0 && data.data.equals(true)) {
|
||||
updateAutopilotStatus(true);
|
||||
startOrStopReadyToAutopilotoop(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(int code, String msg) {
|
||||
updateAutopilotStatus(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void updateAutopilotStatus(boolean isBoarded){
|
||||
if (mOrderStatusCallbackMap.size() > 0) {
|
||||
for (IOCHTaxiPassengerOrderStatusCallback callback :mOrderStatusCallbackMap.values()){
|
||||
callback.onDriverHasCheckedPilotCondition(isBoarded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void startDriverReadyToAutopilotLoop(){
|
||||
if (NetworkUtils.isConnected(mContext)) {
|
||||
startOrStopReadyToAutopilotoop(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void startOrStopReadyToAutopilotoop(boolean isStart) {
|
||||
if (isStart){
|
||||
TaxiPassengerModelLoopManager.getInstance().startReadyToAutopilot();
|
||||
}else {
|
||||
TaxiPassengerModelLoopManager.getInstance().stopReadyToAutopilot();
|
||||
}
|
||||
}
|
||||
|
||||
public void startServicePilotDone(){
|
||||
if (mCurrentOCHOrder == null) return;
|
||||
TaxiPassengerStartReqBean.Result result = new TaxiPassengerStartReqBean.Result();
|
||||
result.lat = mLatitude;
|
||||
result.lon = mLongitude;
|
||||
TaxiPassengerServiceManager.getInstance().startServicePilotDone(mContext,
|
||||
mCurrentOCHOrder.orderNo, result,
|
||||
new TaxiPassengerServiceCallback<TaxiPassengerBaseRespBean>(){
|
||||
|
||||
@Override
|
||||
public void onSuccess(TaxiPassengerBaseRespBean data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(int code, String msg) {
|
||||
ToastUtils.showShort(msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void startAutopilot() {
|
||||
if (!checkCurrentOCHOrder()) {
|
||||
CallerLogger.INSTANCE.e(M_TAXI_P + TAG, "no order or order is empty.");
|
||||
ToastUtils.showShort("当前订单不存在或异常!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCurrentOCHOrder.orderStatus != TaxiPassengerOrderStatusEnum.UserArriveAtStart.getCode()) {
|
||||
ToastUtils.showShort("当前订单状态异常!");
|
||||
return;
|
||||
}
|
||||
|
||||
double startWgsLon = mCurrentOCHOrder.startSitePoint.get(0);
|
||||
double startWgsLat = mCurrentOCHOrder.startSitePoint.get(1);
|
||||
double endWgsLon = mCurrentOCHOrder.endSitePoint.get(0);
|
||||
double endWgsLat = mCurrentOCHOrder.endSitePoint.get(1);
|
||||
|
||||
AutopilotControlParameters parameters = new AutopilotControlParameters();
|
||||
parameters.vehicleType = mCurrentOCHOrder.businessType;
|
||||
parameters.startName = PinYinUtil.getPinYinHeadChar(mCurrentOCHOrder.startSiteAddr); // 起点名称拼音首字母大写:科学城B区2号门(KXCBQ2HM)
|
||||
parameters.endName = PinYinUtil.getPinYinHeadChar(mCurrentOCHOrder.endSiteAddr); // 终点名称拼音首字母大写:科学城C区三号门(KXCCQSHM)
|
||||
parameters.startLatLon = new AutopilotControlParameters.AutoPilotLonLat(startWgsLat, startWgsLon);
|
||||
parameters.endLatLon = new AutopilotControlParameters.AutoPilotLonLat(endWgsLat, endWgsLon);
|
||||
CallerAutoPilotManager.INSTANCE.startAutoPilot(parameters);
|
||||
CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "start autopilot with parameter: %s"
|
||||
, GsonUtil.jsonFromObject(parameters)
|
||||
+ " ,startSiteName=" + mCurrentOCHOrder.startSiteAddr
|
||||
+ " ,endSiteName=" + mCurrentOCHOrder.endSiteAddr);
|
||||
|
||||
TaxiPassengerAnalyticsManager.getInstance().triggerStartAutopilotEvent(false, false,
|
||||
mCurrentOCHOrder.startSiteAddr, mCurrentOCHOrder.endSiteAddr, mCurrentOCHOrder.orderNo);
|
||||
}
|
||||
|
||||
|
||||
private void runOnUIThread(Runnable executor) {
|
||||
if (executor == null) {
|
||||
return;
|
||||
|
||||
@@ -32,12 +32,34 @@ public class TaxiPassengerModelLoopManager {
|
||||
private Disposable mInAndWaitServiceDisposable; //进行中、待服务订单列表轮询
|
||||
private Disposable mQueryOrderRemainingDisposable; //心跳轮询
|
||||
private Disposable mRouteWipeDisposable; //轨迹擦除
|
||||
private Disposable mReadyToAutopilotDisposable; //轨迹擦除
|
||||
|
||||
public void startOrStopRouteAndWipe() {
|
||||
public void startReadyToAutopilot() {
|
||||
if (mReadyToAutopilotDisposable != null && !mReadyToAutopilotDisposable.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
CallerLogger.INSTANCE.i(M_TAXI_P + TAG, "startReadyToAutopilot()");
|
||||
mReadyToAutopilotDisposable = Observable.interval(TaxiPassengerConst.LOOP_DELAY,
|
||||
TaxiPassengerConst.LOOP_PERIOD_1S, TimeUnit.MILLISECONDS)
|
||||
.map((aLong -> aLong + 1))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(aLong -> TaxiPassengerModel.getInstance().loopQueryPilotStatus());
|
||||
}
|
||||
|
||||
public void stopReadyToAutopilot() {
|
||||
if (mReadyToAutopilotDisposable != null) {
|
||||
CallerLogger.INSTANCE.i(M_TAXI_P + TAG, "stopReadyToAutopilot()");
|
||||
mReadyToAutopilotDisposable.dispose();
|
||||
mReadyToAutopilotDisposable = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void startRouteAndWipe() {
|
||||
if (mRouteWipeDisposable != null && !mRouteWipeDisposable.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
CallerLogger.INSTANCE.i(M_TAXI_P + TAG, "startOrStopRouteWipe()");
|
||||
CallerLogger.INSTANCE.i(M_TAXI_P + TAG, "startRouteAndWipe()");
|
||||
mRouteWipeDisposable = Observable.interval(TaxiPassengerConst.LOOP_DELAY,
|
||||
TaxiPassengerConst.LOOP_PERIOD_1S, TimeUnit.MILLISECONDS)
|
||||
.map((aLong -> aLong + 1))
|
||||
@@ -46,9 +68,9 @@ public class TaxiPassengerModelLoopManager {
|
||||
.subscribe(aLong -> TaxiPassengerModel.getInstance().loopRouteAndWipe());
|
||||
}
|
||||
|
||||
public void stopOrStopRouteAndWipe() {
|
||||
public void stopRouteAndWipe() {
|
||||
if (mRouteWipeDisposable != null) {
|
||||
CallerLogger.INSTANCE.i(M_TAXI_P + TAG, "stopOrStopRouteWipe()");
|
||||
CallerLogger.INSTANCE.i(M_TAXI_P + TAG, "stopRouteAndWipe()");
|
||||
mRouteWipeDisposable.dispose();
|
||||
mRouteWipeDisposable = null;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.mogo.och.taxi.passenger.bean.TaxiPassengerOrderQueryRespBean;
|
||||
import com.mogo.och.taxi.passenger.bean.TaxiPassengerOrdersInServiceQueryRespBean;
|
||||
import com.mogo.och.taxi.passenger.bean.TaxiPassengerQueryOrderRouteResp;
|
||||
import com.mogo.och.taxi.passenger.bean.TaxiPassengerScoreUpdateOrderReqBean;
|
||||
import com.mogo.och.taxi.passenger.bean.TaxiPassengerStartReqBean;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import retrofit2.http.Body;
|
||||
@@ -101,4 +102,27 @@ interface TaxiPassengerServiceApi {
|
||||
@GET( "/autopilot-car-hailing/evaluation/label/driver/taxi/listByStar" )
|
||||
Observable<TaxiPassengerAllStarWorld> getWorldByStar(@Header ("appId") String appId, @Header("ticket") String ticket,@Query("star") String star);
|
||||
|
||||
/**
|
||||
* 查询司机是否已确认可开启自动驾驶
|
||||
* @param appId
|
||||
* @param ticket
|
||||
* @param orderNo
|
||||
* @return
|
||||
*/
|
||||
@Headers( {"Content-type:application/json;charset=UTF-8"} )
|
||||
@GET( "/autopilot-car-hailing/cab/flow/v1/driver/taxi/pilot/status" )
|
||||
Observable<TaxiPassengerBaseRespBean> queryPilotStatus(@Header ("appId") String appId
|
||||
, @Header("ticket") String ticket,@Query("orderNo") String orderNo);
|
||||
|
||||
/**
|
||||
* 乘客屏启动自动驾驶成功
|
||||
* @param appId
|
||||
* @param ticket
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
@Headers( {"Content-type:application/json;charset=UTF-8"} )
|
||||
@POST( "/autopilot-car-hailing/cab/flow/v1/driver/taxi/passenger/startServicePilot" )
|
||||
Observable<TaxiPassengerBaseRespBean> startServicePilotDone(@Header ("appId") String appId
|
||||
, @Header("ticket") String ticket,@Body TaxiPassengerStartReqBean data);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.mogo.och.taxi.passenger.bean.TaxiPassengerOrderQueryRespBean;
|
||||
import com.mogo.och.taxi.passenger.bean.TaxiPassengerOrdersInServiceQueryRespBean;
|
||||
import com.mogo.och.taxi.passenger.bean.TaxiPassengerQueryOrderRouteResp;
|
||||
import com.mogo.och.taxi.passenger.bean.TaxiPassengerScoreUpdateOrderReqBean;
|
||||
import com.mogo.och.taxi.passenger.bean.TaxiPassengerStartReqBean;
|
||||
import com.mogo.och.taxi.passenger.constant.TaxiPassengerConst;
|
||||
import com.mogo.commons.debug.DebugConfig;
|
||||
|
||||
@@ -176,7 +177,29 @@ public class TaxiPassengerServiceManager {
|
||||
,MoGoAiCloudClientConfig.getInstance().getToken())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(getSubscribeImpl(context, callback, "checkPhoneAndUpdateOrderStatus"));
|
||||
.subscribe(getSubscribeImpl(context, callback, "arrivedAndScore"));
|
||||
}
|
||||
|
||||
public void queryPilotStatus(Context context, String orderNo
|
||||
,TaxiPassengerServiceCallback<TaxiPassengerBaseRespBean> callback){
|
||||
mOCHTaxiServiceApi.queryPilotStatus(
|
||||
MoGoAiCloudClientConfig.getInstance().getServiceAppId()
|
||||
,MoGoAiCloudClientConfig.getInstance().getToken()
|
||||
,orderNo)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(getSubscribeImpl(context, callback, "queryPilotStatus"));
|
||||
}
|
||||
|
||||
public void startServicePilotDone(Context context,String orderNo,TaxiPassengerStartReqBean.Result loc
|
||||
,TaxiPassengerServiceCallback<TaxiPassengerBaseRespBean> callback){
|
||||
mOCHTaxiServiceApi.startServicePilotDone(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
|
||||
,MoGoAiCloudClientConfig.getInstance().getToken()
|
||||
,new TaxiPassengerStartReqBean(MoGoAiCloudClientConfig.getInstance().getSn()
|
||||
,orderNo,loc))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(getSubscribeImpl(context,callback,"startServicePilotDone"));
|
||||
}
|
||||
public void getWorldByStar(Context context,String start,TaxiPassengerServiceCallback<TaxiPassengerAllStarWorld> callback){
|
||||
mOCHTaxiServiceApi.getWorldByStar(
|
||||
|
||||
@@ -142,19 +142,28 @@ public class BaseTaxiPassengerPresenter extends Presenter<TaxiPassengerBaseFragm
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDriverHasCheckedPilotCondition(boolean isBoarded) {
|
||||
CallerLogger.INSTANCE.d(M_TAXI_P+TAG,"isBoarded = "+isBoarded);
|
||||
runOnUIThread(() -> {
|
||||
mView.updateStartAutopilotBtnStatus(isBoarded);
|
||||
});
|
||||
}
|
||||
|
||||
private void updateOrderView(TaxiPassengerOrderQueryRespBean.Result order) {
|
||||
CallerLogger.INSTANCE.d(M_TAXI_P+TAG,"updateOrderView = "+order.orderStatus);
|
||||
// 70 取消订单
|
||||
if (TaxiPassengerOrderStatusEnum.Cancel.getCode() == order.orderStatus){
|
||||
runOnUIThread(() -> {
|
||||
mView.showOrHideServingOrderFragment(false);
|
||||
// mView.showOrHideStartAutopilotView(false);
|
||||
mView.showOrHideStartAutopilotView(false,false);
|
||||
mView.showOrHidePressengerCheckPager(false, "",
|
||||
"", "", "", "");
|
||||
mView.showOrHideArrivedEndLayout(false,"","");
|
||||
});
|
||||
TaxiPassengerModel.getInstance().recoverNaviInfo();
|
||||
TaxiPassengerGeocodeSearchModel.getInstance(getContext()).destroyGeocodeSearch();
|
||||
TaxiPassengerModel.getInstance().startOrStopReadyToAutopilotoop(false);
|
||||
return;
|
||||
}
|
||||
// 20 司机到达上车点
|
||||
@@ -166,13 +175,23 @@ public class BaseTaxiPassengerPresenter extends Presenter<TaxiPassengerBaseFragm
|
||||
return;
|
||||
}
|
||||
// TODO: 2022/6/10 若乘客端确认已经上车,则显示开始行程按钮 并且不可点击 暗
|
||||
// TODO: 2022/6/10 若司机端已经确认,则显示开始行程按钮 并且可点击
|
||||
//TODO: 2022/6/10 若订单取消或者隐藏则隐藏开始行程按钮
|
||||
// TODO: 2022/6/10 乘客已上车 需要开启轮询司机确认可以开启自动驾驶的接口
|
||||
// TODO: 2022/6/10 若司机端已经确认,则显示开始行程按钮 并且可点击,第二步的轮询停止
|
||||
//TODO: 2022/6/10 若订单取消或者隐藏则关掉开始行程界面,轮询也要取消
|
||||
if (TaxiPassengerOrderStatusEnum.UserArriveAtStart.getCode() == order.orderStatus){
|
||||
// mView.showOrHideStartAutopilotView(true);
|
||||
runOnUIThread(() ->{
|
||||
CallerLogger.INSTANCE.d(M_TAXI_P+TAG,"UserArriveAtStart");
|
||||
mView.showOrHideStartAutopilotView(true,false);
|
||||
});
|
||||
//开启轮询司机是否已准备好开启自动驾驶的环境
|
||||
TaxiPassengerModel.getInstance().startDriverReadyToAutopilotLoop();
|
||||
}
|
||||
if (TaxiPassengerOrderStatusEnum.OnTheWayToEnd.getCode() == order.orderStatus){
|
||||
// mView.showOrHideStartAutopilotView(false);
|
||||
runOnUIThread(() ->{
|
||||
mView.showOrHideServingOrderFragment(true);
|
||||
mView.showOrHideStartAutopilotView(false,false);
|
||||
});
|
||||
TaxiPassengerModel.getInstance().startOrStopReadyToAutopilotoop(false);
|
||||
}
|
||||
// 30 用户到达上车点 并通过了手机号后四位验证
|
||||
// 40 服务中
|
||||
@@ -182,7 +201,6 @@ public class BaseTaxiPassengerPresenter extends Presenter<TaxiPassengerBaseFragm
|
||||
mView.showOrHideArrivedEndLayout(false,"","");
|
||||
mView.showOrHidePressengerCheckPager(false, "",
|
||||
"", "", "", "");
|
||||
mView.showOrHideServingOrderFragment(true);
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -221,4 +239,11 @@ public class BaseTaxiPassengerPresenter extends Presenter<TaxiPassengerBaseFragm
|
||||
TaxiPassengerModel.getInstance().arrivedAndScore(taxiPassengerScoreUpdateOrderReqBean,aBoolean -> mView.showArrivedEndLayout2Thank(aBoolean));
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启自动驾驶
|
||||
*/
|
||||
public void startAutopilot(){
|
||||
TaxiPassengerModel.getInstance().startAutopilot();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -120,6 +120,11 @@ public class TaxiPassengerServingOrderPresenter extends Presenter<TaxiPassengerS
|
||||
runOnUIThread(() -> mView.onCurrentRoadName(currentRoadName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDriverHasCheckedPilotCondition(boolean isBoarded) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVRModeChanged(boolean isVRMode) {
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.mogo.och.taxi.passenger.ui;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.View;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
@@ -154,6 +156,7 @@ public class TaxiPassengerBaseFragment extends MvpFragment<TaxiPassengerBaseFrag
|
||||
super.onResume();
|
||||
// mPresenter.startOrStopOrderLoop();
|
||||
// showOrHideServingOrderFragment(true);
|
||||
// showOrHideStartAutopilotView(true,true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,29 +177,21 @@ public class TaxiPassengerBaseFragment extends MvpFragment<TaxiPassengerBaseFrag
|
||||
private int mPrevAPStatus = -1;
|
||||
public void onAutopilotStatusChanged(int status) {
|
||||
getActivity().runOnUiThread(() -> {
|
||||
// if (isStarting && IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING != status) {
|
||||
// // 1. 主动开启自动驾驶中,不为2(为0、1)则继续loading
|
||||
// return;
|
||||
// }
|
||||
// if (isStarting && IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING == status
|
||||
// && mPrevAPStatus != status) {
|
||||
// // 2. 主动开启自动驾驶中,为2则停止loading,并isStarting = false
|
||||
// startAutopilotDone(true);
|
||||
// return;
|
||||
// }
|
||||
if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING != status) {
|
||||
// 1. 主动开启自动驾驶中,不为2(为0、1)则继续loading
|
||||
return;
|
||||
}
|
||||
if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING == status
|
||||
&& mPrevAPStatus != status) {
|
||||
// 2. 主动开启自动驾驶中,为2则停止loading,并isStarting = false
|
||||
if ( mStartAutopilotView != null && mStartAutopilotView.get() != null){
|
||||
mStartAutopilotView.get().startOrStopLoadingAnim(false);
|
||||
}
|
||||
}
|
||||
// 3. 其他过程直接更新
|
||||
if (mPrevAPStatus != status){
|
||||
autopilotStatusAnimchanged(status);
|
||||
}
|
||||
// if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING == mPrevAPStatus) {
|
||||
// if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE == status) {
|
||||
// // 2->1
|
||||
//// AIAssist.getInstance(getContext()).speakTTSVoice("已进入人工驾驶模式");
|
||||
// } else if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE == status) {
|
||||
// // 2->0
|
||||
//// AIAssist.getInstance(getContext()).speakTTSVoice("自动驾驶已停止,请人工接管");
|
||||
// }
|
||||
// }
|
||||
mPrevAPStatus = status;
|
||||
});
|
||||
}
|
||||
@@ -280,8 +275,6 @@ public class TaxiPassengerBaseFragment extends MvpFragment<TaxiPassengerBaseFrag
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 显示或者隐藏乘客可点击自动驾驶页面
|
||||
* 乘客验证成功,页面显示,按钮置于不可点击
|
||||
@@ -293,10 +286,10 @@ public class TaxiPassengerBaseFragment extends MvpFragment<TaxiPassengerBaseFrag
|
||||
if (isShow){
|
||||
if (mStartAutopilotView == null || mStartAutopilotView.get() == null){
|
||||
mStartAutopilotView = new WeakReference<>(new TaxiPassengerStartAutopilotView(getContext()));
|
||||
mStartAutopilotView.get().setOnClickStartAutopilotBtnCallback(this);
|
||||
}
|
||||
OverlayViewUtils.showOverlayView(getActivity(),mStartAutopilotView.get());
|
||||
mStartAutopilotView.get().setOnClickStartAutopilotBtnCallback(this);
|
||||
mStartAutopilotView.get().updateStartAutopilotBtnStatus(isClickable);
|
||||
updateStartAutopilotBtnStatus(isClickable);
|
||||
}else {
|
||||
if (mStartAutopilotView == null || mStartAutopilotView.get() == null){
|
||||
return;
|
||||
@@ -306,6 +299,13 @@ public class TaxiPassengerBaseFragment extends MvpFragment<TaxiPassengerBaseFrag
|
||||
}
|
||||
}
|
||||
|
||||
public void updateStartAutopilotBtnStatus(boolean isClickable){
|
||||
if (mStartAutopilotView == null || mStartAutopilotView.get() == null){
|
||||
return;
|
||||
}
|
||||
mStartAutopilotView.get().updateStartAutopilotBtnStatus(isClickable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示或者隐藏到达乘客站点的洁面
|
||||
* ① 取消订单 可有可无
|
||||
@@ -387,6 +387,7 @@ public class TaxiPassengerBaseFragment extends MvpFragment<TaxiPassengerBaseFrag
|
||||
|
||||
@Override
|
||||
public void onClickCallback() {
|
||||
//todo 点击开始自动驾驶按钮
|
||||
|
||||
mPresenter.startAutopilot();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
package com.mogo.och.taxi.passenger.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.graphics.drawable.AnimationDrawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.elegant.utils.UiThreadHandler;
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils;
|
||||
import com.mogo.och.common.module.wigets.OCHBorderShadowLayout;
|
||||
import com.mogo.och.common.module.wigets.sfv.FrameFinishCallback;
|
||||
import com.mogo.och.common.module.wigets.sfv.FrameSurfaceView;
|
||||
import com.mogo.och.taxi.passenger.R;
|
||||
import com.mogo.och.taxi.passenger.callback.ITPClickStartAutopilotCallback;
|
||||
import com.mogo.och.taxi.passenger.model.TaxiPassengerModel;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
@@ -19,25 +24,136 @@ import com.mogo.och.taxi.passenger.callback.ITPClickStartAutopilotCallback;
|
||||
public class TaxiPassengerStartAutopilotView extends RelativeLayout implements View.OnClickListener {
|
||||
|
||||
private TextView mStartAutopilotBtn;
|
||||
// private ImageView mAutopilotStartingImage;
|
||||
private ITPClickStartAutopilotCallback mClickCallback;
|
||||
public boolean isStarting = false;
|
||||
private AnimationDrawable mAnimationBtnDrawable;
|
||||
private AnimationDrawable mAnimationStartingDrawable;
|
||||
private static final long TIMER_START_AUTOPILOT_INTERVAL = 10 * 1000L;
|
||||
private Context mContext;
|
||||
private View view;
|
||||
private FrameSurfaceView svCarStartingFrame;
|
||||
private FrameSurfaceView svBtnBgFrame;
|
||||
private Integer[] btnBgAnimIds = new Integer[]{
|
||||
R.drawable.image_00000,
|
||||
R.drawable.image_00001,
|
||||
R.drawable.image_00002,
|
||||
R.drawable.image_00003,
|
||||
R.drawable.image_00004,
|
||||
R.drawable.image_00005,
|
||||
R.drawable.image_00006,
|
||||
R.drawable.image_00007,
|
||||
R.drawable.image_00008,
|
||||
R.drawable.image_00009,
|
||||
R.drawable.image_00010,
|
||||
R.drawable.image_00011,
|
||||
R.drawable.image_00012,
|
||||
R.drawable.image_00013,
|
||||
R.drawable.image_00014,
|
||||
R.drawable.image_00015,
|
||||
R.drawable.image_00016,
|
||||
R.drawable.image_00017,
|
||||
R.drawable.image_00018,
|
||||
R.drawable.image_00019,
|
||||
R.drawable.image_00020,
|
||||
R.drawable.image_00021,
|
||||
R.drawable.image_00022,
|
||||
R.drawable.image_00023,
|
||||
R.drawable.image_00024,
|
||||
R.drawable.image_00025,
|
||||
R.drawable.image_00026,
|
||||
R.drawable.image_00027,
|
||||
R.drawable.image_00028,
|
||||
R.drawable.image_00029,
|
||||
R.drawable.image_00030,
|
||||
R.drawable.image_00031,
|
||||
R.drawable.image_00032,
|
||||
R.drawable.image_00033,
|
||||
R.drawable.image_00034,
|
||||
R.drawable.image_00035,
|
||||
R.drawable.image_00036,
|
||||
R.drawable.image_00037,
|
||||
R.drawable.image_00038,
|
||||
R.drawable.image_00039,
|
||||
R.drawable.image_00040,
|
||||
R.drawable.image_00041,
|
||||
R.drawable.image_00042,
|
||||
R.drawable.image_00043,
|
||||
R.drawable.image_00044,
|
||||
R.drawable.image_00045,
|
||||
R.drawable.image_00046,
|
||||
R.drawable.image_00047,
|
||||
R.drawable.image_00048,
|
||||
R.drawable.image_00049,
|
||||
R.drawable.image_00050,
|
||||
R.drawable.image_00051,
|
||||
R.drawable.image_00052,
|
||||
R.drawable.image_00053,
|
||||
R.drawable.image_00054,
|
||||
R.drawable.image_00055,
|
||||
R.drawable.image_00056,
|
||||
R.drawable.image_00057,
|
||||
R.drawable.image_00058,
|
||||
R.drawable.image_00059,
|
||||
R.drawable.image_00060,
|
||||
R.drawable.image_00061,
|
||||
R.drawable.image_00062,
|
||||
R.drawable.image_00063,
|
||||
R.drawable.image_00064,
|
||||
R.drawable.image_00065,
|
||||
R.drawable.image_00066,
|
||||
R.drawable.image_00067,
|
||||
R.drawable.image_00068,
|
||||
R.drawable.image_00069,
|
||||
R.drawable.image_00070,
|
||||
R.drawable.image_00071,
|
||||
R.drawable.image_00072,
|
||||
R.drawable.image_00073,
|
||||
R.drawable.image_00074
|
||||
};
|
||||
private Integer[] startingAnimIds = new Integer[]{
|
||||
R.drawable.light_00000,
|
||||
R.drawable.light_00001,
|
||||
R.drawable.light_00002,
|
||||
R.drawable.light_00003,
|
||||
R.drawable.light_00004,
|
||||
R.drawable.light_00005,
|
||||
R.drawable.light_00006,
|
||||
R.drawable.light_00007,
|
||||
R.drawable.light_00008,
|
||||
R.drawable.light_00009,
|
||||
R.drawable.light_00010,
|
||||
R.drawable.light_00011,
|
||||
R.drawable.light_00012,
|
||||
R.drawable.light_00013
|
||||
};
|
||||
|
||||
public TaxiPassengerStartAutopilotView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public TaxiPassengerStartAutopilotView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public TaxiPassengerStartAutopilotView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mContext = context;
|
||||
initView(context);
|
||||
}
|
||||
|
||||
private void initView(Context context) {
|
||||
LayoutInflater.from(context).inflate(R.layout.taxi_p_start_autopilot_view, this, true);
|
||||
mStartAutopilotBtn = findViewById(R.id.taxi_p_start_autopilot);
|
||||
view = LayoutInflater.from(context).inflate(R.layout.taxi_p_start_autopilot_view, this,true);
|
||||
mStartAutopilotBtn = view.findViewById(R.id.taxi_p_start_autopilot);
|
||||
mStartAutopilotBtn.setOnClickListener(this);
|
||||
// mAutopilotStartingImage = view.findViewById(R.id.taxi_p_autopilot_starting);
|
||||
svCarStartingFrame = view.findViewById(R.id.taxi_p_autopilot_starting);
|
||||
svCarStartingFrame.setBitmapIds(Arrays.asList(startingAnimIds));
|
||||
svCarStartingFrame.setDuration(1680);
|
||||
|
||||
svBtnBgFrame = view.findViewById(R.id.taxi_p_start_autopilot_btn_sfv);
|
||||
svBtnBgFrame.setBitmapIds(Arrays.asList(btnBgAnimIds));
|
||||
svBtnBgFrame.setDuration(7500);
|
||||
|
||||
svCarStartingFrame.setOnLongClickListener(new OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
TaxiPassengerModel.getInstance().startServicePilotDone();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setOnClickStartAutopilotBtnCallback(ITPClickStartAutopilotCallback clickCallback){
|
||||
@@ -47,11 +163,139 @@ public class TaxiPassengerStartAutopilotView extends RelativeLayout implements V
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.getId() == R.id.taxi_p_start_autopilot){
|
||||
ToastUtils.showShort("等待接口。。。。");
|
||||
//开启动画和自动驾驶
|
||||
if (!(boolean)mStartAutopilotBtn.getTag()){
|
||||
ToastUtils.showLong(R.string.taxi_p_start_autopilot_un_click_tip);
|
||||
return;
|
||||
}
|
||||
if (!isStarting){
|
||||
startOrStopLoadingAnim(true);
|
||||
if (mClickCallback != null) mClickCallback.onClickCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateStartAutopilotBtnStatus(boolean isClickable){
|
||||
mStartAutopilotBtn.setClickable(isClickable);
|
||||
|
||||
svCarStartingFrame.setBackgroundResource(R.drawable.light_00000);
|
||||
|
||||
if (mStartAutopilotBtn == null) return;
|
||||
|
||||
mStartAutopilotBtn.setTag(isClickable);
|
||||
mStartAutopilotBtn.setText(
|
||||
mContext.getResources().getString(R.string.taxi_p_start_autopilot_txt));
|
||||
|
||||
if (isClickable){ //高亮可点击状态下UI
|
||||
mStartAutopilotBtn.setTextColor(
|
||||
mContext.getResources().getColor(R.color.taxi_p_start_autopilot_txt_color));
|
||||
mStartAutopilotBtn.setBackground(null);
|
||||
startAutopilotBgAnimatorDrawable(true);
|
||||
}else {// 置灰色可点击状态下 UI
|
||||
mStartAutopilotBtn.setBackground(
|
||||
mContext.getResources().getDrawable(R.drawable.taxi_p_start_autopilot_txt_btn_bg));
|
||||
mStartAutopilotBtn.setTextColor(
|
||||
mContext.getResources().getColor(R.color.taxi_p_start_autopilot_txt_un_color));
|
||||
startAutopilotBgAnimatorDrawable(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void startAutopilotBgAnimatorDrawable(boolean isStart){
|
||||
if (isStart){
|
||||
svBtnBgFrame.setRepeatTimes(-1);
|
||||
svBtnBgFrame.setFrameFinishCallback(new FrameFinishCallback() {
|
||||
@Override
|
||||
public void onFinishCallback() {
|
||||
// svBtnBgFrame.setBackgroundResource(R.drawable.image_00000);
|
||||
}
|
||||
});
|
||||
svBtnBgFrame.start();
|
||||
}else {
|
||||
svBtnBgFrame.reset();
|
||||
svBtnBgFrame.setBackground(null);
|
||||
}
|
||||
// if (isStart){
|
||||
// if (mAnimationBtnDrawable == null) {
|
||||
// mAnimationBtnDrawable = (AnimationDrawable) mStartAutopilotBtn.getBackground();
|
||||
// }
|
||||
// if (mAnimationBtnDrawable.isRunning()) {
|
||||
// return;
|
||||
// }
|
||||
// mAnimationBtnDrawable.selectDrawable(0);
|
||||
// mAnimationBtnDrawable.start();
|
||||
// }else {
|
||||
// if (mAnimationBtnDrawable != null) {
|
||||
// mAnimationBtnDrawable.stop();
|
||||
// }
|
||||
// mAnimationBtnDrawable = null;
|
||||
// }
|
||||
}
|
||||
|
||||
private void startingCarBgAnimatorDrawable(boolean isStart){
|
||||
if (isStart){
|
||||
svCarStartingFrame.setRepeatTimes(-1);
|
||||
svCarStartingFrame.setFrameFinishCallback(new FrameFinishCallback() {
|
||||
@Override
|
||||
public void onFinishCallback() {
|
||||
}
|
||||
});
|
||||
svCarStartingFrame.setBackground(null);
|
||||
svCarStartingFrame.start();
|
||||
}else {
|
||||
svCarStartingFrame.reset();
|
||||
svCarStartingFrame.setBackgroundResource(R.drawable.light_00000);
|
||||
}
|
||||
|
||||
// if (isStart){
|
||||
// if (mAnimationStartingDrawable == null) {
|
||||
// mAnimationStartingDrawable = (AnimationDrawable) mAutopilotStartingImage.getBackground();
|
||||
// }
|
||||
// if (mAnimationStartingDrawable.isRunning()) {
|
||||
// return;
|
||||
// }
|
||||
// mAnimationStartingDrawable.selectDrawable(0);
|
||||
// mAnimationStartingDrawable.start();
|
||||
// }else {
|
||||
// if (mAnimationStartingDrawable != null) {
|
||||
// mAnimationStartingDrawable.selectDrawable(0);
|
||||
// mAnimationStartingDrawable.stop();
|
||||
// }
|
||||
// mAnimationStartingDrawable = null;
|
||||
// }
|
||||
}
|
||||
|
||||
public void startOrStopLoadingAnim(boolean start) {
|
||||
startingCarBgAnimatorDrawable(start);
|
||||
if (start) {
|
||||
isStarting = true;
|
||||
|
||||
mStartAutopilotBtn.setText(getResources().getString(R.string.taxi_p_start_autopilot_loading));
|
||||
mStartAutopilotBtn.setTextColor(getResources().getColor(R.color.taxi_p_start_autopilot_txt_color));
|
||||
|
||||
startingAutopilotCountDown();
|
||||
} else {
|
||||
isStarting = false;
|
||||
updateStartAutopilotBtnStatus(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void onAutopilotStatusSuccess(){
|
||||
startOrStopLoadingAnim(false);
|
||||
}
|
||||
|
||||
public void onAutopilotStatusFailure(){
|
||||
startOrStopLoadingAnim(false);
|
||||
}
|
||||
|
||||
private void startingAutopilotCountDown() {
|
||||
UiThreadHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() { //未启动成功10s后做处理
|
||||
if (isStarting){ //判断动画是否在进行
|
||||
ToastUtils.showLong(R.string.taxi_p_start_autopilot_fail_10s_tip);
|
||||
startOrStopLoadingAnim(false);
|
||||
}
|
||||
|
||||
}
|
||||
},TIMER_START_AUTOPILOT_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,10 +49,11 @@ public class TaxiPassengerTrafficLightView extends IViewTrafficLight {
|
||||
* 展示红绿灯预警
|
||||
*
|
||||
* @param checkLightId 0-都是默认,1-红,2-黄,3-绿
|
||||
* @param lightSource 1:云端下发;2:自车感知
|
||||
*/
|
||||
@Override
|
||||
public void showWarningTrafficLight(int checkLightId) {
|
||||
super.showWarningTrafficLight(checkLightId);
|
||||
public void showWarningTrafficLight(int checkLightId,int lightSource) {
|
||||
super.showWarningTrafficLight(checkLightId,lightSource);
|
||||
mCurrentLightId = checkLightId;
|
||||
updateTrafficLightIcon(checkLightId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.mogo.och.taxi.passenger.utils;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
|
||||
import com.mogo.commons.debug.DebugConfig;
|
||||
import com.mogo.eagle.core.data.app.AppConfigInfo;
|
||||
import com.mogo.eagle.core.function.call.analytics.AnalyticsManager;
|
||||
import com.mogo.eagle.core.utilcode.util.DateTimeUtils;
|
||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
|
||||
import com.mogo.och.taxi.passenger.constant.TaxiPassengerConst;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* OCH Taxi埋点工具
|
||||
*
|
||||
* Created on 2022/3/24
|
||||
*/
|
||||
public class TaxiPassengerAnalyticsManager {
|
||||
|
||||
private static final class SingletonHolder {
|
||||
private static final TaxiPassengerAnalyticsManager INSTANCE = new TaxiPassengerAnalyticsManager();
|
||||
}
|
||||
|
||||
public static TaxiPassengerAnalyticsManager getInstance() {
|
||||
return TaxiPassengerAnalyticsManager.SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String mStartAutopilotKey;
|
||||
private HashMap<String, Object> mStartAutopilotParams = new HashMap<>();
|
||||
|
||||
private Runnable startAutopilotRunnable = () -> {
|
||||
// 15s内未开启,上报失败埋点
|
||||
mStartAutopilotParams.put(TaxiPassengerConst.EVENT_PARAM_START_RESULT, false);
|
||||
AnalyticsManager.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams);
|
||||
};
|
||||
|
||||
/**
|
||||
* 触发'开启自动驾驶'埋点流程
|
||||
* 开启自动驾驶,15s内成功则发送成功埋点,否则发送失败埋点
|
||||
* @param restart false(点击'开始服务'启动)/true(接管后点击'自动驾驶'按钮启动)
|
||||
* @param send 是否直接发送埋点(15s内开启成功则直接发送成功埋点)
|
||||
*/
|
||||
public void triggerStartAutopilotEvent(
|
||||
boolean restart, boolean send, String startName, String endName, String orderNo) {
|
||||
mStartAutopilotKey = restart ?
|
||||
TaxiPassengerConst.EVENT_KEY_RESTART_AUTOPILOT : TaxiPassengerConst.EVENT_KEY_START_SERVICE;
|
||||
String sn = MoGoAiCloudClientConfig.getInstance().getSn();
|
||||
String plateNum = AppConfigInfo.INSTANCE.getPlateNumber();
|
||||
String dateTime = DateTimeUtils.getTimeText(
|
||||
System.currentTimeMillis(), DateTimeUtils.yyyy_MM_dd_HH_mm_ss);
|
||||
|
||||
mStartAutopilotParams.put(TaxiPassengerConst.EVENT_PARAM_SN, sn);
|
||||
mStartAutopilotParams.put(TaxiPassengerConst.EVENT_PARAM_PLATE_NUM, TextUtils.isEmpty(plateNum) ? "" : plateNum);
|
||||
mStartAutopilotParams.put(TaxiPassengerConst.EVENT_PARAM_ENV_ONLINE,
|
||||
DebugConfig.getNetMode() == DebugConfig.NET_MODE_RELEASE ? true : false);
|
||||
mStartAutopilotParams.put(TaxiPassengerConst.EVENT_PARAM_TIME, dateTime);
|
||||
mStartAutopilotParams.put(TaxiPassengerConst.EVENT_PARAM_START_NAME, startName);
|
||||
mStartAutopilotParams.put(TaxiPassengerConst.EVENT_PARAM_END_NAME, endName);
|
||||
mStartAutopilotParams.put(TaxiPassengerConst.EVENT_PARAM_ORDER_NUMBER, orderNo);
|
||||
|
||||
if (send) {
|
||||
// 开启成功,上报埋点
|
||||
if (startAutopilotRunnable != null &&
|
||||
UiThreadHandler.getsUiHandler().hasCallbacks(startAutopilotRunnable)) {
|
||||
UiThreadHandler.removeCallbacks(startAutopilotRunnable);
|
||||
}
|
||||
mStartAutopilotParams.put(TaxiPassengerConst.EVENT_PARAM_START_RESULT, true);
|
||||
AnalyticsManager.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams);
|
||||
} else {
|
||||
UiThreadHandler.postDelayed(startAutopilotRunnable, TaxiPassengerConst.LOOP_PERIOD_15S);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 930 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 930 KiB |
230
OCH/mogo-och-taxi-passenger/src/main/res/drawable/anmi_flow.xml
Normal file
@@ -0,0 +1,230 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:oneshot="false">
|
||||
<item
|
||||
android:drawable="@drawable/image_00000"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00001"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00002"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00003"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00004"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00005"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00006"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00007"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00008"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00009"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00010"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00011"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00012"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00013"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00014"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00015"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00016"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00017"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00018"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00019"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00020"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00021"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00022"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00023"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00024"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00025"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00026"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00027"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00028"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00029"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00030"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00031"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00032"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00033"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00034"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00035"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00036"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00037"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00038"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00039"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00040"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00041"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00042"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00043"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00044"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00045"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00046"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00047"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00048"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00049"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00050"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00051"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00052"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00053"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00054"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00055"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00056"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00057"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00058"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00059"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00060"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00061"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00062"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00063"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00064"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00065"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00066"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00067"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00068"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00069"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00070"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00071"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00072"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00073"
|
||||
android:duration="100"></item>
|
||||
<item
|
||||
android:drawable="@drawable/image_00074"
|
||||
android:duration="100"></item>
|
||||
</animation-list>
|
||||
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 121 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 126 KiB |
|
After Width: | Height: | Size: 127 KiB |
|
After Width: | Height: | Size: 128 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 131 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 128 KiB |
|
After Width: | Height: | Size: 126 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 120 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 117 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 117 KiB |
|
After Width: | Height: | Size: 117 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 118 KiB |