第三方相关问题

问题收录:第三方登录、第三方支付、推送、分享、ARouter路由、地图等

第三方登录

友盟 微信登录授权不走回调

问题:微信登录没有获取到用户信息、没有反应

解决:

  1. 确认能否进入微信客户端授权确认页面

如果不能进入微信授权页面,或者在微信客户端账号未登录状态下只能进入输入账号密码页面,说明签名验证失败,请检查签名是否一致。

  1. 进入微信授权确认页面,点击后没有返回对应的用户资料

进入这一步多半是由于微信回调配置错误导致,首先打开 Debug 模式日志,查看回调Activity(WXEntryActivity.java) 配置是否正常。

如果确认回调 Activity 及AndroidManifest.xml中微信相关配置都正确,需要确认 WXEntryActivity.java中有无复写其他 SDK(如支付、微信原生登录)的回调逻辑,UShare SDK要求留一个空类,相关回调结果在jar中实现,如微信精简版中 Demo 里的配置:

1
public class WXEntryActivity extends WXCallbackActivity{}

支付相关

微信支付相关

微信支付调用不起来的问题(AsyncTask的坑)

AsyncTask如果有 4、5个线程,则会阻塞。
解决:可换成 RxJava

微信支付调用不起来的问题(AsyncTask的坑).png

WXPayEntryActivity 不回调问题

  1. 注意包名:平台注册的包名+.wxapi.WXPayEntryActivity (完整com.xxx.wxapi.WXPayEntryActivity)
  2. 注意类名 WXPayEntryActivity 不能写错,在清单文件中进行注册
  3. 在清单文件中检查WXPayEntryActivity是否有android:exported="true"属性(此属性作用是标记可被别的Application组件调用)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//多渠道的情况下,包名不一致,底下的yyy.yyy等导入信息是共用的
package xxx.xxx.test.wxapi;

import org.apache.commons.lang.StringUtils;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;

import com.tencent.mm.opensdk.constants.ConstantsAPI;
import com.tencent.mm.opensdk.modelbase.BaseReq;
import com.tencent.mm.opensdk.modelbase.BaseResp;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import com.u1city.androidframe.common.toast.ToastUtil;

import yyy.yyy.R;
import yyy.yyy.core.Constants;
import yyy.yyy.sdk.pay.IPayCallBack;
import yyy.yyy.sdk.pay.WXPayHelper;
import yyy.yyy.view.DaogouBaseActivity;

/**
* *
* 微信支付结果回调
*
*/
public class WXPayEntryActivity extends DaogouBaseActivity implements IWXAPIEventHandler
{

private IWXAPI m_WXApi;
private Context context;

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState, R.layout.activity_wxpay_entry, R.layout.title_default);
}

@Override
public void initView()
{
context = this;
m_WXApi = WXAPIFactory.createWXAPI(this, Constants.APP_ID);
m_WXApi.handleIntent(getIntent(), this);
}

@Override
protected void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
setIntent(intent);
m_WXApi.handleIntent(intent, this);
}

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.wxpay_entry, menu);
return true;
}

@Override
public void onReq(BaseReq arg0)
{
}

@Override
public void onResp(BaseResp p_BaseResp)
{
if (p_BaseResp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX)
{
int m_PayResult = 0;
if (p_BaseResp.errCode == -2)
{
ToastUtil.showToast(context, "您取消了支付");
m_PayResult = -2;
}
if (p_BaseResp.errCode == -1)
{
String m_ErroInfor = StringUtils.isEmpty(p_BaseResp.errStr) ? "未返回具体原因" : p_BaseResp.errStr;
ToastUtil.showToast(context, "支付失败:" + m_ErroInfor);
m_PayResult = -1;
}
IPayCallBack m_IPayCallBack = WXPayHelper.getIPayCallBack();
if (m_IPayCallBack != null)
{
m_IPayCallBack.payCallBack(m_PayResult);
}
finishAnimation();
}
}
}

微信支付回调java.lang.IllegalStateException: Already attached

解决:在WXPayEntryActivity.javaonCreate中用了自定义的super.onCreate(savedInstanceState, R.layout.activity_wxpay_entry, R.layout.title_default);改成系统的super.onCreate(savedInstanceState);即可

微信支付:弹起支付页面但是原来的页面走了onPause没有走onStop方法

命令adb shell dumpsys activity | findstr Run查看当前运行的Activity

调微信支付本身页面不走onStop.png

猜测com.tencent.mm/.plugin.wallet_index.ui.OrderHandlerUI是个Activity当成加载的loading(dialog),此时底部的PayActivity还处于可见状态(调起onPause()),之后OrderHandlerUI自身又调起com.tencent.mm/.framework.app.UIPageFragmentActivity这个Activity,使得PayActivity不可见

UIPageFragmentActivityPayActivity不是相邻的(中间隔了一个OrderHandlerUI)所以影响不到PayActivity的生命周期,即不会触发PayActivityonStop方法

App微信支付“支付验证签名失败”

  1. 断点查看,appid等是否需要加解密(即接口返回的appId是否是加密过的),最终调起微信sdk的时候appId是”wx…”开头的(未加密的)

  2. 接口需要返回的字段有(其中sign要和统一下单的时一样签名过;且生成sign的参数顺序按下方的顺序)

    参考链接:https://segmentfault.com/a/1190000017867855

    1
    2
    3
    4
    5
    6
    7
    payBean.setAppId((String) data.get("appid"));
    payBean.setNonceStr((String) data.get("noncestr"));
    payBean.setSign((String) data.get("sign"));
    payBean.setPrepayId((String) data.get("prepayid"));
    payBean.setPartnerId((String) data.get("partnerid"));
    payBean.setTimeStamp((String) data.get("timestamp"));
    payBean.setPackages((String) data.get("package"));//固定值"Sing=WXPay"

微信WAP支付提示”商家参数格式有误,请联系商家解决”

