MASA MAUI Plugin (六)集成个推,实现本地消息推送[Android] 篇

背景

MAUI的出现,赋予了广大.Net开发者开发多平台应用的能力,MAUI 是Xamarin.Forms演变而来,但是相比Xamarin性能更好,可扩展性更强,结构更简单。但是MAUI对于平台相关的实现并不完整。所以MASA团队开展了一个实验性项目,意在对微软MAUI的补充和扩展

项目地址https://github.com/BlazorComponent/MASA.Blazor/tree/main/src/Masa.Blazor.Maui.Plugin

每个功能都有单独的demo演示项目,考虑到App安装文件体积(虽然MAUI已经集成裁剪功能,但是该功能对于代码本身有影响),届时每一个功能都会以单独的nuget包的形式提供,方便测试,现在项目才刚刚开始,但是相信很快就会有可以交付的内容啦。

前言

本系列文章面向移动开发小白,从零开始进行平台相关功能开发,演示如何参考平台的官方文档使用MAUI技术来开发相应功能。

介绍

鉴于现在运营需求的增强,消息推送在Android开发中应用的场景是十分常见,如电商的活动宣传、资讯类产品进行新闻推送等等,所以关于这个功能我就不过多介绍了。面向海外推送业务MAUI有一些集成Google firebase或其他运营商的可用的示例和绑定库可用,但是国内用户无法使用这些,对于国内比较常见的例如极光、个推等,也没用对应的MAUI或者Xamarin的SDK可用,本人联系过官方也无法提供任何技术支持。

