Merge branch 'qa_merge_shunyi_vr_map' into dev_1.1.9

This commit is contained in:
董宏宇
2020-12-30 14:45:28 +08:00
29 changed files with 941 additions and 161 deletions

6
.idea/misc.xml generated
View File

@@ -1,10 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ASMIdeaPluginConfiguration">
<asm skipDebug="false" skipFrames="false" skipCode="false" expandFrames="false" />
<groovy codeStyle="LEGACY" />
</component>
<component name="ASMPluginConfiguration">
<asm skipDebug="false" skipFrames="false" skipCode="false" expandFrames="false" />
<groovy codeStyle="LEGACY" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="JDK" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
</project>

View File

@@ -20,11 +20,12 @@ public class ViewUtils {
view.destroyDrawingCache();
view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas( bitmap );
view.draw( canvas );
return bitmap;
// return (bitmap = view.getDrawingCache()) != null ? bitmap.copy(Bitmap.Config.ARGB_8888, false) : null;
// Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
// Canvas canvas = new Canvas( bitmap );
// view.draw( canvas );
// return bitmap;
Bitmap bitmap = null;
return (bitmap = view.getDrawingCache()) != null ? bitmap.copy(Bitmap.Config.ARGB_8888, false) : null;
}
public static void processChildView(View view) {

View File

@@ -139,7 +139,7 @@ HTTPDNS_NOOP_VERSION = 2.0.12
######## 外部依赖引用
# 车聊聊
CARCHATTING_VERSION=2.2.42
CARCHATTING_VERSION=2.2.50
# 车聊聊接口
CARCHATTINGPROVIDER_VERSION=1.1.8
# websocket

View File

@@ -67,7 +67,7 @@ dependencies {
implementation project(':foudations:mogo-commons')
}
implementation 'com.zhidaoauto.machine:map:1.0.0-vr-7.5.4'
implementation 'com.zhidaoauto.machine:map:1.0.0-vr-7.5.5'
// implementation 'com.zhidaoauto.machine:map:1.0.0-vr-7.4.5-log-1'
}

View File