问题:安卓webView内的外部商家开发的链接,点立即购买后调起微信这一步出现“商家参数格式有误,请联系商家解决”

解决:找到微信官方给出的文档

另外参考另一篇解决方案

WebViewshouldOverrideUrlLoading内加上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private class MyWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("https://wx.tenpay.com")) {
//H5微信支付要用,不然说"商家参数格式有误"
Map<String, String> extraHeaders = new HashMap<String, String>();
extraHeaders.put("Referer", "http://yx.dagangcheng.com");//替换成自己的“商户申请H5时提交的授权域名”
view.loadUrl(url, extraHeaders);
return true;
} else if (url.startsWith("weixin://wap/pay?") || url.startsWith("http://weixin/wap/pay") ) {//上面的代码校验通过后会组装成“:weixin://wap/pay?prepayid...”格式的链接来调起微信支付(通过weixin://wap/pay?的协议调起的,其中weixin:与http类似)
try {
startActivity(new Intent("android.intent.action.VIEW", Uri.parse(url)));
} catch (Exception e) {
//做些其他的错误提示,比如以下的
/*new CancelOrOkDialog(H5PayActivity.this, getString(R.string.h5_pay_no_pay_app)) {
@Override
public void ok() {
Intent intent = new Intent(H5PayActivity.this, MainActivity.class);
intent.putExtra(Constants.SELECTTAB, 0);
startActivity(intent);
}
};*/
}
return true;
}
}
}

微信小程序支付,无法返回应用

问题:App调用微信小程序支付,跳到小程序窗口后,部分手机(如vivo)点击“返回应用”无反应

解决:在App内点微信分享后再次小程序支付,可以返回App,所以分析应该是微信没有保存App信息到本地的原因。无法解决。

集成支付宝 sdk 遇到的问题

  1. Duplicate zip entry[classes.jar:com/ut/device/UTDevice.class]

原因:支付 sdk 和友盟 sdk 都有这个文件

解决:支付 sdk 下载个不再 utdevice 的 aar 包

  1. Failed to resolve::alipaySdk-15.6.8-20191021122455-noUtdid:Open File

原因:alipay 项目找不到这个 aar 文件

解决:在项目的根目录 build.gradle中增加(flatDir)如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* allprojects 代码块用来配置工程中所有 modules 都要使用的仓库和依赖
* 但是你应该在每个 module 级的 build 文件中配置 module 独有的依赖。
* 对于一个新工程,Android Studio 默认会让所有 modules 使用 JCenter 仓库和 Google 的 Maven 仓库
*/
allprojects {
repositories {
jcenter()
mavenCentral()
//使用开源中国的maven库代替jcenter()
//阿里云的(速度飞快):http://maven.aliyun.com/nexus/content/groups/public/
// maven {
// url 'http://maven.aliyun.com/nexus/content/groups/public'
// }
maven { url "https://jitpack.io" }
maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
maven {
url 'https://maven.google.com/'
name 'Google'
}

//支付宝需要增加这个
flatDir {
dirs 'libs'
dirs '../AliSDK/libs'
}

}
//全局设定编码与java版本
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}

集成威富通支付遇到的问题

注意:别坚信demo,别坚信文档!!!(豹奔–膳闯项目)

  1. android端,本地不做预下单(不安全)。预下单是后台做的。查询订单也是后台的。android端做的:接收后台提供的token_id,并结合微信appid调起支付的sdk就ok了(注意在注册清单文件中对应页面的Activity里要写上这个微信appid)

  2. 后台的坑:appid要改成sub_appid,demo和文档要结合着来看。

支付宝支付

集成支付宝支付出现{resultStatus=4000, result=, memo=系统繁忙,请稍后再试}

  1. {resultStatus=4000, result=, memo=系统繁忙,请稍后再试}

    如果APPID,PID,TARGET_ID,RSA2_PRIVATE都正确的情况下,看手机是否已安装支付宝应用

  2. {resultStatus=4000, result={“alipay_trade_app_pay_response”:{“code”:”40006”,”msg”:”Insufficient Permissions”,”sub_code”:”isv.insufficient-isv-permissions”,”sub_msg”:”ISV权限不足,建议在开发者中心检查应用是否上线”}}, memo=}

    应用没有上线的原因

推送相关

友盟无法推送问题

排查步骤:

  1. ios和安卓是否都不可以,排查是否是后台问题
  2. 看参数,是否加IP白名单
    2.1. 看gradle中配置的参数、看友盟控制台配置的参数、看后台配置的参数(注意正式线还是测试线)
    2.2. 在友盟控制台模拟发送,(从AS取友盟Token)发送给特定用户
  3. ios证书是否配置了

