技术问题
最近更新:2022-11-15

技术问题

日志显示初始化失败,appkey、签名、应用包名无效该如何处理?

  • 检查工程配置的 appkey 与极光控制台上[应用设置]-[应用信息]上显示的是否一致。
  • 检查工程配置的应用包名、Bundle ID 与极光控制台上[极光认证]-[认证设置]-[集成设置]中显示的是否一致。
  • 安装 应用签名获取工具,将获取的 Android 应用签名与极光控制台上[极光认证]-[认证设置]-[集成设置]中显示的是否一致。

一键登录返回 6004 错误码,该如何处理?

问题场景:

  • 需要从授权页面,跳转到其他自定义页面(如验证码登录页面)后,重新返回授权页面。重新返回授权页面的时候,再次调用请求授权一键登录接口,此时会返回 6004 错误码。

问题分析:

  • 出现该问题是由于在授权页还没有关闭的情况下,再次调用请求授权一键登录接口。

解决方案(选其一):

  1. 在不关闭授权页面的情况下,从自定义页面返回授权页面时,不需要再次调用一键登录接口,直接关闭当前页面即可回到授权页面。

  2. 如果必须要关闭授权页面,需要在跳转自定义页面之前,调用 dismissLogin 接口关闭授权页面,之后再在自定义页面重新调用请求授权一键登录接口。

调用 loginTokenVerify API,返回 9021/9020 该如何处理?

  • 检查客户端和后台配置的 appkey 是否一致。

  • 若 appkey 配置一致,检查 loginToken 是否正确,注意 loginToken 不是号码认证的 token。loginToken 获取方法参考:Android SDK 拉起授权页面iOS SDK 拉起授权页面

  • 若后台使用 PHP 开发,请确认后台传的 loginToken 与客户端获取的 loginToken 是否一致,若客户端传到后台的 loginToken 的值有 “+”,PHP 会默认把 “+” 替换成空格,导致 loginToken 校验失败。

  • 号码认证和一键登录的 token 具有 使用有效期,且每个 token 只能使用一次。

  • 生成秘钥对的时候不要设置证书密码,密钥格式设置为 PKCS#8 。

RSA 私钥解密失败,该如何处理?

H5 号码认证返回 2002 错误码,该如何处理?

  • 生产上有 https 访问的,https 请求跨域,会导致上报的 referer 为空,请在 head 中添加代码:<meta content="always" name="referrer">

  • 如果有强转 https 的设置,需要去掉此设置。

如何解决状态栏白底白字问题?

部分手机出现状态栏白底白字的情况,可以用以下代码解决:

// 在application onCreate方法中调用如下代码 @Override public void onCreate() { super.onCreate(); registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { @Override public void onActivityCreated(@NonNull Activity activity , @Nullable Bundle savedInstanceState) { String activityName = activity.getClass().getSimpleName(); if ("GenLoginAuthActivity".equals(activityName) || "CtLoginActivity".equals(activityName) || "LoginAuthActivity".equals(activityName)) { if (Build.VERSION.SDK_INT >= 21) { // 修改状态栏字体颜色,用AndroidX官方兼容API WindowInsetsControllerCompat wic = WindowCompat .getInsetsController(activity.getWindow(), activity.getWindow().getDecorView()); // true表示Light Mode,状态栏字体呈黑色,反之呈白色 wic.setAppearanceLightStatusBars(true); } } } ...... }); }
          // 在application onCreate方法中调用如下代码
@Override
public void onCreate() {
    super.onCreate();
    
    registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
        @Override
        public void onActivityCreated(@NonNull Activity activity
                                      , @Nullable Bundle savedInstanceState) {
            String activityName = activity.getClass().getSimpleName();
            if ("GenLoginAuthActivity".equals(activityName)
                    || "CtLoginActivity".equals(activityName)
                    || "LoginAuthActivity".equals(activityName)) {
                if (Build.VERSION.SDK_INT >= 21) {
                    // 修改状态栏字体颜色,用AndroidX官方兼容API
                    WindowInsetsControllerCompat wic = WindowCompat
                        .getInsetsController(activity.getWindow(), 
                                             activity.getWindow().getDecorView());
                        // true表示Light Mode,状态栏字体呈黑色,反之呈白色
                        wic.setAppearanceLightStatusBars(true);
                }
            }
        }

        ......
    });
}

        
此代码块在浮窗中显示