@@ -576,6 +576,9 @@ public class AMapViewWrapper implements IMogoMapView,
if ( !checkAMapView() ) {
return;
}
if ( mCurrentUI == EnumMapUI.Type_VR ) {
return;
}
Logger.i( TAG, "showBounds:%s -%s-%s- %b ", tag, carPosition.toString(), bound.toShortString(), lockCarPosition );
try {
if ( DebugConfig.isDebug() ) {

View File

@@ -7,7 +7,7 @@ class HttpConstants {
companion object {
const val DEV_BASE_URL_OWNER = "http://dzt-test.zhidaozhixing.com/"
const val RELEASE_BASE_URL_OWNER = "http://dzt.zhidaohulian.com/"
const val RELEASE_BASE_URL_OWNER = "http://dzt.zhidaozhixing.com/"
const val SHOW_BASE_URL_OWNER = "http://dzt-show.zhidaozhixing.com/"
fun getBaseUrl(): String {

View File

@@ -0,0 +1,44 @@
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
method-hook-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/method-hook-lib.cpp )
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
method-hook-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )

View File

@@ -11,8 +11,18 @@ android {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
externalNativeBuild {
cmake {
cppFlags "-std=c++11 -frtti -fexceptions"
}
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
buildTypes {
release {
minifyEnabled false

View File

@@ -0,0 +1,102 @@
#include <jni.h>
#include <string.h>
//
// Created by donghongyu on 12/10/20 1:34 PM.
// 源码地址 https://github.com/pqpo/methodhook
// 方法hook jni类
static const char *kClassMethodHookChar = "com/mogo/module/common/hook/MethodHook";
static struct {
jmethodID m1;
jmethodID m2;
size_t methodSize;
} methodHookClassInfo;
/**
* 替换指定类中的方法
* @param env
* @param type
* @param srcMethodObj 目标方法对象
* @param destMethodObj 替换的方法对象
* @return
*/
static jlong methodHook(JNIEnv *env, jclass type, jobject srcMethodObj, jobject destMethodObj) {
// 反射获取了Java对象的在native层的 ArtMethod指针
void *srcMethod = reinterpret_cast<void *>(env->FromReflectedMethod(srcMethodObj));
void *destMethod = reinterpret_cast<void *>(env->FromReflectedMethod(destMethodObj));
// 定义存储方法ID的数组
int *backupMethod = new int[methodHookClassInfo.methodSize];
// 使用的内存拷贝函数
// 将旧方法ID拷贝到数组中
memcpy(backupMethod, srcMethod, methodHookClassInfo.methodSize);
// 将新方法替换到旧方法地址上
memcpy(srcMethod, destMethod, methodHookClassInfo.methodSize);
// 将旧方法ID返回给java层用来做方法还原使用
return reinterpret_cast<long>(backupMethod);
}
/**
* 恢复指定类中的方法
* @param env
* @param type
* @param srcMethod 目标方法对象
* @param methodPtr
* @return
*/
static jobject methodRestore(JNIEnv *env, jclass type, jobject srcMethod, jlong methodPtr) {
// 要还原的旧方法 指针
int *backupMethod = reinterpret_cast<int *>(methodPtr);
// 获取了Java对象的在native层的 ArtMethod指针
void *artMethodSrc = reinterpret_cast<void *>(env->FromReflectedMethod(srcMethod));
// 将旧方法指针,替换到 artMethodSrc 中
memcpy(artMethodSrc, backupMethod, methodHookClassInfo.methodSize);
// 删除旧方法备份指针
delete[]backupMethod;
// 返回旧方法
return srcMethod;
}
// 定义要注册的方法
static JNINativeMethod gMethods[] = {
{
"hook_native",
"(Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;)J",
(void *) methodHook
},
{
"restore_native",
"(Ljava/lang/reflect/Method;J)Ljava/lang/reflect/Method;",
(void *) methodRestore
}
};
extern "C"
JNIEXPORT jint JNICALL
/**
* 在jni加载的时候进行方法参数获取
* @param vm
* @param reserved
* @return
*/
JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env = nullptr;
if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
return JNI_FALSE;
}
// 加载指定java class
jclass classEvaluateUtil = env->FindClass(kClassMethodHookChar);
// 注册
if (env->RegisterNatives(classEvaluateUtil, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) <
0) {
return JNI_FALSE;
}
// 获取 MethodHook m1、m2 的方法ID
methodHookClassInfo.m1 = env->GetStaticMethodID(classEvaluateUtil, "m1", "()V");
methodHookClassInfo.m2 = env->GetStaticMethodID(classEvaluateUtil, "m2", "()V");
// 获取artMethod的大小
methodHookClassInfo.methodSize = reinterpret_cast<size_t>(methodHookClassInfo.m2) -
reinterpret_cast<size_t>(methodHookClassInfo.m1);
return JNI_VERSION_1_4;
}

View File

@@ -73,11 +73,27 @@ public class BezierAnimationView extends RelativeLayout implements View.OnClickL
runnable.run();
}
public void bezierAnimationStart(){
runnable = new Runnable() {
@Override
public void run() {
try {
Log.d("点赞--", "");
bezierAnimation(resource);
handler.postDelayed(this, 500);
} catch (Exception e) {
e.printStackTrace();
}
}
};
runnable.run();
}
private void bezierAnimation(int resource) {
final ImageView imageView = new ImageView(context);
imageView.setBackgroundResource(animation_drawable[resource]);
RelativeLayout.LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.addRule(ALIGN_BOTTOM);
// params.addRule(ALIGN_BOTTOM);
params.addRule(CENTER_HORIZONTAL);
imageView.setLayoutParams(params);
addView(imageView);

View File

@@ -50,10 +50,10 @@ public class MapMarkerAdapter {
* @return MarkerView
*/
public static IMarkerView getMarkerInfoWindowView( Context context, MarkerShowEntity markerShowEntity, MogoMarkerOptions options ) {
if ( markerShowEntity.isChecked() ) {
return new MapMarkerInfoView( context, markerShowEntity, options );
} else {
return new MapMarkerView( context, markerShowEntity, options );
}
// if ( markerShowEntity.isChecked() ) {
// return new MapMarkerInfoView( context, markerShowEntity, options );
// } else {
// }
return new MapMarkerView( context, markerShowEntity, options );
}
}

View File

@@ -52,7 +52,11 @@ public class MapMarkerInfoView extends MapMarkerBaseView {
public MapMarkerInfoView( Context context, MarkerShowEntity markerShowEntity, MogoMarkerOptions options ) {
super( context );
mOptions = options;
updateView( markerShowEntity );
try {
updateView( markerShowEntity );
} catch ( Exception e ) {
e.printStackTrace();
}
}
@Override
@@ -60,7 +64,7 @@ public class MapMarkerInfoView extends MapMarkerBaseView {
LayoutInflater.from( context ).inflate( R.layout.modudle_services_marker_layout_info, this );
ivUserHead = findViewById( R.id.ivUserHead );
// ivIcon = findViewById( R.id.ivIcon );
ivIcon = findViewById(R.id.ivIcon);
ivIcon = findViewById( R.id.ivIcon );
clMarkerContent = findViewById( R.id.clMarkerContent );
ivReverseTriangle = findViewById( R.id.ivReverseTriangle );
ivCar = findViewById( R.id.ivCar );
@@ -69,84 +73,80 @@ public class MapMarkerInfoView extends MapMarkerBaseView {
@Override
public void updateView( MarkerShowEntity markerShowEntity ) {
try {
Object bindObj = markerShowEntity.getBindObj();
Object bindObj = markerShowEntity.getBindObj();
if ( MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode() ) {
ivCar.setImageResource( R.drawable.icon_map_marker_location_yellow_vr );
} else {
ivCar.setImageResource( R.drawable.icon_map_marker_location_yellow );
}
clMarkerContent.setBackgroundResource( R.drawable.bg_map_marker_yellow_info );
ivReverseTriangle.setImageResource( R.drawable.bg_shape_reverse_yellow );
switch ( markerShowEntity.getMarkerType() ) {
case ModuleNames.CARD_TYPE_CARS_CHATTING:
case ModuleNames.CARD_TYPE_USER_DATA:
ivUserHead.setVisibility( View.VISIBLE );
ivIcon.setVisibility( View.INVISIBLE );
loadImageWithMarker( markerShowEntity );
ivCar.setImageResource( R.drawable.icon_map_marker_car_gray );
//ivCar.setRotation(new Random().nextInt(360));
ivCar.setRotation( ( float ) markerShowEntity.getMarkerLocation().getAngle() );
break;
case ModuleNames.CARD_TYPE_ROAD_CONDITION:
case ModuleNames.CARD_TYPE_NOVELTY:
ivUserHead.setVisibility( View.INVISIBLE );
ivIcon.setVisibility( View.VISIBLE );
if ( bindObj instanceof MarkerExploreWay && ( ( MarkerExploreWay ) bindObj ).getPoiType() != null ) {
// 根据poiType获取对应的图片
String poiType = ((MarkerExploreWay) bindObj).getPoiType();
PoiWrapper poiWrapper =
CloudPoiManager.getInstance().getWrapperByPoiType(poiType);
if (poiWrapper != null) {
// 加载图片
loadPoiTypeIcon(poiWrapper.getIconInfoUrl(),poiWrapper.getIconInfoRes());
}else{
Logger.e(TAG, "未能根据poiType获取对应poi信息无法渲染info marker====" + poiType);
}
}
break;
case ModuleNames.CARD_TYPE_SHARE_MUSIC:
ivUserHead.setVisibility( View.INVISIBLE );
ivIcon.setVisibility( View.VISIBLE );
if ( bindObj instanceof MarkerShareMusic ) {
// 2 为书籍听书3 为新闻,1 为qq音乐,int
switch ( ( ( MarkerShareMusic ) bindObj ).getShareType() ) {
case 1:
ivIcon.setImageResource( R.drawable.icon_map_marker_misic );
break;
case 2:
ivIcon.setImageResource( R.drawable.icon_map_marker_book );
break;
case 3:
ivIcon.setImageResource( R.drawable.icon_map_marker_news );
break;
default:
ivIcon.setImageResource( R.drawable.icon_map_marker_misic );
break;
}
}
break;
default:
break;
}
if ( !TextUtils.isEmpty( markerShowEntity.getTextContent() ) ) {
String content;
if ( markerShowEntity.getTextContent().length() > 8 ) {
content = markerShowEntity.getTextContent().substring( 0, 7 ) + "...";
} else {
content = markerShowEntity.getTextContent();
}
tvMarkerContent.setText( content );
}
} catch ( Exception e ) {
e.printStackTrace();
if ( MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode() ) {
ivCar.setImageResource( R.drawable.icon_map_marker_location_yellow_vr );
} else {
ivCar.setImageResource( R.drawable.icon_map_marker_location_yellow );
}
clMarkerContent.setBackgroundResource( R.drawable.bg_map_marker_yellow_info );
ivReverseTriangle.setImageResource( R.drawable.bg_shape_reverse_yellow );
switch ( markerShowEntity.getMarkerType() ) {
case ModuleNames.CARD_TYPE_CARS_CHATTING:
case ModuleNames.CARD_TYPE_USER_DATA:
ivUserHead.setVisibility( View.VISIBLE );
ivIcon.setVisibility( View.INVISIBLE );
loadImageWithMarker( markerShowEntity );
ivCar.setImageResource( R.drawable.icon_map_marker_car_gray );
//ivCar.setRotation(new Random().nextInt(360));
ivCar.setRotation( ( float ) markerShowEntity.getMarkerLocation().getAngle() );
break;
case ModuleNames.CARD_TYPE_ROAD_CONDITION:
case ModuleNames.CARD_TYPE_NOVELTY:
ivUserHead.setVisibility( View.INVISIBLE );
ivIcon.setVisibility( View.VISIBLE );
if ( bindObj instanceof MarkerExploreWay && ( ( MarkerExploreWay ) bindObj ).getPoiType() != null ) {
// 根据poiType获取对应的图片
String poiType = ( ( MarkerExploreWay ) bindObj ).getPoiType();
PoiWrapper poiWrapper =
CloudPoiManager.getInstance().getWrapperByPoiType( poiType );
if ( poiWrapper != null ) {
// 加载图片
loadPoiTypeIcon( poiWrapper.getIconInfoUrl(), poiWrapper.getIconInfoRes() );
} else {
Logger.e( TAG, "未能根据poiType获取对应poi信息无法渲染info marker====" + poiType );
}
}
break;
case ModuleNames.CARD_TYPE_SHARE_MUSIC:
ivUserHead.setVisibility( View.INVISIBLE );
ivIcon.setVisibility( View.VISIBLE );
if ( bindObj instanceof MarkerShareMusic ) {
// 2 为书籍听书3 为新闻,1 为qq音乐,int
switch ( ( ( MarkerShareMusic ) bindObj ).getShareType() ) {
case 1:
ivIcon.setImageResource( R.drawable.icon_map_marker_misic );
break;
case 2:
ivIcon.setImageResource( R.drawable.icon_map_marker_book );
break;
case 3:
ivIcon.setImageResource( R.drawable.icon_map_marker_news );
break;
default:
ivIcon.setImageResource( R.drawable.icon_map_marker_misic );
break;
}
}
break;
default:
break;
}
if ( !TextUtils.isEmpty( markerShowEntity.getTextContent() ) ) {
String content;
if ( markerShowEntity.getTextContent().length() > 8 ) {
content = markerShowEntity.getTextContent().substring( 0, 7 ) + "...";
} else {
content = markerShowEntity.getTextContent();
}
tvMarkerContent.setText( content );
}
}
}

View File

@@ -24,11 +24,11 @@ import com.mogo.utils.logger.Logger;
* desc : 地图Marker图标
* version: 1.0
*/
public class
MapMarkerView extends MapMarkerBaseView {
public class MapMarkerView extends MapMarkerBaseView {
private String TAG = "MapMarkerView";
private FrameLayout clMarkerTopView;
private MarkerShowEntity mMarkerShowEntity;
public MapMarkerView( Context context ) {
super( context );
@@ -45,7 +45,12 @@ MapMarkerView extends MapMarkerBaseView {
public MapMarkerView( Context context, MarkerShowEntity markerShowEntity, MogoMarkerOptions options ) {
super( context );
mOptions = options;
updateView( markerShowEntity );
mMarkerShowEntity = markerShowEntity;
try {
updateView( markerShowEntity );
} catch ( Exception e ) {
e.printStackTrace();
}
}
@Override
@@ -55,37 +60,35 @@ MapMarkerView extends MapMarkerBaseView {
} else {
LayoutInflater.from( context ).inflate( R.layout.modudle_services_marker_layout, this );
}
ivIcon = findViewById( R.id.ivIcon );
clMarkerTopView = findViewById( R.id.clMarkerTopView );
ivIcon = findViewById( R.id.ivIcon );
ivCar = findViewById( R.id.ivCar );
}
@Override
public void updateView( MarkerShowEntity markerShowEntity ) {
try {
Object bindObj = markerShowEntity.getBindObj();
switch ( markerShowEntity.getMarkerType() ) {
case ModuleNames.CARD_TYPE_ROAD_CONDITION:
case ModuleNames.CARD_TYPE_NOVELTY:
if ( bindObj instanceof MarkerExploreWay && ( ( MarkerExploreWay ) bindObj ).getPoiType() != null ) {
// 根据poiType获取对应的图片
String poiType = ( ( MarkerExploreWay ) bindObj ).getPoiType();
PoiWrapper poiWrapper =
CloudPoiManager.getInstance().getWrapperByPoiType( poiType );
if ( poiWrapper != null ) {
// 加载图片
loadPoiTypeIcon( poiWrapper.getIconUrl(), poiWrapper.getIconRes() );
} else {
Logger.e( TAG, "未能根据poiType获取对应poi信息无法渲染marker====" + poiType );
}
Object bindObj = markerShowEntity.getBindObj();
switch ( markerShowEntity.getMarkerType() ) {
case ModuleNames.CARD_TYPE_ROAD_CONDITION:
case ModuleNames.CARD_TYPE_NOVELTY:
if ( mMarkerShowEntity != null && mMarkerShowEntity.isChecked() ) {
clMarkerTopView.setBackgroundResource( R.drawable.module_services_marker_vr_bkg_checked );
}
if ( bindObj instanceof MarkerExploreWay && ( ( MarkerExploreWay ) bindObj ).getPoiType() != null ) {
// 根据poiType获取对应的图片
String poiType = ( ( MarkerExploreWay ) bindObj ).getPoiType();
PoiWrapper poiWrapper =
CloudPoiManager.getInstance().getWrapperByPoiType( poiType );
if ( poiWrapper != null ) {
// 加载图片
loadPoiTypeIcon( poiWrapper.getIconUrl(), poiWrapper.getIconRes() );
} else {
Logger.e( TAG, "未能根据poiType获取对应poi信息无法渲染marker====" + poiType );
}
break;
default:
break;
}
} catch ( Exception e ) {
e.printStackTrace();
}
break;
default:
break;
}
}

View File

@@ -0,0 +1,67 @@
package com.mogo.module.common.hook;
import android.util.Pair;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 替换管理
* Created by donghongyu on 12/29/20 1:34 PM
*/
public final class HookManager {
private HookManager() {
}
public static HookManager get() {
return InstanceHolder.sInstance;
}
private static class InstanceHolder {
private static HookManager sInstance = new HookManager();
}
private Map<Pair<String, String>, MethodHook> methodHookMap = new ConcurrentHashMap<>();
/**
* 替换方法
*
* @param originMethod 原始方法
* @param hookMethod 替换方法
*/
public void hookMethod(Method originMethod, Method hookMethod) {
if (originMethod == null || hookMethod == null) {
throw new IllegalArgumentException("argument cannot be null");
}
Pair<String, String> key = Pair.create(hookMethod.getDeclaringClass().getName(), hookMethod.getName());
if (methodHookMap.containsKey(key)) {
MethodHook methodHook = methodHookMap.get(key);
methodHook.restore();
}
MethodHook methodHook = new MethodHook(originMethod, hookMethod);
methodHookMap.put(key, methodHook);
methodHook.hook();
}
public void callOrigin(Object receiver, Object... args) {
StackTraceElement stackTrace = Thread.currentThread().getStackTrace()[3];
String className = stackTrace.getClassName();
String methodName = stackTrace.getMethodName();
MethodHook methodHook = methodHookMap.get(Pair.create(className, methodName));
if (methodHook != null) {
try {
methodHook.callOrigin(receiver, args);
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,100 @@
package com.mogo.module.common.hook;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 替换类与c++代码对应
* Created by donghongyu on 12/29/20 1:34 PM
*/
public class MethodHook {
public static void m1() {
}
public static void m2() {
}
// 目标方法
private Method srcMethod;
// 要替换的方法
private Method hookMethod;
// 备份目标替换方法ID
private long backupMethodPtr;
/**
* hook方法
*
* @param src 要替换的方法对象
* @param dest 被替换的方法对象
*/
public MethodHook(Method src, Method dest) {
srcMethod = src;
hookMethod = dest;
srcMethod.setAccessible(true);
hookMethod.setAccessible(true);
}
/**
* 调用 native 层,完成替换
*/
public void hook() {
if (backupMethodPtr == 0) {
backupMethodPtr = hook_native(srcMethod, hookMethod);
}
}
/**
* 调用 native 层,完成方法还原
*/
public void restore() {
if (backupMethodPtr != 0) {
restore_native(srcMethod, backupMethodPtr);
backupMethodPtr = 0;
}
}
/**
* 调用原来class 对象中的方法
*
* @param receiver 接受对象
* @param args 方法列表
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public void callOrigin(Object receiver, Object... args)
throws InvocationTargetException, IllegalAccessException {
if (backupMethodPtr != 0) {
restore();
srcMethod.invoke(receiver, args);
hook();
} else {
srcMethod.invoke(receiver, args);
}
}
/**
* 调用 native 方法完成 方法替换
*
* @param src 旧方法
* @param dest 新方法
* @return 就方法ID
*/
private static native long hook_native(Method src, Method dest);
/**
* 调用 native 方法完成 方法还原
*
* @param src
* @param methodPtr
* @return
*/
private static native Method restore_native(Method src, long methodPtr);
static {
// 加载本地方法 so
System.loadLibrary("method-hook-lib");
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#890">
<com.mogo.module.common.animation.BezierAnimationView
android:id="@+id/bezier_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#7810" />
</RelativeLayout>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval"
android:useLevel="false">
<solid android:color="#000000" />
<size
android:width="@dimen/module_media_pop_window_anim_img_size_new"
android:height="@dimen/module_media_pop_window_anim_img_size_new" />
</shape>

View File

@@ -7,45 +7,59 @@
<com.mogo.module.media.widget.CircleNumberProgress
android:id="@+id/window_circle_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:circleBackground="@color/modules_media_music_bg_color"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:circleBackground="@color/modules_media_music_bg_color"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- app:ringColor="@color/modules_media_music_circle_color"-->
app:layout_constraintTop_toTopOf="parent" />
<!-- app:ringColor="@color/modules_media_music_circle_color"-->
<!-- <com.mogo.module.media.widget.PercentageRingView-->
<!-- android:id="@+id/window_circle_bg"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintLeft_toLeftOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent"-->
<!-- app:layout_constraintRight_toRightOf="parent"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent" />-->
<!-- <com.mogo.module.media.widget.PercentageRingView-->
<!-- android:id="@+id/window_circle_bg"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintLeft_toLeftOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent"-->
<!-- app:layout_constraintRight_toRightOf="parent"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent" />-->
<com.mogo.module.media.widget.AnimCircleImageView
android:id="@+id/window_circle_img_new"
android:layout_width="@dimen/module_media_pop_window_anim_img_size_new"
android:layout_height="@dimen/module_media_pop_window_anim_img_size_new"
android:src="@drawable/module_media_default_music_img_new"
android:scaleType="fitCenter"
android:src="@drawable/module_media_default_music_img_new"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/window_play_pause_new"
android:layout_width="@dimen/module_media_pop_window_pause"
android:layout_height="@dimen/module_media_pop_window_pause"
android:background="@drawable/module_media_play_bg_selector"
android:src="@drawable/module_media_window_pop_play_new"
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/window_obscuration"
android:layout_width="@dimen/module_media_pop_window_anim_img_size_new"
android:layout_height="@dimen/module_media_pop_window_anim_img_size_new"
android:layout_gravity="center_vertical|center_horizontal"
android:alpha="0.5"
android:background="@drawable/module_media_circle_bg" />
<ImageView
android:id="@+id/window_play_pause_new"
android:layout_width="@dimen/module_media_pop_window_pause"
android:layout_height="@dimen/module_media_pop_window_pause"
android:layout_gravity="center_vertical|center_horizontal"
android:background="@drawable/module_media_play_bg_selector"
android:src="@drawable/module_media_window_pop_play_new" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -927,6 +927,8 @@ public class MogoServices implements IMogoMapListener,
return mLastCarLocation;
}
private boolean mLastStatusIsVr = false;
@Override
public void onMapModeChanged( EnumMapUI ui ) {
if ( ui == EnumMapUI.Type_VR ) {
@@ -934,11 +936,15 @@ public class MogoServices implements IMogoMapListener,
MapCenterPointStrategy.resetByChangeMode();
MapMarkerManager.getInstance().redrawMarkerByStyleChanged();
AIAssist.getInstance( mContext ).speakTTSVoice( "你已进入鹰眼模式" );
mLastStatusIsVr = true;
} else {
MogoApisHandler.getInstance().getApis().getStatusManagerApi().setVrMode( TAG, false );
MapCenterPointStrategy.resetByChangeMode();
MapMarkerManager.getInstance().redrawMarkerByStyleChanged();
AIAssist.getInstance( mContext ).speakTTSVoice( "你已离开鹰眼模式" );
if ( mLastStatusIsVr ) {
mLastStatusIsVr = false;
MogoApisHandler.getInstance().getApis().getStatusManagerApi().setVrMode( TAG, false );
MapCenterPointStrategy.resetByChangeMode();
MapMarkerManager.getInstance().redrawMarkerByStyleChanged();
AIAssist.getInstance( mContext ).speakTTSVoice( "你已离开鹰眼模式" );
}
}
}
}

View File

@@ -2,10 +2,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mogo.module.small.map">
<application>
<!--<application>
<service
android:name=".SmallMapService"
android:exported="false"
android:process=":smallMap"/>
</application>
/>
</application>-->
</manifest>

View File

@@ -0,0 +1,186 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.amap.api.col.n3;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.LayoutInflater.Factory;
import android.view.View;
import android.view.ViewStub;
import com.android.internal.policy.MyPhoneLayoutInflater;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.HashSet;
public final class le2 extends ContextThemeWrapper {
private Resources a = lg.a();
private Theme b;
private LayoutInflater c;
private ClassLoader d;
private int e;
private static final String[] f = new String[]{"android.widget", "android.webkit", "android.app"};
private le2.a g = new le2.a();
private Factory h = new Factory() {
public final View onCreateView(String var1, Context var2, AttributeSet var3) {
return le2.this.a(var1, var2, var3);
}
};
public le2(Context var1, int var2, ClassLoader var3) {
super(var1, var2);
this.d = var3;
this.b = lg.b();
this.e = var2;
super.onApplyThemeResource(this.b, this.e, true);
(new StringBuilder("classloader:")).append(this.d);
}
public final Resources getResources() {
return this.a != null ? this.a : super.getResources();
}
public final void a(int var1) {
if (var1 != this.e) {
this.e = var1;
super.onApplyThemeResource(this.b, this.e, true);
}
}
public final Theme getTheme() {
return this.b != null ? this.b : super.getTheme();
}
public final Object getSystemService(String var1) {
if ("layout_inflater".equals(var1)) {
if (this.c == null) {
// 这里构建一个自己对的布局填充器
// 与已经被修改的context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)
// 隔离从而保证高德地图SDK能正常初始化
LayoutInflater var2 = new MyPhoneLayoutInflater(getBaseContext());
this.c = var2.cloneInContext(this);
this.c.setFactory(this.h);
this.c = this.c.cloneInContext(this);
}
return this.c;
} else {
return super.getSystemService(var1);
}
}
private final View a(String var1, Context var2, AttributeSet var3) {
if (this.g.a.contains(var1)) {
return null;
} else {
Constructor var4;
if ((var4 = (Constructor) this.g.b.get(var1)) == null) {
Class var5 = null;
boolean var6 = false;
String var7 = "api.navi";
label71:
{
label70:
{
Throwable var10000;
label79:
{
boolean var10001;
try {
if (var1.contains(var7)) {
var5 = this.d.loadClass(var1);
} else {
String[] var17;
int var8 = (var17 = f).length;
int var9 = 0;
while (var9 < var8) {
String var10 = var17[var9];
try {
var5 = this.d.loadClass(var10 + "." + var1);
break;
} catch (Throwable var13) {
++var9;
}
}
}
if (var5 == null) {
break label71;
}
} catch (Throwable var15) {
var10000 = var15;
var10001 = false;
break label79;
}
if (var5 == ViewStub.class) {
break label71;
}
try {
if (var5.getClassLoader() != this.d) {
break label71;
}
break label70;
} catch (Throwable var14) {
var10000 = var14;
var10001 = false;
}
}
Throwable var18 = var10000;
(new StringBuilder("load view err:")).append(Log.getStackTraceString(var18));
break label71;
}
var6 = true;
}
if (!var6) {
this.g.a.add(var1);
return null;
}
try {
var4 = var5.getConstructor(Context.class, AttributeSet.class);
this.g.b.put(var1, var4);
} catch (Throwable var12) {
(new StringBuilder("create view err:")).append(Log.getStackTraceString(var12));
}
}
try {
View var16 = null;
if (var4 != null) {
var16 = (View) var4.newInstance(var2, var3);
}
return var16;
} catch (Throwable var11) {
(new StringBuilder("create view err:")).append(Log.getStackTraceString(var11));
return null;
}
}
}
public static class a {
public HashSet<String> a = new HashSet();
public HashMap<String, Constructor<?>> b = new HashMap();
public a() {
}
}
}

View File

@@ -0,0 +1,40 @@
package com.amap.api.col.n3;
import android.content.Context;
import android.content.res.XmlResourceParser;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* 这里是为了解决 使用换肤框架后,高德地图初始化有问题加入的
* 问题原因是:
* skin 框架会替换 LayoutInflater 中的 setFactory2 从而导致高德 le 中的 setFactory 失效。
* 解决方案为:
* 直接通过内存地址替换整个 ArtMethod来将需要修改的高德SDK中的方法指向我们修改过后的方法。
*/
public class lg2 extends lg {
static le2 b;
public static View a(Context var0, int var1, ViewGroup var2) {
XmlResourceParser var9 = a().getXml(var1);
if (!a) {
return LayoutInflater.from(var0).inflate(var9, var2);
} else {
try {
if (b == null) {
b = new le2(var0, c == -1 ? 0 : c, lg.class.getClassLoader());
}
b.a(c == -1 ? 0 : c);
View var3 = LayoutInflater.from(b).inflate(var9, var2);
return var3;
} catch (Throwable var7) {
var7.printStackTrace();
np.c(var7, "ResourcesUtil", "selfInflate(Activity activity, int resource, ViewGroup root)");
} finally {
var9.close();
}
return null;
}
}
}

View File

@@ -0,0 +1,60 @@
package com.android.internal.policy;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
/**
* @author donghongyu
* @date 12/25/20 5:12 PM
*/
public class MyPhoneLayoutInflater extends LayoutInflater {
private static final String[] sClassPrefixList = {
"android.widget.",
"android.webkit.",
"android.app."
};
/**
* Instead of instantiating directly, you should retrieve an instance
* through {@link Context#getSystemService}
*
* @param context The Context in which in which to find resources and other
* application-specific things.
* @see Context#getSystemService
*/
public MyPhoneLayoutInflater(Context context) {
super(context);
}
protected MyPhoneLayoutInflater(LayoutInflater original, Context newContext) {
super(original, newContext);
}
/**
* Override onCreateView to instantiate names that correspond to the
* widgets known to the Widget factory. If we don't find a match,
* call through to our super class.
*/
@Override
protected View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException {
for (String prefix : sClassPrefixList) {
try {
View view = createView(name, prefix, attrs);
if (view != null) {
return view;
}
} catch (ClassNotFoundException e) {
// In this case we want to let the base class take a crack
// at it.
}
}
return super.onCreateView(name, attrs);
}
public LayoutInflater cloneInContext(Context newContext) {
return new MyPhoneLayoutInflater(this, newContext);
}
}

View File

@@ -1,22 +1,30 @@
package com.mogo.module.small.map;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.mogo.commons.AbsMogoApplication;
import com.amap.api.col.n3.lg;
import com.amap.api.col.n3.lg2;
import com.mogo.module.common.MogoApisHandler;
import com.mogo.module.common.hook.HookManager;
import com.mogo.module.common.wm.WindowManagerView;
import com.mogo.service.MogoServicePaths;
import com.mogo.service.map.IMogoSmallMapProvider;
import com.mogo.service.module.ModuleType;
import com.mogo.service.statusmanager.IMogoStatusChangedListener;
import com.mogo.service.statusmanager.StatusDescriptor;
import com.mogo.utils.logger.Logger;
import java.lang.reflect.Method;
/**
* @author donghongyu
@@ -26,9 +34,11 @@ import com.mogo.service.statusmanager.StatusDescriptor;
public class SmallVisionProvider implements IMogoSmallMapProvider, IMogoStatusChangedListener {
private final String TAG = "SmallVisionProvider";
private Intent mSmallMapServiceIntent;
private Context mContext;
private WindowManagerView mWindowManagerView;
private SmallMapDirectionView mSmallMapDirectionView;
@Override
public Fragment createFragment(Context context, Bundle data) {
return null;
@@ -55,6 +65,15 @@ public class SmallVisionProvider implements IMogoSmallMapProvider, IMogoStatusCh
Log.d(TAG, "小地图模块初始化……");
mContext = context;
try {
// 替换高德地图的方法,解决因为加入换肤框架导致地图初始化失败
Method srcMethod = lg.class.getDeclaredMethod("a", Context.class, int.class, ViewGroup.class);
Method destMethod = lg2.class.getDeclaredMethod("a", Context.class, int.class, ViewGroup.class);
HookManager.get().hookMethod(srcMethod, destMethod);
} catch (Exception e) {
e.printStackTrace();
}
MogoApisHandler.getInstance()
.getApis()
.getStatusManagerApi()
@@ -76,22 +95,22 @@ public class SmallVisionProvider implements IMogoSmallMapProvider, IMogoStatusCh
public void onDestroy() {
Log.d(TAG, "小地图模块销毁……");
hidePanel();
// 释放组件内存
mSmallMapDirectionView = null;
mWindowManagerView = null;
}
@Override
public void showPanel() {
Log.d(TAG, "小地图模块触发展示……");
if (MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode()) {
mSmallMapServiceIntent = new Intent(mContext, SmallMapService.class);
mContext.startService(mSmallMapServiceIntent);
}
addSmallMapView();
}
@Override
public void hidePanel() {
Log.d(TAG, "小地图模块触发隐藏……");
if (mSmallMapServiceIntent != null) {
AbsMogoApplication.getApp().stopService(mSmallMapServiceIntent);
if (mWindowManagerView != null && mWindowManagerView.isShowing()) {
mWindowManagerView.dismiss();
}
}
@@ -122,4 +141,33 @@ public class SmallVisionProvider implements IMogoSmallMapProvider, IMogoStatusCh
}
}
}
/**
* 添加小地图View
*/
private void addSmallMapView() {
Logger.d(TAG, "addSmallMapView");
// 初始化小地图控件
if (mSmallMapDirectionView == null) {
mSmallMapDirectionView = new SmallMapDirectionView(mContext);
}
if (mWindowManagerView == null) {
mWindowManagerView = new WindowManagerView.Builder(mContext)
.contentView(mSmallMapDirectionView)
.size(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT
)
.position(
mContext.getResources().getDimensionPixelOffset(R.dimen.module_small_map_view_x),
mContext.getResources().getDimensionPixelOffset(R.dimen.module_small_map_view_y)
)
.gravity(Gravity.TOP | Gravity.LEFT)
.showInWindowManager();
}
mWindowManagerView.show();
}
}

View File

@@ -3,6 +3,7 @@ package com.mogo.module.v2x.adapter.holder;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
@@ -10,11 +11,13 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.mogo.commons.AbsMogoApplication;
import com.mogo.commons.debug.DebugConfig;
import com.mogo.module.common.animation.BezierAnimationView;
import com.mogo.module.common.entity.MarkerExploreWay;
@@ -23,6 +26,7 @@ import com.mogo.module.common.entity.V2XEventShowEntity;
import com.mogo.module.common.entity.V2XLiveCarInfoEntity;
import com.mogo.module.common.entity.V2XMessageEntity;
import com.mogo.module.common.entity.V2XRoadEventEntity;
import com.mogo.module.common.wm.WindowManagerView;
import com.mogo.module.v2x.R;
import com.mogo.module.v2x.V2XServiceManager;
import com.mogo.module.v2x.entity.net.V2XUserInfoRes;
@@ -81,7 +85,7 @@ public class V2XRoadEventVH extends V2XBaseViewHolder<V2XEventShowEntity> {
private HeartLikeView ivEventZan;
private ViewGroup mViewGroup;
private WindowManagerView mWindowManagerView;
// 上传事件的用户信息
private MarkerUserInfo mUserInfo;
@@ -312,7 +316,7 @@ public class V2XRoadEventVH extends V2XBaseViewHolder<V2XEventShowEntity> {
e.printStackTrace();
}
}
/*
* 展示事件的图片/视频资源
* */
@@ -364,6 +368,53 @@ public class V2XRoadEventVH extends V2XBaseViewHolder<V2XEventShowEntity> {
}
}
private void bezierAnimation(int[] loc) {
if (mWindowManagerView == null) {
Log.d(TAG, "bezierAnimation:null");
mWindowManagerView = new WindowManagerView.Builder(mContext.getApplicationContext())
.contentView(R.layout.module_common_bezier_layout)
.size(WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT)
.position(loc[0], loc[1])
.gravity(Gravity.TOP | Gravity.LEFT)
.showInWindowManager();
}
try {
if (mWindowManagerView.isShowing()) {
return;
}
mWindowManagerView.show();
} catch (Exception e) {
e.printStackTrace();
}
BezierAnimationView bezierAnimationView = mWindowManagerView.findViewById(R.id.bezier_view);
bezierAnimationView.bezierAnimationStart();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// mWindowManagerView.dismiss();
}
}, 2000);
}
public int[] getLocation(View v) {
int[] loc = new int[4];
int[] location = new int[2];
v.getLocationOnScreen(location);
loc[0] = location[0];
loc[1] = location[1];
int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
v.measure(w, h);
loc[2] = v.getMeasuredWidth();
loc[3] = v.getMeasuredHeight();
//base = computeWH();
return loc;
}
/**
* 为了给车聊聊更多的信息需要重新查询一次
*

View File

@@ -36,7 +36,7 @@
<TextView
android:id="@+id/tvEventTypeTitle"
android:layout_width="@dimen/dp_120"
android:layout_height="@dimen/dp_40"
android:layout_height="@dimen/dp_35"
android:layout_marginStart="@dimen/dp_31"
android:layout_marginBottom="@dimen/dp_42"
android:background="@drawable/bg_v2x_event_type_red_vr"

View File

@@ -37,7 +37,7 @@
<TextView
android:id="@+id/tvImgTextContent"
android:layout_width="@dimen/dp_120"
android:layout_height="@dimen/dp_40"
android:layout_height="@dimen/dp_35"
android:layout_marginTop="15dp"
android:background="@drawable/bg_v2x_event_type_orange_vr"
android:gravity="center"

View File

@@ -120,5 +120,8 @@
<dimen name="v2x_driving_heigt">46px</dimen>
<dimen name="v2x_recommond_route_size">26px</dimen>
<!--适配贝塞尔曲线-->
<dimen name="v2x_bezier_x">1281px</dimen>
</resources>