又一城安卓友盟推送问题排查步骤

  1. 确认安卓和ios是否单端出现问题,如果单端出现问题,那么大概率是APP端的问题,需要各自排查问题;

  2. 单端出现问题的情况下,需要先排查与友盟的对接是否出现问题,先在友盟的后台通过推送测试消息,
    可同时测试独立用户(设备码)和特定用户(别名),如果无法推送成功,那么就是与友盟的对接出现了问题,需要排查参数的配置是否出错;

  3. 排查参数配置时需要排查代码、友盟后台、后台的AppKey、MasterSecret、MessageSecret的参数配置,
    IOS还需要排查证书;其中后台的配置地址为:
    后台顾客端参数配置:域名/weChat/appGenerationSuccess
    后台导购端参数配置:域名/appPackage/guideAppGenerationSuccess
    如果参数配置没有问题,通过友盟后台推送还是失败,那可能是代码中出现错误;

  4. 在双端友盟推送能够成功,并且在确定各端友盟对应应用已配置了IP白名单(IP为域名对外访问对应的IP。比如阿里云给的IP)的情况下
    (注:需要确定友盟控制台已添加IP白名单)在确定白名单已经配置的情况下,
    Android端和IOS端会同时出现问题,那么大概率可能是后台的问题,需要告知后台帮忙排查解决问题

  5. 推送失败信息如下:
    什么是DeviceTokenNotForTopic

    • DeviceToken和当前的bundleID不匹配
      一般是推送证书有问题,需要重新上传证书。
      注:在项目未发布的时候就要针对推送进行测试,及时发现问题并解决,如果发现了推送问题,可参照以上的步骤进行排查
  6. 关于友盟后台推送可以收到,又一城后台推送收不到

    1
    2
    1. 排查参数:查看友盟后台登记的参数、app中的参数、又一城后台登记的第三方参数(注意:**有可能message和secret参数顺序填反**
    2. 排查友盟后台是否有填IP白名单

友盟推送问题排查步骤

1:先排查是Android端会出现问题,还是IOS端会出现问题,如果是单端出现问题(Android端或者IOS端),那么大概率是APP端的问题,需要各自排查问题;

2:单端(Android或者IOS端)出现问题的情况下,需要先排查与友盟的对接是否出现问题,先在友盟的后台通过推送测试消息,可同时测试独立用户(设备码)和特定用户(别名),如果无法推送成功,那么就是与友盟的对接出现了问题,需要排查参数的配置是否出错;

img

3:排查参数配置时需要排查代码、友盟后台、后台的AppKey、MasterSecret、MessageSecret的参数配置,IOS还需要排查证书;其中后台的配置地址为:

后台顾客端参数配置:域名/weChat/appGenerationSuccess

后台导购端参数配置:域名/appPackage/guideAppGenerationSuccess

如果参数配置没有问题,通过友盟后台推送还是失败,那可能是代码中出现错误;

4:在双端友盟推送能够成功,并且在确定各端友盟对应应用已配置了白名单的情况下(注:需要确定友盟已添加白名单),白名单配置如下图:

img

在确定白名单已经配置的情况下,Android端和IOS端会同时出现问题,那么大概率可能是后台的问题,需要告知后台帮忙排查解决问题

5:推送失败信息如下:

img

一般是推送证书有问题,重新上传下。

注:在项目未发布的时候就要针对推送进行测试,及时发现问题并解决,如果发现了推送问题,可参照以上的步骤进行排查

友盟推送错误

友盟注册报错 s=-11,s1=accs bindapp error

排查:

  1. 检查参数、IP白名单、后台填的参数
  2. 代码中注册逻辑要加mPushAgent.setResourcePackageName(packageName);
  3. 有可能是跟阿里百川一起使用,导致的冲突(有可能是so包冲突;有可能是百川失败)

友盟推送 java.lang.IllegalArgumentException: ResClass未初始化,请确保你已经添加了必要的资源。同时确保你在混淆文件中添加了xxx.xxx.xidamen.R$*

问题描述:友盟注册成功,取到正确的别名和token了。用自定义样式推送的消息,报“java.lang.IllegalArgumentException: ResClass未初始化,请确保你已经添加了必要的资源。同时确保你在混淆文件中添加了xxx.xxx.xidamen.R$*”

解决:实际是缺少了.so包,报错中还有报缺少so包的错误。IMLib/libs下缺少了so包

ResClass未初始化,请确保你已经添加了必要的资源

ResClass未初始化,请确保你已经添加了必要的资源…

友盟推送的过程中报这个错误。

排查步骤:

1、友盟控制台查看了参数、app中配置的参数、后台配置的参数,一致。–》app端可以接收消息

2、友盟控制台是否添加了IP白名单

3、是否因为是多渠道而没有在友盟注册中添加packageName,这个packageName需要和AndroidManifest.xml中的包名一致

SBC2.0 最后排查到是第3点的问题

解决:

1、在PushCenter.java中添加参数

ResClass未初始化的解决1.png

2、在调用这个注册的地方添加参数

ResClass未初始化的解决2.png

3、注意这个packageName要与AndroidManifest.xml中的包名一致

ResClass未初始化的解决3.png

ResClass未初始化的解决4.png

后台推送消息,手机接收不到的问题

排查过程:

  1. 先对比ios和安卓看两端是否有同样问题

    1. 如果有同样问题,检查参数配置(友盟控制台、手机端、后台)要一致、友盟控制台的IP白名单是否配置
  2. 因为ios未上架AppStore无法推送,排除与ios对比的可能性,从参数、ip白名单等方面排查

  3. 检查参数(友盟控制台、后台、安卓端)一致,尝试从友盟控制台推送消息,安卓可接收到【得出参数无误的结论】

  4. 检查友盟控制台IP白名单,无误【得出不是IP白名单问题】

  5. 通过后台网页发送推送消息,后台服务抓取参数进行比对,发现友盟注册别名”alias_type”错误

  6. 别名错误的原因是groovy中设置的“\\”导致首字母消失【详解见 https://shenbh.top/gradle知识/Gradle笔记/下的groovy的manifestPlaceholders属性值取值问题 这个笔记】

分享相关

关于微信无法分享问题

前置条件:使用友盟第三方分享(包含了微信)
排查步骤:

  1. 看日志
    1.1 提示参数错误:检查渠道、参数(Android参数、网站登记参数)
    1.2 提示包名错误:检查Android包名、网站登记包名

微信分享一闪即消失,调不起来微信

  • 检查是否使用的是签名包,非签名包不能调试微信分享功能(但若在多渠道中指定在直接运行时的是签名包也是ok的)

  • 检查是否有自定义分享缩略图(thumbData),若有,检查自定义缩略图大小不能超过32kb

  • 检查是否有自定义描述内容(description),若有,检查自定义描述内容长度不能超过1024

  • 关于微信分享的其他限制可查看原码WXMediaMessage.class,截取一段:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    final boolean checkArgs() {
    if(this.getType() != 8 || this.thumbData != null && this.thumbData.length != 0) {
    if(this.thumbData != null && this.thumbData.length > '耀') {
    Log.e("MicroMsg.SDK.WXMediaMessage", "checkArgs fail, thumbData is invalid");
    return false;
    } else if(this.title != null && this.title.length() > 512) {
    Log.e("MicroMsg.SDK.WXMediaMessage", "checkArgs fail, title is invalid");
    return false;
    } else if(this.description != null && this.description.length() > 1024) {
    Log.e("MicroMsg.SDK.WXMediaMessage", "checkArgs fail, description is invalid");
    return false;
    } else if(this.mediaObject == null) {
    Log.e("MicroMsg.SDK.WXMediaMessage", "checkArgs fail, mediaObject is null");
    return false;
    } else {
    return this.mediaObject.checkArgs();
    }
    } else {
    Log.e("MicroMsg.SDK.WXMediaMessage", "checkArgs fail, thumbData should not be null when send emoji");
    return false;
    }
    }

分享SDK7.1.x必须配合友盟基础组件库(v9.2.x版本或更高版本)使用!

问题:分享SDK7.1.x必须配合友盟基础组件库(v9.2.x版本或更高版本)使用!

安卓/提示友盟基础组件库版本太低

原因:原本已经在build.gradlebuildTypes》release中开启了混淆minifyEnabled true,但没有开启zip和无用资源优化,我这边开启了zipAlignEnabledshrinkResources后就报上述的错误

1
2
shrinkResources true
zipAlignEnabled true

解决:

  1. 升级了gradle版本

    • gradle-wrapper.properties中:gradle-6.5-all.zip—>gradle-6.7.1-all.zip
    • 根目录build.gradle中:classpath 'com.android.tools.build:gradle:4.1.1' —> classpath 'com.android.tools.build:gradle:4.2.2'
  2. 给这个moduleproguard-rules.pro配置了免混淆规则

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    -optimizationpasses 5 # 指定代码的压缩级别
    -dontusemixedcaseclassnames # 是否使用大小写混合
    -dontpreverify # 混淆时是否做预校验
    -verbose # 混淆时是否记录日志
    -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 混淆时所采用的算法
    -keep public class * extends android.app.Activity # 保持哪些类不被混淆
    -keep public class * extends android.app.Application # 保持哪些类不被混淆
    -keep public class * extends android.app.Service # 保持哪些类不被混淆
    -keep public class * extends android.content.BroadcastReceiver # 保持哪些类不被混淆
    -keep public class * extends android.content.ContentProvider # 保持哪些类不被混淆
    -keep public class * extends android.app.backup.BackupAgentHelper # 保持哪些类不被混淆
    -keep public class * extends android.preference.Preference # 保持哪些类不被混淆
    -keep public class com.android.vending.licensing.ILicensingService # 保持哪些类不被混淆
    -keepclasseswithmembernames class * { # 保持 native 方法不被混淆
    native <methods>;
    }
    -keepclasseswithmembers class * { # 保持自定义控件类不被混淆
    public <init>(android.content.Context, android.util.AttributeSet);
    }
    -keepclasseswithmembers class * {# 保持自定义控件类不被混淆
    public <init>(android.content.Context, android.util.AttributeSet, int);
    }
    -keepclassmembers class * extends android.app.Activity { # 保持自定义控件类不被混淆
    public void *(android.view.View);
    }
    -keepclassmembers enum * { # 保持枚举 enum 类不被混淆
    public static **[] values();
    public static ** valueOf(java.lang.String);
    }
    -keep class * implements android.os.Parcelable {#保持Parcelable不被混淆
    public static final android.os.Parcelable$Creator *;
    }
    # Explicitly preserve all serialization members. The Serializable interface
    # is only a marker interface, so it wouldn't save them.
    -keep public class * implements java.io.Serializable {*;}
    -keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
    }
    -keepclassmembers class * {
    public <init> (org.json.JSONObject);
    }
    -keep public class com.rcw597.app.R$*{
    public static final int *;
    public static final java.lang.String *;
    }
    #################################################################################################

    #Gson混淆配置
    # removes such information by default, so configure it to keep all of it.
    -keepattributes Signature
    # Gson specific classes
    -keep class sun.misc.Unsafe {*;}
    -keep class com.google.gson.stream.** {*;}
    # Application classes that will be serialized/deserialized over Gson
    -keep class com.google.gson.examples.android.model.** {*;}
    -dontwarn com.google.**
    -keep class com.google.gson.** {*;}
    -keep class com.google.protobuf.** {*;}
    #这句非常重要,主要是滤掉 com.demo.demo.bean包下的所有.class文件不进行混淆编译,com.demo.demo是你的包名
    -keep class com.rcw597.app.net.params.** {*;}
    -keep class com.rcw597.app.im.bean.** {*;}
    -keep class com.rcw597.app.im.bean.params.** {*;}

    #################################################################################################

    #IM云信混淆配置
    -dontwarn com.netease.**
    -keep class com.netease.** {*;}
    -keep class com.lykevin.neteaseim.** {*;}
    #如果你使用全文检索插件,需要加入
    -dontwarn org.apache.lucene.**
    -keep class org.apache.lucene.** {*;}
    -keep class net.sqlcipher.** {*;}
    -dontwarn com.xiaomi.push.**
    -keep class com.xiaomi.** {*;}
    -ignorewarnings
    -keepattributes *Annotation*
    -keepattributes Exceptions
    -keepattributes InnerClasses
    -keepattributes Signature
    -keepattributes SourceFile,LineNumberTable
    -keep class com.hianalytics.android.**{*;}
    -keep class com.huawei.updatesdk.**{*;}
    -keep class com.huawei.hms.**{*;}
    -dontwarn com.vivo.push.**
    -keep class com.vivo.push.**{*; }
    -keep class com.vivo.vms.**{*; }
    -keep class com.netease.nimlib.mixpush.vivo.VivoPush* {*;}
    -keep class com.netease.nimlib.mixpush.vivo.VivoPushReceiver{*;}
    -dontwarn com.meizu.cloud.**
    -keep class com.meizu.cloud.** {*;}
    -keep public class * extends android.app.Service
    -keep class com.heytap.msp.** { *;}
    #################################################################################################

    #极验
    -dontwarn com.geetest.sdk.**
    -keep class com.geetest.sdk.**{*;}
    #################################################################################################

    #友盟SDK混淆配置
    -dontshrink
    -dontoptimize
    -dontwarn com.google.android.maps.**
    -dontwarn android.webkit.WebView
    -dontwarn com.umeng.**
    -dontwarn com.tencent.weibo.sdk.**
    -dontwarn com.facebook.**
    -keep public class javax.**
    -keep public class android.webkit.**
    -dontwarn android.support.v4.**
    -keep enum com.facebook.**
    -keepattributes Exceptions,InnerClasses,Signature
    -keepattributes *Annotation*
    -keepattributes SourceFile,LineNumberTable
    -keep public interface com.facebook.**
    -keep public interface com.tencent.**
    -keep public interface com.umeng.socialize.**
    -keep public interface com.umeng.socialize.sensor.**
    -keep public interface com.umeng.scrshot.**
    -keep public class com.umeng.socialize.* {*;}
    -keep class com.facebook.**
    -keep class com.facebook.** { *; }
    -keep class com.umeng.scrshot.**
    -keep public class com.tencent.** {*;}
    -keep class com.umeng.socialize.sensor.**
    -keep class com.umeng.socialize.handler.**
    -keep class com.umeng.socialize.handler.*
    -keep class com.umeng.weixin.handler.**
    -keep class com.umeng.weixin.handler.*
    -keep class com.umeng.qq.handler.**
    -keep class com.umeng.qq.handler.*
    -keep class UMMoreHandler{*;}
    -keep class com.tencent.mm.sdk.modelmsg.WXMediaMessage {*;}
    -keep class com.tencent.mm.sdk.modelmsg.** implements com.tencent.mm.sdk.modelmsg.WXMediaMessage$IMediaObject {*;}
    -keep class im.yixin.sdk.api.YXMessage {*;}
    -keep class im.yixin.sdk.api.** implements im.yixin.sdk.api.YXMessage$YXMessageData{*;}
    -keep class com.tencent.mm.sdk.** {
    *;
    }
    -keep class com.tencent.mm.opensdk.** {
    *;
    }
    -keep class com.tencent.wxop.** {
    *;
    }
    -keep class com.tencent.mm.sdk.** {
    *;
    }
    -keep class com.twitter.** { *; }
    -keep class com.tencent.** {*;}
    -dontwarn com.tencent.**
    -keep class com.kakao.** {*;}
    -dontwarn com.kakao.**
    -keep public class com.umeng.com.umeng.soexample.R$*{
    public static final int *;
    }
    -keep public class com.linkedin.android.mobilesdk.R$*{
    public static final int *;
    }
    -keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
    }
    -keep class com.tencent.open.TDialog$*
    -keep class com.tencent.open.TDialog$* {*;}
    -keep class com.tencent.open.PKDialog
    -keep class com.tencent.open.PKDialog {*;}
    -keep class com.tencent.open.PKDialog$*
    -keep class com.tencent.open.PKDialog$* {*;}
    -keep class com.umeng.socialize.impl.ImageImpl {*;}
    -keep class com.sina.** {*;}
    -dontwarn com.sina.**
    -keep class com.alipay.share.sdk.** {
    *;
    }
    -keepnames class * implements android.os.Parcelable {
    public static final ** CREATOR;
    }
    -keep class com.linkedin.** { *; }
    -keep class com.android.dingtalk.share.ddsharemodule.** { *; }
    -keepattributes Signature
    -keep class com.umeng.** {*;}
    -keep class com.uc.** {*;}
    -keepclassmembers class * {
    public <init> (org.json.JSONObject);
    }
    -keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
    }
    -keep class com.zui.** {*;}
    -keep class com.miui.** {*;}
    -keep class com.heytap.** {*;}
    -keep class a.** {*;}
    -keep class com.vivo.** {*;}
    -keep public class com.xm597.app.R$*{
    public static final int *;
    }
    #################################################################################################
    #高德地图混淆配置
    -keep class com.amap.api.maps.**{*;}
    -keep class com.autonavi.**{*;}
    -keep class com.amap.api.trace.**{*;}
    -keep class com.amap.api.location.**{*;}
    -keep class com.amap.api.fence.**{*;}
    -keep class com.autonavi.aps.amapapi.model.**{*;}
    -keep class com.amap.api.services.**{*;}
    -keep class com.amap.api.navi.**{*;}
    -keep class com.autonavi.**{*;}
    #################################################################################################

    #百度地图混淆配置
    -keep class com.baidu.** {*;}
    -keep class com.baidu.vi.** {*;}
    -keep class mapsdkvi.com.** {*;}
    -keep class vi.com.** {*;}
    -dontwarn com.baidu.**
    #################################################################################################

    #EventBus混淆配置
    -keepattributes *Annotation*
    -keepclassmembers class * {
    @org.greenrobot.eventbus.Subscribe <methods>;
    }
    -keep enum org.greenrobot.eventbus.ThreadMode { *; }
    # And if you use AsyncExecutor:
    -keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
    }
    #################################################################################################

    #Glide混淆配置
    -keep public class * implements com.bumptech.glide.module.GlideModule
    -keep class * extends com.bumptech.glide.module.AppGlideModule {
    <init>(...);
    }
    -keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
    **[] $VALUES;
    public *;
    }
    -keep class com.bumptech.glide.load.data.ParcelFileDescriptorRewinder$InternalRewinder {
    *** rewind();
    }
    #################################################################################################

    #Retrofit混淆配置
    # Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
    # EnclosingMethod is required to use InnerClasses.
    -keepattributes Signature, InnerClasses, EnclosingMethod
    # Retrofit does reflection on method and parameter annotations.
    -keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
    # Retain service method parameters when optimizing.
    -keepclassmembers,allowshrinking,allowobfuscation interface * {
    @retrofit2.http.* <methods>;
    }
    # Ignore annotation used for build tooling.
    -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
    # Ignore JSR 305 annotations for embedding nullability information.
    -dontwarn javax.annotation.**
    # Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
    -dontwarn kotlin.Unit
    # Top-level functions that can only be used by Kotlin.
    -dontwarn retrofit2.KotlinExtensions
    -dontwarn retrofit2.KotlinExtensions$*
    # With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
    # and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
    -if interface * { @retrofit2.http.* <methods>; }
    -keep,allowobfuscation interface <1>
    #################################################################################################

    #极光推送混淆配置
    -dontoptimize
    -dontpreverify
    -dontwarn cn.jpush.**
    -keep class cn.jpush.** { *; }
    -keep class * extends cn.jpush.android.helpers.JPushMessageReceiver { *; }
    -dontwarn cn.jiguang.**
    -keep class cn.jiguang.** { *; }
    -dontwarn cn.com.chinatelecom.**
    -keep class cn.com.chinatelecom.** { *; }
    -dontwarn com.ct.**
    -keep class com.ct.** { *; }
    -dontwarn a.a.**
    -keep class a.a.** { *; }
    -dontwarn com.cmic.**
    -keep class com.cmic.** { *; }
    -dontwarn com.unicom.**
    -keep class com.unicom.** { *; }
    -dontwarn com.sdk.**
    -keep class com.sdk.** { *; }
    -keep public class com.sina.** {
    *;
    }
    #################################################################################################
    #OAID
    -keep class XI.CA.XI.**{*;}
    -keep class XI.K0.XI.**{*;}
    -keep class XI.XI.K0.**{*;}
    -keep class XI.vs.K0.**{*;}
    -keep class XI.xo.XI.XI.**{*;}
    -keep class com.asus.msa.SupplementaryDID.**{*;}
    -keep class com.asus.msa.sdid.**{*;}
    -keep class com.bun.lib.**{*;}
    -keep class com.bun.miitmdid.**{*;}
    -keep class com.huawei.hms.ads.identifier.**{*;}
    -keep class com.samsung.android.deviceidservice.**{*;}
    -keep class org.json.**{*;}
    -keep public class com.netease.nis.sdkwrapper.Utils {public <methods>;}