但是,这样的困难是无法难倒MASA的开发人员的,所以在各方压力的鞭策下,有了本文,本文以“国内服务提供商个推(https://www.getui.com)的Android 原生SDK”为例,提供Android原生代码到MAUI代码的绑定及实现方式。

思路

Android 的第三方库生态系统非常庞大。正因为此,使用现有的Android库通常比创建一个新的库更合理。其实早在Xamarin的时代,微软已经提供了Android绑定库(Xamarin)这个项目,实现原理为:创建一个绑定库,该库使用C# 包装器自动包装库,以便通过C# 调用来调用Java 代码,通过使用托管可调用包装器 (MCW) 实现绑定。MCW 是一个JNI 桥,在托管代码需要调用Java代码时会使用它。托管可调用包装器还支持对Java类型进行子类化以及覆盖Java类型的虚拟方法。同样,每当 Android 运行时 (ART) 代码需要调用托管代码时,它都会通过另一个称为 Android 可调用包装器 (ACW) 的 JNI 桥来实现。 下图说明了此体系结构

b5e01408e2bfd0c411694c703b52aec8.png

通常情况下,绑定 Android 库(.aar 或 .jar)文件绝非易事;通常它需要花费额外的精力来解决 Java 和 .NET 之间的差异导致的问题。这些问题会使 MAUI无法绑定 Android 库,并在生成日志中显示为错误消息。

推送功能涉及到的内容非常多,接下来我们只开发最基础的功能,并对此做最精简配置。

开发步骤

一、下载个推Android SDK

个推账号的申请及应用的创建请参考官方文档(个推面向个人开发者,而且我们通过CID发送测试是免费的,无需充值和实名认证)。

这里我们着重介绍集成的方法,个推官网的文档示例是使用Maven 方式集成,但是这种方式在MAUI当然无法实现,所以我们需要手动下载SDK对应的aar文件进行手动集成。

maven仓库地址为:http://mvn.getui.com/nexus/content/repositories/releases/com/getui

我们需要gtsdk和gtc,分别下载最新的gtc-3.1.12.0.aargtsdk-3.2.13.0.aar

我是怎么知道需要使用这两个文件呢?因为我下载了官方的Demo然后使用maven集成后在
C:\Users\用户名\.gradle\caches\modules-2\files-2.1\com.getui 目录下载了这两个文件😉
878a7f7cdeed13486ef59c5a195010f7.png

二、创建Android绑定库

新建一个项目:Masa.Blazor.Maui.Plugin.GeTuiPushBinding,项目模板选择Android Java 库绑定

1df772a3a217b02d2996bc25a265a219.png

在根目录创建Jars文件夹,并将下载的两个aar文件添加进去。添加进去的文件属性中,生成操作默认选择的是AndroidLibrary,如果不对请手动更正。

前方高能预警!😎

右键生成这个项目,我们会看到很多编译警告,其中还包含6处错误。

8c51b148fc36def0bbfec4ea78b8e1c1.png
我们依次点击对应错误,进入生成的cs文件,这些文件位于obj\Debug\net7.0-android\generated\src

错误1和2对应Com.Getui.Gtc.Base.Crypt.CryptTools文件的Decrypt和Encrypt方法。

这里Java.IO.OutputStream和InputStream类型都被转换为System.IO.Stream,导致本来两个签名不一致的方法被弄成了一样(更正的方法本文不做讨论,本Demo没有使用到这两个方法)索性将280行和134行的本来应该映射到OutputStream类型的Decrypt和Encrypt方法注释。

其他错误都是类型转换错误导致的没有实现接口,我们分别修改4个OnArrived方法,将方法的参数global::Org.Json.JSONObject修改为Java.Lang.Object,并将方法的virtual标记更改为override

只有一个参数的OnArrived方法需要将返回值也修改为Java.Lang.Object。

4处全部更正之后,再次生成就不会有报错了。

注意:不要选重新生成,重新生成会将之前的修改覆盖掉。

三、创建Demo项目

新建一个MAUI Blazor项目:Masa.Blazor.Maui.Plugin.GeTuiSample,添加对Masa.Blazor.Maui.Plugin.GeTuiPushBinding项目的引用

1、初始化个推SDK

个推SDK的初始化在MainActivity.OnCreate() 或MainApplication.OnCreate()方法中都是可以的,我们这里在MainActivity中初始化。修改Platforms->Android->MainActivity.cs文件,在MainActivity的OnCreate事件中添加我们的初始化方法

public class MainActivity : MauiAppCompatActivity{protected override void OnCreate(Bundle savedInstanceState){base.OnCreate(savedInstanceState);Com.Igexin.Sdk.PushManager.Instance.Initialize(this);var cid = Com.Igexin.Sdk.PushManager.Instance.GetClientid(this);System.Diagnostics.Debug.WriteLine($"cid:{cid}");}}

因为我们完成了绑定,所以这里可以使用个推SDK中的Com.Igexin.Sdk命名空间下的PushManager来完成初始化,
初始化方法Initialize非常简单,初始化后我们可以通过GetClientid方法拿到客户端ID,方便我们后续在个推平台下发推送测试任务,因为向特定CID发送推送是免费的。

2、配置推送服务

继续在Android目录下新建推送服务类DemoPushService

using Android.App;namespace Masa.Blazor.Maui.Plugin.GeTuiSample
{[Service(Process = ":pushservice", Exported = false)]public class DemoPushService : Com.Igexin.Sdk.PushService{}
}

我们只要实现一个继承自Com.Igexin.Sdk.PushService的类即可。

注意:服务必须指定Process = “:pushservice”,设置了这行代码,系统就会为该服务创建新的进程,DemoPushService 将运行在这个新的独立的进程,它所在的apk依旧运行在原来进程。这样就实现了Android使用多进程。
android:exported 是Android中的四大组件 Activity,Service,Provider,Receiver 四大组件中都会有的一个属性。
主要作用是:是否支持其它应用调用。处于安全考虑我们这里设置为Exported = false,代表不支持其他应用调用。

修改AndroidManifest.xml文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"><application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true" android:label="@string/app_name" android:usesCleartextTraffic="true"xmlns:tools="http://schemas.android.com/tools"><serviceandroid:name="Masa.Blazor.Maui.Plugin.GeTuiSample.DemoPushService"android:exported="false"android:label="PushService"android:process=":pushservice"/><meta-data android:name="GETUI_APPID"  tools:replace="android:value"  android:value="这里填你在个推的APPID" /></application><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.INTERNET" />
</manifest>

我们在application 中添加了xmlns:tools=“http://schemas.android.com/tools”,作用是在下面的meta-data中使用tools:replace,否则会出现Android 组件化集成合并AndroidManifest.xml 的问题,添加android:label="@string/app_name"也是为了避免合并问题。
service表示我们添加的自定义推送类,android:name的值必须写全命名空间。
GETUI_APPID部分为个推应用对应的APPID

我们启动应用,并在个推平台下发一个测试推送

a6d5ebd36106643b069862b3fa45b8db.gif
Android推送功能涉及的内容非常多,不同的Android版本、不同手机厂商还有不同的功能和实现方式,例如vivo有特有的角标通知等。我们这里只演示了最基本的推送功能,其他高级操作,例如自定义接收推送服务事件,设置通知图标及样式,相应对应通知点击事件,离线推送功能等,如有需求后续介绍。


如果你对我们的开源项目感兴趣,无论是代码贡献、使用、提 Issue,欢迎联系我们

237f25d53573a1c07c1bb22841bb7c8b.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/281222.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第八天

配置文件 Vi /etc/fstab /dev/vg01/lv01 /dir01 ext4 defaults mount -a 扫描 使用交换空间 1.创建分区 2.mkswap /dev/sda创建交换分区 3.swapon /dev/sda启用交换分区 Linux系统启动过程 1、引导程序 BIOS自检 &#xff08;硬件自检&#xff09; 2、G…

iOS 通知中心(NSNotificationCenter)

NSNotificationCenter 在这里第一步和第二步的顺序可以互换&#xff0c;一般楼主我喜欢先在需要发送消息的页面发送消息&#xff0c;然后再在需要监听的页面注册监听。要注意的是不管是通知中心还是KVO都需要在页面销毁之前移除监听。 注册观察者/*** 观察者注册消息通知*…

vue-router和react-router嵌套路由layout配置方案的区别

最近在学习react&#xff0c;在路由这一块有点看不懂&#xff0c;第一感觉是灵活性很大&#xff0c;想怎么来就怎么来&#xff0c;但问题也来了&#xff0c;稍微复杂一点就GG了&#xff0c;不如vue的傻瓜式配置来的方便。 先说一下vue的路由配置方式&#xff0c;目录结构如下&…

微软加更.NET7中文手册,都有哪些新亮点?

11月8号发布了.NET7&#xff0c;从底层性能改进&#xff0c;到上层API升级&#xff0c;让.NET7综合性能再度提升&#xff01;同时发布了最新的C#11&#xff0c;也带来了很多小惊喜。如何快捷学习最新的.NET7和C#11&#xff1f;答案只有一个&#xff0c;微软官方中文文档&#x…

jquery对json的各种遍历

http://caibaojian.com/jquery-each-json.html转载于:https://www.cnblogs.com/pxffly/p/8442448.html

中级工程师之路

前言&#xff1a;之前在问答中问了一个问题 毕业半年感觉没什么进步该怎么办&#xff1f; 这个问题一直让我感觉比计较焦虑。于是在一个关于面试经验的博客中找到了一些灵感。就是通过问题进行学习&#xff0c;对自身的知识体系进行整理和补充。以问题作为切入点&#xff0c;不…

Vue在渲染函数createELement和JSX中使用插槽slot

Vue对于插槽有两个专门的APIvm.$slots和vm.$scopedSlots&#xff0c;分别是普通插槽和作用域插槽&#xff0c;使用JSX语法或渲染函数的时候&#xff0c;定义插槽将使用上述两个API。 渲染函数createElement 普通插槽和作用域插槽在定义上相差不大&#xff0c;但是在使用方法上…

.NET Conf China 2022 第一批讲师阵容大揭秘!整个期待了!

目光看过来2022年12月3-4日一场社区性质的国内规模最大的线上线下.NET Conf 2022技术大会即将盛大开幕目前大会正紧锣密鼓地进行中第一批大咖讲师及主题已确定小编迫不及待想和大家分享分享嘉宾很大咖分享内容很硬核戳戳小手期待ing孔令磊维宏股份 首席架构师 十多年数控领域研…

2017 Material design 第二章第六节《富有创造性的定制方案》

六、富有创造性的定制方案&#xff08;Creative customization&#xff09; 动效可以应用于不同的对象尺寸和不同的环境&#xff0c;这有助于设计美感和功能的统一。 icon的类型系统icons可以有双重功能。 产品icons应该设计得精致、美观。 Icons 系统icons一个系统icon也许存在…

(十四)Java springcloud B2B2C o2o多用户商城 springcloud架构- Spring Cloud构建分布式电子商务平台...

通过Spring Cloud构建PC微信APP云服务的云商平台系统&#xff0c;其中包括B2B、B2C、C2C、O2O、新零售、直播电商等子平台&#xff0c;之前我们讲了很多关于Spring Cloud的概念文章&#xff0c;从本节开始&#xff0c;我们会以分布式微服务电子商务平台为案例&#xff0c;逐步给…

C# 队列(Queue)

概述队列&#xff08;Queue&#xff09;代表了一个先进先出的对象集合。当您需要对各项进行先进先出的访问时&#xff0c;则使用队列。当您在列表中添加一项&#xff0c;称为入队&#xff0c;当您从列表中移除一项时&#xff0c;称为出队。Queue 类的方法和属性Count 获取 Queu…

vue完全编程方式与react在书写和运用上的异同

在构建html元素时&#xff0c;vue倾向于模板方式&#xff0c;而react则完全使用javascript的编程能力&#xff0c;但vue也具备完全编程的能力&#xff08;与react一样使用JSX和createElement渲染函数&#xff09;。所以&#xff0c;当vue使用完全编程方式时&#xff0c;与react…

Solr 配置文件之schema.xml

schema.xml这个配置文件的根本目的是为了通过配置告诉Solr怎样建立索引。solr的数据结构例如以下&#xff1a;document&#xff1a;一个文档、一条记录 field&#xff1a;域、属性solr通过搜索某个或某些field&#xff0c;返回若干个符合条件的document。或者按搜索的score排序…

wget整站抓取、网站抓取功能;下载整个网站;下载网站到本地

wget -r -p -np -k -E http://www.xxx.com 抓取整站 wget -l 1 -p -np -k http://www.xxx.com 抓取第一级 -r 递归抓取-k 抓取之后修正链接&#xff0c;适合本地浏览 http://blog.sina.com.cn/s/blog_669fb0c3010137bq.html wget -m -e robotsoff -k -E "http://…

Git标签tag及tag远程同步

Git给某个历史版本打上标签&#xff0c;这样我们可以快速的众多历史版本中找到自己需要的版本&#xff0c;一般打标签的版本都是发布版本&#xff0c;例如v1.0.0 标签操作 创建标签 # 轻量标签 git tag tagname eg: git tag v1.4# 附注标签 git tag -a tagname -m tag descr…

妙用SQL Server聚合函数和子查询迭代求和

先看看下面的表和其中的数据&#xff1a;t_product该表有两个字段&#xff1a;xh和price&#xff0c; 其中xh是主索引字段&#xff0c;现在要得到如下的查询结果&#xff1a;从上面的查询结果可以看出&#xff0c;totalprice字段值的规则是从第1条记录到当前记录的price之和。如…

记一次.NET某工控图片上传CPU爆高分析

一&#xff1a;背景 1.讲故事今天给大家带来一个入门级的 CPU 爆高案例&#xff0c;前段时间有位朋友找到我&#xff0c;说他的程序间歇性的 CPU 爆高&#xff0c;不知道是啥情况&#xff0c;让我帮忙看下&#xff0c;既然找到我&#xff0c;那就用 WinDbg 看一下。二&#xff…

微信小程序项目实践准备工作

微信小程序项目实践准备工作一、了解微信小程序产品定位及功能介绍微信小程序是一种全新的连接用户与服务的方式&#xff0c;它可以在微信内被便捷地获取和传播&#xff0c;同时具有出色的使用体验。简单的说&#xff0c;小程序是微信附属产品&#xff0c;需要依赖微信&#xf…

VSCode 用户自定义片段 snippet 基本语法说明

先上一个官方模板&#xff1a; "Print to console": {"prefix": "log","body": ["console.log($1);","$2"],"description": "Log output to console" }prefix 前缀&#xff0c;emmet 触发条…

Python集合和函数

深浅拷贝&#xff1a;.copy()方法&#xff0c;浅拷贝值拷贝一层。列表中的列表和字典会深拷贝&#xff0c;其他类型会浅拷贝。列表中的列表和字典会随着副本的修改而改变&#xff0c;其他类型不会随着副本的改变为改变。ab不是复制&#xff0c;是两个变量共享同一内存空间&…