Android阿里云推送离线通知集成踩坑之路

2023-11-04

  最近因为公司后台服务器买的是阿里云的服务,所以把友盟的推送换成了阿里云推送,首先不得不说,文档写得很差,兼容性和适配做得也不是很好,加了技术支持群,但是里面的同学问一个问题半天才有回复,好了,不扯谈,直接上代码。
  1.添加依赖:
  由于公司项目是组件化开发,所以我把推送也单独做成了一个组件,可以独立运行.在项目的统一依赖管理config.gradle添加阿里云推送的依赖和各第三方渠道的依赖,如下图所示:    如有疑问和版本更新,可以去阿里云官网查看,这里就不说这些了
  ![在这里插入图片描述](https://img-blog.csdnimg.cn/84834625b98d42198f68649debefc0f3.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5reh5reh55qE6aaZ54Of,size_20,color_FFFFFF,t_70,g_se,x_16)

  
           // 主通道依赖
        "ali_push"                   : 'com.aliyun.ams:alicloud-android-push:3.4.0',
        // 辅助通道基础依赖
        "third_push"                 : 'com.aliyun.ams:alicloud-android-third-push:3.4.0',
        // 华为依赖
        "push-huawei"                : 'com.aliyun.ams:alicloud-android-third-push-huawei:3.4.0',
        // 小米依赖
        "push-xiaomi"                : 'com.aliyun.ams:alicloud-android-third-push-xiaomi:3.4.0',
        // OPPO依赖
        "push-oppo"                  : 'com.aliyun.ams:alicloud-android-third-push-oppo:3.4.0',
        // vivo依赖
        "push-vivo"                  : 'com.aliyun.ams:alicloud-android-third-push-vivo:3.4.0',
        // 魅族依赖
        "push-meizu"                 : 'com.aliyun.ams:alicloud-android-third-push-meizu:3.4.0',
        // 谷歌依赖
        "push-fcm"                   : 'com.aliyun.ams:alicloud-android-third-push-fcm:3.4.0',
        // 公共依赖库
        "alicloud-utdid"             : 'com.aliyun.ams:alicloud-android-utdid:2.5.1-proguard',
        "alicloud-utils"             : 'com.aliyun.ams:alicloud-android-utils:1.1.6.4',
        "alicloud-ut"                : 'com.aliyun.ams:alicloud-android-ut:5.4.4',
        "alicloud-beacon"            : 'com.aliyun.ams:alicloud-android-beacon:1.0.5',
        2.Manifast配置如下:这里的appid和key填上你自己项目的即可.

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

        3.初始化:推送组件我做成了接口的形式,外部不用相互依赖即可直接调用,调用很方便,代码耦合行也不高,现在的组件化开发就得这样,不用每个模块相互依赖或引用,代码如下:
        推送基础的接口管理类:IPushActions
        接口管理类封装了以下方法:
        初始化、推送开关是否开启、设置别名、设置tag、绑定账号、移除别名、解绑tag、开启推送、关闭推送、解绑账号、查询所有别名、查询所有tag这些主要的方法

在这里插入图片描述
在这里插入图片描述

public interface IPushActions {

//初始化
void setDebugMode(boolean isDebugMode);

//初始化
void initPush(Application application);

//推送是否关闭
boolean isPushStopped(Context context);

//setAlias 阿里
void setAlias(Context context,String psnCode);

//解绑标签
void unBindTag(Context context, int target, String[] tags);

//setTags 阿里
void setTags(Context context, String[] tags);

//移除别名
void removeAlias(Context context, String alias);

void openPush();

void closePush();

boolean isStopPush(Context context);

void stopJPush(Context context);

void resumeJPush(Context context);

//绑定账号
void bindAccount(Context context,String userId);

//解绑账号
void unbindAccount(Context context,String userId);

//查询所有tag
void listTags(Context context,int target);

//查询所有别名
void listAliases(Context context);

}
4.初始化的代码在Mainapplication中也就一句话,如下图:
在这里插入图片描述

5.同学们有没有觉得很方便,因为我基于推送接口类写了一个推送的管理类,在上面设置tag和别名的基础方法之上写了具体初始化和各种绑定解绑逻辑,截图如下:

在这里插入图片描述
6.这里的代码只是参考,同志们根据自己的逻辑进行调整,完整代码如下:
package com.powervision.lib_ali_push.manager;

import android.app.Application;
import android.content.Context;

import com.alibaba.sdk.android.push.CloudPushService;
import com.alibaba.sdk.android.push.CommonCallback;
import com.alibaba.sdk.android.push.huawei.HuaWeiRegister;
import com.alibaba.sdk.android.push.noonesdk.PushServiceFactory;
import com.alibaba.sdk.android.push.register.GcmRegister;
import com.alibaba.sdk.android.push.register.MeizuRegister;
import com.alibaba.sdk.android.push.register.MiPushRegister;
import com.alibaba.sdk.android.push.register.OppoRegister;
import com.alibaba.sdk.android.push.register.VivoRegister;
import com.blankj.utilcode.util.AppUtils;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.powervision.lib_ali_push.component.MyMessageIntentService;
import com.powervision.lib_common.contants.AppUseConstant;
import com.powervision.lib_common.utils.LogUtils;
import com.powervision.lib_push.IPushActions;
import com.powervision.pvcamera.lib_alipush.BuildConfig;

import java.util.Arrays;
import java.util.List;

/**

  • @auth: njb

  • @date: 2021/8/6 9:57

  • @desc: 描述
    */
    public class AliPushManager implements IPushActions {

    private static AliPushManager mPushManager;
    private String TAG = “AliPushManager”;
    CloudPushService pushService;
    private FirebaseApp firebaseApp;

    private AliPushManager() {

    }

    public static AliPushManager getInstance() {
    if (mPushManager == null) {
    mPushManager = new AliPushManager();
    }
    return mPushManager;
    }

    @Override
    public void setDebugMode(boolean isDebugMode) {
    if (pushService != null) {
    //调试是否打开
    pushService.setDebug(isDebugMode);
    //设置日志级别
    pushService.setLogLevel(CloudPushService.LOG_DEBUG);
    }
    }

    @Override
    public void initPush(final Application application) {
    pushService = PushServiceFactory.getCloudPushService();
    pushService.setPushIntentService(MyMessageIntentService.class);
    pushService.register(application, new CommonCallback() {
    @Override
    public void onSuccess(String response) {
    LogUtils.d(TAG, “init cloudchannel success”);
    AliPushManager.getInstance().setAlias(application, PushTagUtils.getDeviceId());
    AliPushManager.getInstance().setTags(application, PushTagUtils.getTag());
    }

         @Override
         public void onFailed(String errorCode, String errorMessage) {
             LogUtils.d(TAG, "init cloudchannel failed -- errorcode:" + errorCode + " -- errorMessage:" + errorMessage);
         }
     });
     //初始化辅助渠道推送
     initThirdPush(application);
     AliPushManager.getInstance().setDebugMode(BuildConfig.DEBUG);
     setPushService(pushService);
    

    }

    private void initThirdPush(Application application) {
    // 初始化小米辅助推送
    MiPushRegister.register(application, AppUseConstant.XIAOMI_APP_ID, AppUseConstant.XIAOMI_APP_KEY);
    // 接入华为辅助推送
    HuaWeiRegister.register(application);
    // 接入ViVo初始化推送
    VivoRegister.register(application);
    // 接入Opp)初始化推送
    OppoRegister.register(application, AppUseConstant.OPPO_APP_KEY, AppUseConstant.OPPO_APP_Secret);
    // 接入MeiZu初始化推送
    MeizuRegister.register(application, “MEIZU_ID”, “MEIZU_KEY”);
    // 接入FCM/GCM初始化推送
    GcmRegister.register(application, AppUseConstant.GCM_SEND_ID, AppUseConstant.GOOGLE_APP_ID);
    //注册FireBase
    initFireBaseApp(application);

    }

    private void initFireBaseApp(Application application) {
    FirebaseOptions options = new FirebaseOptions.Builder()
    .setApplicationId(AppUseConstant.GOOGLE_APP_ID)
    .setGcmSenderId(AppUseConstant.GCM_SEND_ID)
    .setApiKey(AppUseConstant.GOOGLE_API_KEY).build();
    boolean hasBeenInitialized = false;
    List firebaseApps = FirebaseApp.getApps(application);
    for (FirebaseApp app : firebaseApps) {
    if (app.getName().equals(FirebaseApp.DEFAULT_APP_NAME)) {
    hasBeenInitialized = true;
    firebaseApp = app;
    }
    }
    //判断是否注册
    if (!hasBeenInitialized) {
    firebaseApp = FirebaseApp.initializeApp(application, options, AppUtils.getAppName());
    }
    }

    public void setPushService(CloudPushService pushService) {
    this.pushService = pushService;
    }

    public CloudPushService getPushService() {
    return pushService;
    }

    @Override
    public boolean isPushStopped(Context context) {
    return false;
    }

    @Override
    public void setAlias(final Context context, final String alias) {
    if (pushService != null) {
    pushService.addAlias(alias, new CommonCallback() {
    @Override
    public void onSuccess(String s) {
    LogUtils.d(TAG, alias + " success 别名绑定成功");
    }

             @Override
             public void onFailed(String errorCode, String errorMsg) {
                 LogUtils.d(TAG, alias + " failed." + "errorCode: " + errorCode + ", errorMsg:" + errorMsg + "\n");
             }
         });
     }
    

    }

    @Override
    public void unBindTag(final Context context, final int target, final String[] tags) {
    if (pushService != null) {
    pushService.unbindTag(target, tags, null, new CommonCallback() {
    @Override
    public void onSuccess(String response) {
    LogUtils.d(TAG, “success tag解绑成功” + tags);
    AliPushManager.getInstance().setTags(context, PushTagUtils.getTag());
    }

             @Override
             public void onFailed(String errorCode, String errorMsg) {
                 LogUtils.d(TAG, " failed." + "errorCode: " + errorCode + ", errorMsg:" + errorMsg + "\n");
             }
         });
     }
    

    }

    @Override
    public void setTags(Context context, final String[] tags) {
    if (pushService != null) {
    pushService.bindTag(CloudPushService.DEVICE_TARGET, tags, “”, new CommonCallback() {
    @Override
    public void onSuccess(String s) {
    LogUtils.d(TAG, " success 标签绑定成功" + Arrays.toString(tags));

             }
    
             @Override
             public void onFailed(String errorCode, String errorMsg) {
                 LogUtils.d(TAG, tags + " failed." + "errorCode: " + errorCode + ", errorMsg:" + errorMsg + "\n");
             }
         });
     }
    

    }

    @Override
    public void removeAlias(final Context context, final String alias) {
    if (pushService != null) {
    pushService.removeAlias(alias, new CommonCallback() {
    @Override
    public void onSuccess(String response) {
    LogUtils.d(TAG, alias + " success 别名解绑成功");
    LogUtils.d(TAG, AppUseConstant.ALIAS + " --解绑前的别名—");
    if (!AppUseConstant.isUnBind) {
    AppUseConstant.ALIAS = PushTagUtils.getDeviceId();
    LogUtils.d(TAG, AppUseConstant.ALIAS + " --解绑后的别名—");
    AliPushManager.getInstance().setAlias(context, AppUseConstant.ALIAS);
    }
    }

             @Override
             public void onFailed(String errorCode, String errorMsg) {
                 LogUtils.d(TAG, " failed." + "errorCode: " + errorCode + ", errorMsg:" + errorMsg);
             }
         });
     }
    

    }

    @Override
    public void openPush() {
    if (pushService != null) {
    pushService.turnOnPushChannel(new CommonCallback() {
    @Override
    public void onSuccess(String s) {
    com.blankj.utilcode.util.LogUtils.d(“turn on push channel success”);
    }

             @Override
             public void onFailed(String errorCode, String errorMsg) {
                 com.blankj.utilcode.util.LogUtils.d("turn on push channel failed." + "errorCode: " + errorCode + ", errorMsg:" + errorMsg + "\n");
             }
         });
     }
    

    }

    @Override
    public void closePush() {
    if (pushService != null) {
    pushService.turnOffPushChannel(new CommonCallback() {
    @Override
    public void onSuccess(String s) {
    com.blankj.utilcode.util.LogUtils.d(“turn off push channel success”);
    }

             @Override
             public void onFailed(String errorCode, String errorMsg) {
                 com.blankj.utilcode.util.LogUtils.d("turn off push channel failed." + "errorCode: " + errorCode + ", errorMsg:" + errorMsg + "\n");
             }
         });
     }
    

    }

    @Override
    public boolean isStopPush(Context context) {
    return false;
    }

    @Override
    public void stopJPush(Context context) {

    }

    @Override
    public void resumeJPush(Context context) {

    }

    @Override
    public void bindAccount(Context context, String userId) {
    final String account = userId;
    if (pushService != null) {
    pushService.bindAccount(account, new CommonCallback() {
    @Override
    public void onSuccess(String s) {
    LogUtils.d(TAG, account + " 账号绑定成功 success\n");
    }

             @Override
             public void onFailed(String errorCode, String errorMsg) {
                 LogUtils.d(TAG, account + " failed." + "errorCode: " + errorCode + ", errorMsg:" + errorMsg);
             }
         });
     }
    

    }

    @Override
    public void unbindAccount(Context context, final String account) {
    if (pushService != null) {
    pushService.bindAccount(account, new CommonCallback() {
    @Override
    public void onSuccess(String s) {
    LogUtils.d(TAG, s + “unbind account success 解绑账号成功”);
    }

             @Override
             public void onFailed(String errorCode, String errorMsg) {
                 LogUtils.d(TAG, "bind account failed." + "errorCode: " + errorCode + ", errorMsg:" + errorMsg + "\n");
             }
         });
     }
    

    }

    @Override
    public void listTags(final Context context, final int target) {
    if (pushService != null) {
    pushService.listTags(target, new CommonCallback() {
    @Override
    public void onSuccess(String response) {
    LogUtils.d(TAG, response + " success 查询标签成功");
    if (response.contains(Arrays.toString(PushTagUtils.getTag()))) {
    AliPushManager.getInstance().unBindTag(context, CloudPushService.DEVICE_TARGET, PushTagUtils.getTag());
    } else {
    bindTag(context, PushTagUtils.getTag());
    }
    }

             @Override
             public void onFailed(String errorCode, String errorMsg) {
                 LogUtils.d(TAG, " failed." + "errorCode: " + errorCode + ", errorMsg:" + errorMsg);
             }
         });
     }
    

    }

    private void bindAlias(Context context, String alias) {
    LogUtils.d(TAG, alias);
    if (alias.isEmpty()) {
    return;
    }
    AliPushManager.getInstance().setAlias(context, alias);
    }

    private void bindTag(Context context, String[] tags) {
    AliPushManager.getInstance().setTags(context, tags);
    //LogUtils.d(TAG, String.valueOf(tags));
    }

    @Override
    public void listAliases(final Context context) {
    if (pushService != null) {
    pushService.listAliases(new CommonCallback() {
    @Override
    public void onSuccess(String response) {
    LogUtils.d(TAG, response + " success 别名查询成功");
    }

             @Override
             public void onFailed(String errorCode, String errorMsg) {
                 LogUtils.d(TAG, " failed." + "errorCode: " + errorCode + ", errorMsg:" + errorMsg);
             }
         });
     }
    

    }
    }

7.遇到的问题:
a.初始化的时候一定要在隐私协议同意之后进行,相信集成友盟和sharesdk等第三方的同学一定会遇到这个问题,这里分两步,1是与初始化,这个方法不会获取设备信息,不用请求权限,2是需要在用户同意隐私协议之后初始化的方法,当然阿里云官网也给出了说明,说明如下:
在这里插入图片描述
b.阿里云推送和第三方辅助渠道在初始化时一定要在主线程中进行,不然会出现App在后台或者被杀死收到通知,但是进程没有拉起来的情况,代码如下:
在这里插入图片描述
判断是否为主进程的方法如下:
在这里插入图片描述
/**
* 当前进程是否为主进程
*
* @return True-是 False-否
*/
private boolean isMainProcess() {
// 获取当前包名
String packageName = this.getPackageName();
// 获取当前进程名
String processName = getProcessName(android.os.Process.myPid());
return processName == null || processName.equals(packageName);
}
c.在初始化第三方辅助渠道的时候,一定要仔细看文档,检查各个应用市场的key,因为这些配置关系到App退到后台和被杀死的情况下推送问题。这里特别说明一下!!!Oppo辅助渠道初始化的时候第三个参数不是appkey,也不是appid,而是appsecret,这里本同学刚开始也是填写错误,导致oppo手机一直注册失败,找了半天文档和资料才发现问题,所以接第三方一定要仔细,把文档和步骤看懂在开始写代码,要不然上来咔咔一顿操作猛于虎,但是发现出问题就蒙蔽了,完全找不到原因.
在这里插入图片描述
在这里插入图片描述
d.google的fcm推送国内由于用不了的原因,测试的时候一定要开启vpn,要不然会导致开启google服务失败而收不到离线通知。fcm初始化也要注意重复初始化的问题,如下图:
在这里插入图片描述
e.各大第三方辅助通道初始化成功的截图如下:
google gcm:
在这里插入图片描述
huawei:
在这里插入图片描述
xiaomi:
在这里插入图片描述

Oppo:
在这里插入图片描述
Vivo:
在这里插入图片描述
如果没有获取到上面的token,请仔细检查各种配置:
1.阿里云的推送后台:在这里插入图片描述这里需要注意的是Oppo填写的第2个可以是MasterSecret,而不是appsecret,很多同学不注意也会填错,这个去oppo开放平台获取你本应用的就好.
2.华为的配置:
https://help.aliyun.com/document_detail/190012.html
!!! 这里需要注意的是华为需要开通消息回执和配置SHA256证书指纹,要不然会一直提示初始化失败,本同学刚开始没有配置指纹证书,导致注册时一直获取不到华为推送渠道注册成功的token.
在这里插入图片描述
在这里插入图片描述

今天由于时间原因先到这里,后面会给出小米、oppo、vivo、gcm的具体配置和问题,目前各大平台的离线推送都很及时,当然,这里和我们公司付费有一定关系,还有提示用户打开各种通知权限,后面也会讲解.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android阿里云推送离线通知集成踩坑之路 的相关文章

  • 使用 Firebase 数据填充 Android spinner

    我在填充时遇到一些问题propertyAddress从我的properties桌子到我的旋转器MaintenanceActivity 问题本身不在于代码 而在于可以使用 Firebase 控制台修改的数据库规则 目前 我的规则是这样的 ru
  • 序列化 ArrayList

    我正在尝试编写一个 Android 游戏 即使用户想要返回主菜单或者活动被系统终止 我也希望能够暂停游戏 onSaveInstanceState 似乎并没有给我很大的控制权来决定何时可以读回捆绑包 而且据我所知 捆绑包仅在短时间内有效 所以
  • 需要在状态改变时关闭MediaRecorder播放的声音

    我已尝试在下面的链接中找到的更改 但没有效果 如何在状态改变时关闭 MediaRecorder 播放的声音 https stackoverflow com questions 6804205 how to shut off the soun
  • 即使具有用户权限,也无法在外部存储上保存文件 [Android]

    我正在 Android 上开发一个用于图像处理的应用程序 但我一直在编写图像保存代码 这是我使用的方法 private void saveImageToExternalStorage Bitmap finalBitmap String ro
  • 在 Android Studio 中调试服务的正确方法?

    在 Android Studio 中调试服务有正确的方法吗 或者 Android Studio 无法做到这一点 当我尝试调试时 它只会断开套接字 与目标虚拟机断开连接 地址 localhost 8600 传输 socket 希望你能在这里帮
  • Android view.animate() 第一次执行后工作方式不同且错误

    我已经实现了一个横幅 每当用户失去连接时就会弹出 重新连接后 另一个横幅会显示几秒钟然后消失 布局是一个RelativeLayout 其中一个灰色的TextView 表示警告 一个绿色的TextView 表示重新连接消息 如果我只是更改 V
  • Android studio 3.0不生成签名的apk

    将 android studio 更新到版本 3 0 Windows 后 我无法生成签名的 APK 构建完成后 我收到消息 单击 查找 会将我带到 APP 文件夹 但找不到 APK 改变了什么 自Android Studio 3 0更新后
  • 更新到最新版本(3.1)后缺少 google-play-services_lib.jar

    我在我的应用程序中使用 Google Play 服务已经有一段时间了 没有出现任何问题 我正在使用 Eclipse 我已在 I O 后将播放服务 以及 ADT 和 SDK 更新到最新版本 但现在我无法构建我的应用程序 我已将 google
  • 文本末尾有额外的换行符

    使用此方法设置文本后 我似乎得到了一些额外的换行符TextView message setText Html fromHtml message 我怎样才能删除这些 它们导致我的布局扭曲 因为它在输出中添加了两条额外的行 该字符串已通过以下方
  • GoogleMap 本质上是可打包的吗?

    我对java和android很陌生 我遇到了一个基本问题 在这个给定的fragment 我可以添加GoogleMap对象为parcelable没有任何额外的pracelable类为 public class SecondFragment e
  • 在 Android 模拟器上运行 Google 地图 v2

    我尝试在我的 Android 应用程序中实现 Google 地图 v2 但不幸的是 我收到的不是地图 而是以下消息 是否可以在 Android 模拟器 平台 4 2 上运行这些地图 目前 引用 Google Android Map API
  • 如何更改Android软键盘中任意键的按键背景

    我想让键盘上的一些键与其他键不同 例如下图中的shift 删除 空格键 根据google的参考文档 我们可以通过使用 来改变按键的背景android keybackground drawable xxx in input xml 但它改变了
  • Android 上的 Facebook 社交插件

    我想集成 Facebook 的评论社交插件 https developers facebook com docs reference plugins comments https developers facebook com docs r
  • Rails Resque 作业无法访问数据库,I/O 错误

    我遇到错误 无法找到任何相关信息 这是一个 Ruby on Rails 堆栈 Ruby 1 9 Rails 3 2 并使用 sqlite3 数据库进行开发 Resque 和 Redis 用于后台作业 Rails Web 应用程序启动正常 可
  • 将 Spritekit 游戏转换为 Android?

    是否有任何新选项可以将 spritekit 游戏转换为 Android 游戏 似乎唯一的选择是用 Java 重新编码所有内容或使用 Cocos2D LibGDX 等 很不幸的是 不行 而且带有 Apportable 服务的跨平台 Sprit
  • getApplicationDocumentsDirectory 在 flutter 桌面(Windows)上不起作用

    如何在 Windows 上的 flutter 桌面上保存和打开文件 getApplicationDocumentsDirectory 不适用于 Windows 应用程序的 flutter 桌面 Future
  • 如何从 Google Fit API 获取步数?

    请原谅我的笨蛋 我对 Android 和 Google API 完全陌生 我有以下连接到 GoogleFit 的代码 我还有一个 API 密钥和 Oauth 我在哪里 如何使用 API 密钥和 Oauth 关于如何获取它们的指南有很多 但关
  • SQLite 导入选项卡文件:.import 是每行执行一次插入还是将它们与事务分组?

    我正在从选项卡文件导入数百万行 而 SQLite import mode 选项卡非常慢 我有三个索引 所以缓慢可能来自索引 但首先我想检查 import 是否添加将大量 所有行分组到单个提交中的行 我无法找到 import 如何工作的文档
  • Android NDK - 仅用 C/C++ 编写

    有没有一种可能的方法可以使用 C C 编写整个 NDK 应用程序 而无需像 hello jni 示例项目 HelloJni java 中那样的 Java 入门 类 以某种方式创建一个 HelloJni c 来执行相同的操作 从 Androi
  • 从哪里开始阅读 SQLite 源代码? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想了解sqlite是如何实现的 并且 想阅读源代码 我已经下载了源代码 我应该开始查看代码的哪一部分 SQLite文档页 http

随机推荐

  • java IO流注意项总结

    IO流有很多种 按照操作数据的不同 可以分为字节流和字符流 按照数据传输方向的不同又可分为输入流和输出流 程序从输入流中读取数据 向输出流中写入数据 在IO包中 字节流的输入输出流分别用java io InputStream和java io
  • C/C++ 指向字符的指针为什么可以用字符串来初始化,而不是字符地址。

    感谢大佬 YLEOY https blog csdn net leigelaile1 article details 77511323 本文是通过几篇转帖的文章整理而成的 内容稍有修改 一 C语言中 为什么字符串可以赋值给字符指针变量 ch
  • H - Give Me This Pizza(栈stack)

    H Give Me This Pizzahttps vjudge csgrandeur cn problem Gym 101343H include
  • UE4 C++调用蓝图事件(单个参数)

    UE4 C 调用蓝图事件 C 先在头文件上面声明一个代理 我需要传递参数所以声明了一个单参数的代理 名字要以F开头 不然编译不通过 DECLARE DYNAMIC MULTICAST DELEGATE OneParam FCNUtf8Str
  • STM32的简单的SD卡读写

    导读 SD卡一般支持两种读写模式 SPI和SDIO模式 SD卡的引脚排序如下图所示 SPI模式下有几个重要的操作命令 分别是 SD卡R1回应的格式如下SPI模式下的典型初始化过程如下 1 初始化硬件配置 SPI配置 IO配置等 SD卡一般支
  • C++类和对象:对象的初始化和清理

    C 类和对象 对象的初始化和清理 1 构造函数与析构函数 2 构造函数的分类与调用 2 1 分类 2 2 调用 3 拷贝函数的调用时机 4 构造函数的调用规则 5 深拷贝与浅拷贝 6 初始化列表 7 类对象作为类成员 8 静态成员 8 1
  • JAVA操作Excel文件

    JAVA EXCEL API 是一开放源码项目 通过它Java开发人员可以读取Excel文件的内容 创建新的Excel文件 更新已经存在的Excel文件 使用该API非Windows操作系统也可以通过纯Java应用来处理Excel数据表 因
  • uniapp app 实现右上角回首页;点homeButton返回上一页;onNavigationBarButtonTap不生效问题

    场景 app Android移动端 实现点击右上角图标 回首页 问题 用了官网的 homeButton 图标正常展示了 也可点击 但每次点击后是会返回上一页而非首页 后来查到说 要结合onNavigationBarButtonTap生命周期
  • 关于STM32中ADC原理

    该文章内容来源于江协助科技 如有侵权 联系删除 目录 ADC原理 逐次逼近型ADC ADC框图介绍 注入通道 规则通道介绍 ADC基本结构 重点 转换模式 数据对齐 内部校准 ADC原理可以将引脚上连续变化模拟电压转换为内存中存储的数字变量
  • 区块链Fabric-从入门到实战(一)

    加密算法 加密算法分对称加密算法和非对称加密算法 在区块链中主要使用的时非对称加密算法 非对称加密是指为满足安全性需求和所有权验证需求而集成到区块链中的加密技术 非对称加密在加密和解密过程中 使用两个非对称的密钥 分别为公钥和私钥 非对称密
  • Android studio设置快捷键

    Android studio 设置快捷键 因为习惯用eclipse快捷键 所以将Androidstudio的快捷键设置成eclipse快捷键一致 首先在setting keymap 复制一份eclipse 这样就是eclipse的快捷键 以
  • 如何用matlab画泰勒图

    前几天写文章 想画一些泰勒图 我觉得其实这个泰勒图吧 包含的信息也并不多 只是看起来比较直观 且看起来逼格比较高 就谷歌了一下怎么画 先找到的是这个代码 但是有毒 死活跑不通 不知为何 且评论里大家和我的问题都一毛一样 遂重找 http c
  • ctfshow web15-web25详细思路

    web15 提示 公开的信息比如邮箱 可能造成信息泄露 产生严重后果 进入题目后看到有个QQ邮箱 我们搜一下它的QQ 没啥信息 返回到刚才的网站加后缀看能不能进去后台 不知道用户名密码哎 那忘记密码吧 发现一个信息 刚才搜的QQ用户在西安
  • 十、Update 存储过程

    文章目录 修改数据的要求 存储过程中的数据库异常 我们需要数据库异常 MariaDB 发起异常 SIGNAL和RESIGNAL mariaDB 捕获异常 捕获指定异常 捕获自定义异常 获取异常消息 update 锁及其测试 Update 锁
  • 通过Dockerfile启动容器遇到的两个不常见错误

    1 报错 ImportError cannot import name cached property from werkzeug 安装更高级的版本 pip install Werkzeug 0 16 0 2 已安装pip 执行python
  • Python入门--关键字

    关键字是Python编程语言中具有特殊含义的保留单词 不能用作变量名 函数名 类名或其他标识符 以下是Python 3 9 0版本中的关键字列表 False None True and as assert async await break
  • 将 varchar 转换为数据类型 numeric 时出现算术溢出错误

    SQL Server 2005 中 如果使用5位以上的字符串转换为numeric时就会出现 将 varchar 转换为数据类型 numeric 时出现算术溢出错误 这样的错误 如果使用5位以下 含5位 的就不会出错
  • Python笔记18-继承&函数重写

    一 继承 重点掌握 1 概念 如果两个或者两个以上的类具有相同的属性和方法 我们可以抽取一个类出来 在抽取出来的类中声明各个类公共的部分 被抽取出来的类 父类 father class 超类 super class 基类 base clas
  • Java List转换成String数组

    实现代码 List
  • Android阿里云推送离线通知集成踩坑之路

    最近因为公司后台服务器买的是阿里云的服务 所以把友盟的推送换成了阿里云推送 首先不得不说 文档写得很差 兼容性和适配做得也不是很好 加了技术支持群 但是里面的同学问一个问题半天才有回复 好了 不扯谈 直接上代码 1 添加依赖 由于公司项目是