IM即时通讯

关于百川IM在安卓8不能调起问题(阿里已经不维护了)

现象:PMS顾客端IM聊天在安卓8不能调起,会报登录超时。安卓8以下的正常。导购端的都正常(包括在安卓8)
排查步骤:

  1. 排查是否是tcmService进程没有开启(在AS的logcat的标题栏上看的)
  2. 排查gradle中的targetVersion的值,IM不支持太高的版本(解决:降低targetVersion)
    原因:辣苹果顾客端targetVersion设置成27,而云旺不支持这么高的版本。
    解决:降低targetVersion

百川在安卓8以上无法推送问题

现象:导购端退到后台,顾客端发送消息。在安卓6上导购端状态栏有新消息提示,在安卓8以上没有新消息提示

解决:【暂不解决,百川都不维护了,看看客户是否换成融云】

地图&定位

高德地图相关

key、定位相关

  1. 如果误删高德地图控制台申请的应用和key
    可以进行添加新的key,同时要更改代码注册清单文件中对应的apikey的值
  2. 同一个应用可以申请多个key,不过注册清单文件中的apikey只能一个,所以限制了只能有一个生效
    (当然如果是两个编辑器进行编译的话,那么可以同时用到两个)
  3. 高德地图控制台申请应用名,即使删除了也不能重新用这个名字
  4. 注意:在安卓6.0以上的sdk中,权限是要写在代码中,在注册清单文件中写的无效。(只能在手机的设置里信任此应用方可),否则会报“缺少定位权限”的异常
  5. 删除了高德地图控制台申请的key,应用中会报“KEY鉴权失败”的异常