如何解决 UI 资源加载异常?

问题描述:

  • UI 资源加载异常,debug 模式下正常,release 模式下异常。

问题分析:

  • 使用自动集成,所有资源文件正常导入。
  • 用户开启了混淆,并且防混淆代码配置正常。
  • 猜测是 shrinkResources 设置为 true 导致资源被混淆,将 shrinkResources 设置为 false 后报错问题得到解决。

解决方法(选其一):

  1. 将 shrinkResources 设置为 false。
  2. 在 res 下创建 raw 文件夹,添加 keep.xml 文件,需要对以下资源配置防混淆:
@drawable/umcsdk*,@drawable/jverify*,@anim/umcsdk*
          @drawable/umcsdk*,@drawable/jverify*,@anim/umcsdk*

        
此代码块在浮窗中显示

登录页面中使用的图片资源都需要添加防混淆。例如通过 setLogoImgPath 设置了 logo 图片,对应的图片在开启资源混淆时也需要添加防混淆配置。 比如上图中设置的图标是 ic_icon,最终的防混淆配置如下:

<?xml version="1.0" encoding="UTF-8"?> <resources xmlns:tools="http://schemas.android.com/tools" tools:keep="@drawable/umcsdk*,@drawable/jverify*,@anim/umcsdk*,@drawable/ic_icon" />
          <?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" 
    tools:keep="@drawable/umcsdk*,@drawable/jverify*,@anim/umcsdk*,@drawable/ic_icon" />

        
此代码块在浮窗中显示

如何在一键登录授权页上进行弹窗处理?

场景描述:
在一键登录授权页上,添加自定义控件,通过点击自定义控件进行弹窗,展现形式如下图:

解决方案:
由于此授权页是运营商直接返回的,开发者无法直接拿到授权页对应的 activity,故无法直接在授权页上弹窗,解决方案如下:

  • 通过 Application 的 registerActivityLifecycleCallbacks 回调,监听所有的 activity(详情可百度如何监听),通过匹配运营商的 activity 来获取授权页 activity(context)。
  • 点击自定义控件时,在顶层 activity 上进行弹窗,详情如下:
// 在application onCreate方法中调用如下代码 public class MyApplication extends Application { private static WeakReference<Activity> TOP_ACTIVITY; public static WeakReference<Activity> getTopActivity() { return TOP_ACTIVITY; } @Override public void onCreate() { super.onCreate(); registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { @Override public void onActivityCreated(@NonNull Activity activity , @Nullable Bundle savedInstanceState) { TOP_ACTIVITY = new WeakReference<>(activity); } ...... }); } }
          // 在application onCreate方法中调用如下代码
public class MyApplication extends Application {
    private static WeakReference<Activity> TOP_ACTIVITY;
    