aMap = mapView.getMap();一直报 NullPointException

解决:在app.build中添加

1
2
3
4
5
6
7
8
sourceSets{
main{
jniLibs.srcDirs = ['libs']
}
instrumentTest.setRoot('tests')
debug.setRoot('build-types/debug')
release.setRoot('build-types/release')
}

完整代码

app.build

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
apply plugin: 'com.android.application'

task clean(type:Exec){
ext.lockhunter = '\"C:\\LockHunter.exe\"'
def buildDir = file(new File("build"))
commandLine 'cmd' , "$lockhunter", '/delete', '/silent',buildDir
}

android {
compileSdkVersion 23
buildToolsVersion '23.0.3'
defaultConfig {
applicationId "com.xxx"
minSdkVersion 17
targetSdkVersion 19
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
productFlavors {
}

sourceSets{
main{
jniLibs.srcDirs = ['libs']
}

instrumentTest.setRoot('tests')
debug.setRoot('build-types/debug')
release.setRoot('build-types/release')
}
}

dependencies {
compile fileTree(includes: ['*.jar'], dir: 'libs')
compile files('libs/fastjson-1.2.4.jar')
compile files('libs/nineoldandroids-2.4.0.jar')
compile files('libs/okhttp-3.4.1.jar')
compile files('libs/okio-1.9.0.jar')
compile files('libs/universal-image-loader-1.9.2.jar')
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.flipboard:bottomsheet-core:1.5.1'
compile files('libs/AMap_Location_V3.5.0_20170731.jar')
compile files('libs/AMap_Search_V5.2.1_20170630.jar')
compile files('libs/Android_Map3D_SDK_V5.2.1_20170630.jar')
compile files('libs/Volley.jar')
}

AndroidManifest.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xxx"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="19" />

<!-- 地图包、搜索包需要的基础权限 -->
<!-- 允许程序打开网络套接字 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 允许程序设置内置sd卡的写权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 允许程序获取网络状态 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 允许程序访问WiFi网络信息 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 允许程序读写手机状态和身份 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 允许程序访问CellID或WiFi热点来获取粗略的位置 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!--用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!--用于访问GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!--用于读取手机当前的状态-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!--用于申请调用A-GPS模块-->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS" />

<application
android:name="com.xxx.MyApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="b5eae3aeaae6a5439226e657ac997d08" />

<!--主要界面-->
<activity
android:name="com.xxx.personal.locate.MarkerAnimationActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<!-- 定位需要的服务 使用2.0的定位需要加上这个 -->
<service android:name="com.amap.api.location.APSService" />
</application>

</manifest>

MarkerAnimationActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
package com.xxx.personal.locate;


import android.app.Activity;
import android.content.Context;
import android.graphics.Point;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.Button;

import com.amap.api.maps.AMap;
import com.amap.api.maps.MapView;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.animation.Animation;
import com.amap.api.maps.model.animation.ScaleAnimation;
import com.amap.api.maps.model.animation.TranslateAnimation;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.geocoder.GeocodeResult;
import com.amap.api.services.geocoder.GeocodeSearch;
import com.amap.api.services.geocoder.RegeocodeAddress;
import com.amap.api.services.geocoder.RegeocodeQuery;
import com.amap.api.services.geocoder.RegeocodeResult;
import com.xxx.MyBaseActivity;
import com.xxx.R;

/**
* AMapV2地图中简单介绍一些Marker的用法.
* Marker动画功能介绍
*/
public class MarkerAnimationActivity extends MyBaseActivity implements View.OnClickListener,AMap.OnCameraChangeListener,GeocodeSearch.OnGeocodeSearchListener {
private MarkerOptions markerOption;
private AMap aMap;
private MapView mapView;
private LatLng latlng = new LatLng(39.761, 116.434);

Marker screenMarker = null;
Marker growMarker = null;

GeocodeSearch geocodeSearch;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.marker_animation_activity);
/*
* 设置离线地图存储目录,在下载离线地图或初始化地图设置; 使用过程中可自行设置, 若自行设置了离线地图存储的路径,
* 则需要在离线地图下载和使用地图页面都进行路径设置
*/
// Demo中为了其他界面可以使用下载的离线地图,使用默认位置存储,屏蔽了自定义设置
// MapsInitializer.sdcardDir =OffLineMapUtils.getSdCacheDir(this);
mapView = (MapView) findViewById(R.id.map);
mapView.onCreate(savedInstanceState); // 此方法必须重写
init();


}

/**
* 初始化AMap对象
*/
private void init() {
Button clearMap = (Button) findViewById(R.id.growMarker);
clearMap.setOnClickListener(this);
Button resetMap = (Button) findViewById(R.id.jumpMarker);
resetMap.setOnClickListener(this);
if (aMap == null) {
aMap = mapView.getMap();
}
aMap.setOnMapLoadedListener(new AMap.OnMapLoadedListener() {
@Override
public void onMapLoaded() {
addMarkersToMap();
}
});

// 设置可视范围变化时的回调的接口方法
aMap.setOnCameraChangeListener(new AMap.OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition position) {

}

@Override
public void onCameraChangeFinish(CameraPosition postion) {
//屏幕中心的Marker跳动
startJumpAnimation();
}
});



aMap.setOnCameraChangeListener(this);
geocodeSearch = new GeocodeSearch(this);
geocodeSearch.setOnGeocodeSearchListener(this);
}

/**
* 方法必须重写
*/
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}

/**
* 方法必须重写
*/
@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}

/**
* 方法必须重写
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}

/**
* 方法必须重写
*/
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}

/**
* 在地图上添加marker
*/
private void addMarkersToMap() {

addMarkerInScreenCenter();

addGrowMarker();
}


/**
* 在屏幕中心添加一个Marker
*/
private void addMarkerInScreenCenter() {
LatLng latLng = aMap.getCameraPosition().target;
Point screenPosition = aMap.getProjection().toScreenLocation(latLng);
screenMarker = aMap.addMarker(new MarkerOptions()
.anchor(0.5f,0.5f)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.purple_pin)));
//设置Marker在屏幕上,不跟随地图移动
screenMarker.setPositionByPixels(screenPosition.x,screenPosition.y);

}