    public static WeakReference<Activity> getTopActivity() {
        return TOP_ACTIVITY;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(@NonNull Activity activity
                                          , @Nullable Bundle savedInstanceState) {
                TOP_ACTIVITY = new WeakReference<>(activity);
            }
    
            ......
        });
    }
}

        
此代码块在浮窗中显示
public class MainActivity extends AppCompatActivity { List<View> views; boolean isChecked = false; LoginSettings settings = new LoginSettings(); settings.setAuthPageEventListener(new AuthPageEventListener() { @Override public void onEvent(int i, String s) { Log.i("jiguang-log", "[login] code = " + i + " result = " + s); if (i == 2) { //进入登录页后添加监听 isChecked = false; addDialogIfUnCheck(); } else if (i == 6) { //用户勾选后移除监听 isChecked = true; removeDialogIfChecked(); } else if (i == 7) { //用户取消勾选后添加监听 isChecked = false; addDialogIfUnCheck(); } } }); / * 客户未勾选隐私条款需要添加监听 */ private void addDialogIfUnCheck() { if (isChecked) return; new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { if (views != null) views.clear(); views = getAllChildViews(); views.get(13).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Activity activity = MyApplication.getTopActivity().get(); dialog(activity); } }); ViewGroup vp = (RelativeLayout) views.get(12); int high = vp.getHeight(); int width = vp.getWidth(); ((TextView) views.get(13)).setWidth(width); ((TextView) views.get(13)).setHeight(high); ((TextView) views.get(13)).setGravity(Gravity.CENTER); views.get(13).setClickable(true); views.get(13).setFocusable(true); views.get(13).setEnabled(true); } }); } / * 客户勾选隐私条款后需要移除监听 */ private void removeDialogIfChecked() { if (!isChecked) return; new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { views.get(13).setOnClickListener(null); views.get(13).setClickable(false); views.get(13).setFocusable(false); views.get(13).setEnabled(false); } }); } / * 获取该activity所有view */ public List<View> getAllChildViews() { Activity activity = MyApplication.getTopActivity().get(); View view = activity.getWindow().getDecorView(); return getAllChildViews(view); } private List<View> getAllChildViews(View view) { List<View> allchildren = new ArrayList<View>(); if (view instanceof ViewGroup) { ViewGroup vp = (ViewGroup) view; for (int i = 0; i < vp.getChildCount(); i++) { View viewchild = vp.getChildAt(i); allchildren.add(viewchild); allchildren.addAll(getAllChildViews(viewchild)); } } return allchildren; } private void dialog(Context context) { AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context); alertDialogBuilder.setMessage("请同意页面底部隐私条款"); AlertDialog alertDialog = alertDialogBuilder.create(); alertDialog.show(); } }
          public class MainActivity extends AppCompatActivity {
    List<View> views;
    boolean isChecked = false;
    
    LoginSettings settings = new LoginSettings();
    settings.setAuthPageEventListener(new AuthPageEventListener() {
        @Override
        public void onEvent(int i, String s) {
            Log.i("jiguang-log", "[login] code = " + i + " result = " + s);
            if (i == 2) { //进入登录页后添加监听
                isChecked = false;
                addDialogIfUnCheck();
            } else if (i == 6) { //用户勾选后移除监听
                isChecked = true;
                removeDialogIfChecked();
            } else if (i == 7) { //用户取消勾选后添加监听
                isChecked = false;
                addDialogIfUnCheck();
            }
        }
    });

    /
     * 客户未勾选隐私条款需要添加监听
     */
    private void addDialogIfUnCheck() {
        if (isChecked) return;
    
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                if (views != null) views.clear();
                views = getAllChildViews();
                views.get(13).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Activity activity = MyApplication.getTopActivity().get();
                        dialog(activity);
                    }
                });
    
                ViewGroup vp = (RelativeLayout) views.get(12);
                int high = vp.getHeight();
                int width = vp.getWidth();
                ((TextView) views.get(13)).setWidth(width);
                ((TextView) views.get(13)).setHeight(high);
                ((TextView) views.get(13)).setGravity(Gravity.CENTER);
    
                views.get(13).setClickable(true);
                views.get(13).setFocusable(true);
                views.get(13).setEnabled(true);
            }
        });
    }

    /
     * 客户勾选隐私条款后需要移除监听
     */
    private void removeDialogIfChecked() {
        if (!isChecked) return;
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                views.get(13).setOnClickListener(null);
                views.get(13).setClickable(false);
                views.get(13).setFocusable(false);
                views.get(13).setEnabled(false);
            }
        });
    }

    /
     * 获取该activity所有view
     */
    public List<View> getAllChildViews() {
        Activity activity = MyApplication.getTopActivity().get();
        View view = activity.getWindow().getDecorView();
        return getAllChildViews(view);
    }
    
    private List<View> getAllChildViews(View view) {
        List<View> allchildren = new ArrayList<View>();
        if (view instanceof ViewGroup) {
            ViewGroup vp = (ViewGroup) view;
            for (int i = 0; i < vp.getChildCount(); i++) {
                View viewchild = vp.getChildAt(i);
                allchildren.add(viewchild);
                    allchildren.addAll(getAllChildViews(viewchild));
            }
        }
        return allchildren;
    }

    private void dialog(Context context) {
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
        alertDialogBuilder.setMessage("请同意页面底部隐私条款");
        AlertDialog alertDialog = alertDialogBuilder.create();
        alertDialog.show();
    }
}

        
此代码块在浮窗中显示
文档内容是否对您有帮助?

Copyright 2011-2022, jiguang.cn, All Rights Reserved. 粤ICP备12056275号-13 深圳市和讯华谷信息技术有限公司

在文档中心打开