/**
* 添加一个从地上生长的Marker
*/
public void addGrowMarker() {
if(growMarker == null) {
MarkerOptions markerOptions = new MarkerOptions().icon(BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_AZURE))
.position(latlng);
growMarker = aMap.addMarker(markerOptions);
}

startGrowAnimation();
}

/**
* 地上生长的Marker
*/
private void startGrowAnimation() {
if(growMarker != null) {
Animation animation = new ScaleAnimation(0,1,0,1);
animation.setInterpolator(new LinearInterpolator());
//整个移动所需要的时间
animation.setDuration(1000);
//设置动画
growMarker.setAnimation(animation);
//开始动画
growMarker.startAnimation();
}
}

/**
* 屏幕中心marker 跳动
*/
public void startJumpAnimation() {

if (screenMarker != null ) {
//根据屏幕距离计算需要移动的目标点
final LatLng latLng = screenMarker.getPosition();
Point point = aMap.getProjection().toScreenLocation(latLng);
point.y -= dip2px(this,125);
LatLng target = aMap.getProjection()
.fromScreenLocation(point);
//使用TranslateAnimation,填写一个需要移动的目标点
Animation animation = new TranslateAnimation(target);
animation.setInterpolator(new Interpolator() {
@Override
public float getInterpolation(float input) {
// 模拟重加速度的interpolator
if(input <= 0.5) {
return (float) (0.5f - 2 * (0.5 - input) * (0.5 - input));
} else {
return (float) (0.5f - Math.sqrt((input - 0.5f)*(1.5f - input)));
}
}
});
//整个移动所需要的时间
animation.setDuration(600);
//设置动画
screenMarker.setAnimation(animation);
//开始动画
screenMarker.startAnimation();

} else {
Log.e("amap","screenMarker is null");
}
}

//dip和px转换
private static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
/*
* 从地上生长的Marker
*/
case R.id.growMarker:
startGrowAnimation();
break;
/*
* marker 跳动动画
*/
case R.id.jumpMarker:
startJumpAnimation();
break;
default:
break;
}
}

@Override
public void onCameraChange(CameraPosition cameraPosition) {
LatLng target = cameraPosition.target;
// System.out.println(target.latitude+"---"+target.longitude);
getAddressByLatlng(target);
}

@Override
public void onCameraChangeFinish(CameraPosition cameraPosition) {

}


@Override
public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int i) {

if (i == 0) {
if (regeocodeResult != null && regeocodeResult.getRegeocodeAddress() != null) {
RegeocodeAddress regeocodeAddress = regeocodeResult.getRegeocodeAddress();
String formatAddress = regeocodeAddress.getFormatAddress();
String simpleAddress = formatAddress.substring(9);
System.out.println("查询经纬度对应详细地址:\n" + simpleAddress);
} else {
// NToast.shortToast(AMAPLocationActivity.this, "没有搜索到结果");
System.out.println();
}
} else {
// NToast.shortToast(AMAPLocationActivity.this, "搜索失败,请检查网络");
System.out.println();
}
}

@Override
public void onGeocodeSearched(GeocodeResult geocodeResult, int i) {

}

private void getAddressByLatlng(LatLng latLng) {
//逆地理编码查询条件:逆地理编码查询的地理坐标点、查询范围、坐标类型。
LatLonPoint latLonPoint = new LatLonPoint(latLng.latitude, latLng.longitude);
RegeocodeQuery query = new RegeocodeQuery(latLonPoint, 500f, GeocodeSearch.AMAP);
//异步查询
geocodeSearch.getFromLocationAsyn(query);
}
}

选择模糊定位的时候位置不可用

解决:关闭掉持续定位 option.setOnceLocation(false);

1
2
3
4
5
6
7
8
9
10
11
12
AMapLocationClient locationClient = new AMapLocationClient(context);  
AMapLocationClientOption option = new AMapLocationClientOption();
option.setOnceLocation(false);
option.setOnceLocationLatest(false);
option.setInterval(interval);
locationClient.setLocationOption(option);
locationClient.setLocationListener(aMapLocation -> {
if (listener != null) {
listener.onLocationChanged(aMapLocation);
}
});
locationClient.startLocation();

如果需要持续定位的场景,那么选择模糊定位的判断可以从已获取到的权限入手

百度定位移到项目中不可用

  1. 检查权限;检查是不是重新申请了key(一个包名对应一个key);
  2. 用百度定位的时候要用getApplicationContext(),因为当前的context被销毁了虽然不报错,但是也不提供定位。

Bugly相关

Bugly 无法上报的问题

  • 可能是加了自己的异常捕获导致的
    解决:去掉自己的异常捕获

GreenDao的问题

  • 复合主键

在数据库表多对多的关系中,中间表使用的是复合主键,在GreenDao中复合主键的表达方式是:

1
2
3
4
5
6
// 复合主键
@Entity(indexes = { @Index(value = "studentId, teacherId", unique = true)})
public class TeacherStudent{
private long studentId;
private long teacherId;
}
  • 多对多关系:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Entity
public class Student{
@Id
private long id;
@ToMany
@JoinEntity(entity = TeacherStudent.class, sourceProperty = "studentId", targetProperty = "teacherId")
private List<Teacher> teachers;
}
@Entity
public class Teacher{
@Id
private long id;
@ToMany
@JoinEntity(entity = TeacherStudent.class, sourceProperty = "teacherId", targetProperty = "studentId")
private List<Student> students;
}
  • 查询结果出现重复项:
    当查询结果出现重复项的时候,使用函数.distinct()取消所有的重复项。
  • 如果GreenDao报错时,首先是将自动生成的代码段删除然后重新编译

MVPArms失效问题

在AS4.1以上没有templates的issue

https://github.com/JessYanCoding/MVPArmsTemplate/issues/26

https://www.bigademo.com/2021/01/20/AndroidStudio%204.1%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A8%A1/index.html

查看 AndroidStudio-代码快捷键&模板 的AS4.1上写模板【新方式】

其他功能

App 跳转微信小程序失败

安卓端调用微信小程序支付功能时候,一直失败,微信的app也调不起来。

对比了微信开放平台上的安卓应用的的appId 值,配置的包名、以及应用签名信息,确认都完全正确。微信的分享也正常,但是就是调不起来小程序,微信sdk给的错误信息如下:

1
2
3
4
5
6
7
D/MicroMsg.PaySdk.WXFactory: createWXAPI, appId = wx8c3653f8c376e8c4, checkSignature = false

11645-11645/app.laidianyi.weilanshidai D/MicroMsg.SDK.WXApiImplV10: <init>, appId = wx8c3653f8c376e8c4, checkSignature = false

11645-11645/app.laidianyi.weilanshidai D/MicroMsg.SDK.WXMsgImplComm: ignore wechat app signature validation

11645-11645/app.laidianyi.weilanshidai I/MicroMsg.SDK.WXApiImplV10: sendReq, req type = 19

经过一系列尝试,原来是个人微信账号没有预览权限导致,换个有预览权限的微信账号,安卓app就能正常调起微信小程序了
备注:iOS 没有这个问题,只有安卓会出现这个问题