Android与uni-app 互相通信案例(包含源代码)

Posted 人民的石头

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android与uni-app 互相通信案例(包含源代码)相关的知识,希望对你有一定的参考价值。

一、背景

在uni-app开发过程中,有时候会遇到uni-app插件或者提供的api对硬件操作不太友好,需要使用原生android开发对应模块,为了使得双方通信方便,特意封装了一个接口,可实现Android与Uni-app互相通讯。

二、内容

做完以下第一、第二部分,即可实现Android与uni-app 互相通信,当然双方通信有不同方式,具体情况具体分析,我的采用的方案是写Android原生插件,在uni-app中集成Android原生插件方式实现。

1、原生Android部分

Android原生涉及到的几个类,MyEvent.java(传递消息的ben类),MyEventManager.java类作用(事件管理器用来处理事件与通知监听器),MyListener.java类,作用接口回调(监听器接口)。由于采用的是uni-app插件方式,故先去uni-app官网下载插件sdk进行开发。详情见最后的代码连接,以下只是例举用的类。

代码


public class MyEvent 

    //数据
    private Object data;

    //事件来源  字符串
    private String source;

    //触发对象
    private Object trigger;

    private int state;

    public MyEvent() 
    

    public MyEvent(Object data) 
        this.data = data;
    

    public Object getTrigger() 
        return trigger;
    

    public void setTrigger(Object trigger) 
        this.trigger = trigger;
    

    public MyEvent(Object data, String source) 
        this.data = data;
        this.source = source;
    

    public Object getData() 
        return data;
    

    public void setData(Object data) 
        this.data = data;
    

    public String getSource() 
        return source;
    

    public void setSource(String source) 
        this.source = source;
    

    public int getState() 
        return state;
    

    public void setState(int state) 
        this.state = state;
    

    @Override
    public String toString() 
        return "MyEvent" +
                "data=" + data +
                ", source='" + source + '\\'' +
                ", trigger=" + trigger +
                ", state=" + state +
                '';
    


MyEventManager.java


/**
 * 事件管理器
 * 用来
 * 处理
 * 事件
 * 与通知
 * 监听器
 */
public class MyEventManager 

    private static MyEventManager myEventManager;

    private Map<String, Collection<MyListener>> listeners;

    /**
     * 不能外部 new
     * 实例化
     */
    private MyEventManager() 
        this.listeners = new HashMap<String, Collection<MyListener>>();
    

    /**
     * 返回监听 总数
     *
     * @return
     */

    public int getSize() 
        int size = 0;
        for (String str : listeners.keySet()) 
            size = size + listeners.get(str).size();

        
        return size;
    

    public Map<String, Collection<MyListener>> getListeners() 

        return listeners;
    

    /**
     * 单例模式
     *
     * @return
     */
    public static MyEventManager getMyEventManager() 
        if (myEventManager == null) 
            synchronized (MyEventManager.class) 
                if (myEventManager == null) 
                    myEventManager = new MyEventManager();
                
            
        
        return myEventManager;
    

    /***
     * 添加事件
     * @param listener    事件对象
     * @param source      来源
     */
    public MyListener addListener(MyListener listener, String source) 

        if (listener != null && source != null) 
            Collection<MyListener> myListeners = listeners.get(source);

            if (myListeners == null) 
                myListeners = new HashSet<MyListener>();
                listeners.put(source, myListeners);
            
            myListeners.add(listener);

        
        return listener;

    

    /***
     * 添加事件
     *  @param source      来源
     * @param listener    事件对象
     */
    public MyListener addListener(String source, MyListener listener) 

        return addListener(listener, source);
    

    /**
     * 移除监听
     *
     * @param listener
     */
    public void removeListener(MyListener listener) 
        if (listeners == null || listener == null) 
            return;
        

        //变量所有  找出相同的  删除
        for (String str : listeners.keySet()) 

            Collection collection = listeners.get(str);
            Iterator<MyListener> iter = collection.iterator();
            while (iter.hasNext()) 
                MyListener next = (MyListener) iter.next();
                if (next == listener) 
                    collection.remove(next);
                    return;
                
            
        

    

    /***
     *   发送数据
     * @param data   数据
     * @param source 来源
     * @return
     */
    public static MyEvent postMsg(Object data, String source) 
        MyEventManager myEventManager = MyEventManager.getMyEventManager();
        MyEvent myEvent = new MyEvent(data);
        myEvent.setSource(source);
        if (myEventManager.listeners == null)

            return myEvent;
        myEventManager.notifyListeners(myEvent, myEvent.getSource());
        return myEvent;
    

    /**
     * 通知所有的myListener
     * 相同的 (source) 来源才通知
     */
    private void notifyListeners(MyEvent event, String source) 

        //取出  key为source 的  监听器集合
        Collection<MyListener> collection = listeners.get(source);

//        Log.i(MyEventManager.class.getName(), source + "--->" + event.getData());

        if (collection == null) 
            return;
        
        //遍历监听器集合
        Iterator<MyListener> iter = collection.iterator();
        while (iter.hasNext()) 
            MyListener next = iter.next();
            //通知回调
            next.onChange(event);
        

        //销毁事件对象
        event = null;
    


MyListener.java类

public interface MyListener extends EventListener 
    void onChange(MyEvent myEvent);

BluetoothAndWifi.java类继承UniModule实现插件


public class BluetoothAndWifi extends UniModule 

    public static int REQUEST_CODE = 1000;//请求码
    public static int REQUEST_BLUETOOTH_CODE = 1001;//请求码

    @UniJSMethod(uiThread = false)
    public void sendMsgToUni() 
        MyEventManager.postMsg("==大宝==Android发送给==Uni-app====", "formAndroid");
    

    @UniJSMethod(uiThread = false)
    public void initAndroidEventListner() 

        Ted();
    

    @UniJSMethod(uiThread = true)
    public void Ted() 
        Toast.makeText(mWXSDKInstance.getContext(), "==初始化监听AndroidEventListner==", Toast.LENGTH_SHORT).show();

        MyEventManager.getMyEventManager().addListener(new MyListener() 
            @Override
            public void onChange(MyEvent myEvent) 

                if (myEvent.getSource().trim().equals("fromUni-app") ) //判断过滤
                    //从uniapp 或者原生传过来的数据
                    Object data = myEvent.getData();
                    Toast.makeText(mWXSDKInstance.getContext(), "==Uni传过来的数据====" + data, Toast.LENGTH_SHORT).show();
                

            
        , "fromUni-app");
    

    /**
     * 加法运算
     */
    @UniJSMethod(uiThread = false)
    public void addMathNumber(int a, int b, UniJSCallback callback) 
        callback.invoke(a + b + 9);
    

    /**
     * 原生toast提示
     */
    @UniJSMethod(uiThread = false)
    public void showToast(String msg, UniJSCallback callback) 
        Toast.makeText(mWXSDKInstance.getContext(), msg, Toast.LENGTH_SHORT).show();
        callback.invoke(msg);
    

    /**
     * 原生toast提示
     */
    @UniJSMethod(uiThread = false)
    public void aShowToastOK(String msg, UniJSCallback callback) 
        Toast.makeText(mWXSDKInstance.getContext(), msg, Toast.LENGTH_SHORT).show();
        callback.invoke(msg);
    

    /**
     * 跳转到
     * wifi页面
     */
    @UniJSMethod(uiThread = false)
    public void gotoWifiPage() 

        if (mUniSDKInstance != null && mUniSDKInstance.getContext() instanceof Activity) 
            Intent intent = new Intent(mUniSDKInstance.getContext(), WiFiActivity.class);
            ((Activity) mUniSDKInstance.getContext()).startActivityForResult(intent, REQUEST_CODE);
        

    


    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) 
        if (requestCode == REQUEST_CODE && data.hasExtra("respond")) 
//            Log.e("TestModule", "原生页面返回----"+data.getStringExtra("respond"));
         else 
            super.onActivityResult(requestCode, resultCode, data);
        
    

怎么使用

 Android原生部分
 //发送消息
 MyEventManager.postMsg("==大宝==Android发送给==Uni-app====", "formAndroid");//发消息

 //初始化监听
      MyEventManager.getMyEventManager().addListener(new MyListener() 
            @Override
            public void onChange(MyEvent myEvent) 

                if (myEvent.getSource().trim().equals("fromUni-app") ) //判断过滤
                    //从uniapp 或者原生传过来的数据
                    Object data = myEvent.getData();
                    Toast.makeText(mWXSDKInstance.getContext(), "==Uni传过来的数据====" + data, Toast.LENGTH_SHORT).show();
                

            
        , "fromUni-app");
//"fromUni-app" 标记 必须与发送消息的标记一样


uni-app部分的代码

//获取java类 
let myEventManager = plus.android.importClass("com.xiaoya.mylibrary.business.msg.MyEventManager");
let eventManager = myEventManager.getMyEventManager();

let myListener = plus.android.implements("com.xiaoya.mylibrary.business.msg.MyListener", 
                    onChange: function(event) 
                        plus.android.importClass(event);
                        console.log("==日志输出33333==" + event.getData());
                        if (event.getSource() == 'formAndroid') 


                            andoridModule.showToast(event.getData());
                        

                        //导入类  

                        //获取数据  
                        // console.log);  
                        //获取来源  
                        // console.log(event.getSource();  
                    
                )

  // //添加监听器    
  eventManager.addListener("formAndroid", myListener);



msg部分

2、uni-app调用部分

a、代码

<template>
    <view class="content">
        <input type="number" v-model="a" />
        <input type="number" v-model="b" />
        <button type="default" @click="sendMsgToUni">原生发消息给uni</button>
        <button type="default" @click="add">加法</button>
        <button type="default" @click="openwifi">打开wifi</button>
        <button type="default" @click="openbluetooth">打开蓝牙</button>
        <button type="default" @click="sendMsgToAndroid">Uni发消息给原生</button>
    </view>
</template>

<script>
    // 引入插件
    let andoridModule = uni.requireNativePlugin('BluetoothAndWifiPlugin');

    let myEventManager = plus.android.importClass("com.xiaoya.mylibrary.business.msg.MyEventManager");
    let eventManager = myEventManager.getMyEventManager();

    export default 
        data() 
            return 
                a: 1,
                b: 2
            
        ,

        onLoad() 


        ,

        onShow() 
            // 初始化原生数据接收监听
            andoridModule.initAndroidEventListner();
            this.initUniListener(); //初始化uni数据接收监听

        ,


        methods: 
            // Uni发消息给原生
            sendMsgToAndroid() 
                myEventManager.postMsg("==蘑菇头==发送消息==", "fromUni-app");
            ,
            /* 原生发消息给uni */
            sendMsgToUni() 

                andoridModule.sendMsgToUni();
            ,
            // 初始化Uni监听
            initUniListener() 
                console.log("===日志输出111===" + myEventManager);
                console.log("===日志输出222===" + eventManager);

                let myListener = plus.android.implements("com.xiaoya.mylibrary.business.msg.MyListener", 
                    onChange: function(event) 
                        plus.android.importClass(event);
                        console.log("==日志输出33333==" + event.getData());
                        if (event.getSource() == 'formAndroid') 


                            andoridModule.showToast(event.getData());
                        

                        //导入类  

                        //获取数据  
                        // console.log);  
                        //获取来源  
                        // console.log(event.getSource();  
                    
                )

                // //添加监听器    
                eventManager.addListener("formAndroid", myListener);
            ,

            /*打开蓝牙*/
            openbluetooth() 
                // this.jsCallNativeActivity();
                 
                // andoridModule.goToBluetoothPage();
            ,

            /*openwifi页面跳转*/
            openwifi() 

                // myEventManager.postMsg("app 显示了", "onShow");
                andoridModule.gotoWifiPage();
            ,

            /**
             * 相加
             */
            add() 

                andoridModule.addMathNumber(this.a, this.b, (e) => 
                    andoridModule.showToast('1+B=' + e);
                );
            ,

        

    
</script>

<style>
    .content 
        padding-top: 200rpx;
    
</style>

uni-app工程截图

3、最终效果

4、代码地址

代码还包含其他功能,例如uni-app调用

Android原生代码

https://download.csdn.net/download/shi450561200/87383612

uni-app代码

https://download.csdn.net/download/shi450561200/87383617

https://ask.dcloud.net.cn/article/id-36187

Springboot-入门案例

学习视频地址: https://www.bilibili.com/video/BV1PE411i7CV

1- 微服务

1.1 微服务基本概念

微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通(通常是基于HTTP的RESTful API)。

1.2 单体应用架构

所谓单体应用架构只要是指,将一个应用中的所有服务都封装在一个应用中。常见的ERP、CMS系统,都是将数据库,web访问等所有功能放入到一个war包中,然后发布到tomcat等容器中的应用。

单体应用架构优点

易于开发和测试,也十分方便部署。当需要扩展时,只需要将war包多复制几份,将其放置服务器中,通过nginx做个负载均衡就可以了。

单体应用架构缺点

哪怕是需要修改非常小的地方,都要将整个服务停掉,然后重新打包,部署这个war包。当面临一个大型项目时,不可能将所有的内容都放在一个应用里面。如何维护和分工合作都是问题。

1.3 微服务架构

所谓微服务架构,就是要解决单体应用架构的方式,将每个功能元素独立出来,把独立出来的功能元素的动态组合,需要的功能元素才去拿来组合,需要将多一些时间可以整合多个功能元素。所以微服务架构只是对功能元素进行复制,而没有对整个应用进行复制

微服务架构好处

节省了调用资源,每个功能元素的服务都是一个可替换的,可独立升级的软件代码!!!

微服务的具体解释: https://martinfowler.com/articles/microservices.html

如何构建微服务

一个大型系统的微服务架构,就像一个复杂交织的神经网络,每一个神经元就是一个功能元素,它们各自完成自己的功能,然后通过http相互请求调用。比如京东商城。缓存、数据库、浏览页面、结账、支付等服务都是一个个独立的功能服务,都被微化了。它们作为了一个个微服务共同构建一个庞大的系统,如果修改其中的一个功能,只需要更新升级其中一个功能服务单元即可。但是这种庞大的系统架构给部署和运维带来很大的难度,于是,Spring给我们带来了构建大型分布式微服务的全套、全程产品。

  • 构建一个个功能独立的微服务应用单元,可以使用Spring Boot,可以帮助快速构建一个应用。
  • 大型分布式网络服务的调用,这部分由Spring cloud来完成,实现分布式。
  • Spring 为我们想清楚了整个开始构建应用到大型分布式应用全流程方案。

2- SpringBoot简介

2.1 约定优于配置

Build Anything with Spring Boot:Spring Boot is the starting point for building all Spring-based applications. Spring Boot is designed to get you up and running as quickly as possible, with minimal upfront configuration of Spring。

上面是引自官网的一段话,大概是说: Spring Boot 是所有基于 Spring 开发的项目的起点,Spring Boot 的设计是为了让你尽可能快的跑起来 Spring 应用程序并且尽可能减少你的配置文件

约定优于配置(Convention over Configuration),又称按约定编程

本质上是说是一种软件设计范式,系统、类库或框架应该假定合理的默认值,而非要求提供不必要的配置。默认帮我们进行了很多设置,多数 Spring Boot 应用只需要很少的 Spring 配置。同时它集成了大量常用的第三方库配置(例如 Redis、MongoDB、Jpa、RabbitMQ、Quartz 等等),SpringBoot 应用中这些第三方库几乎可以零配置的开箱即用。

2.2 Spring优缺点分析

优点

Spring是Java企业版(Java Enterprise Edition,JEE,也称J2EE)的轻量级代替品。无需开发重量级的Enterprise Java Bean(EJB),Spring为企业级Java开发提供了一种相对简单的方法,通过依赖注入和面向切面编程,用简单的Java对象(Plain Old Java Object,POJO)实现了EJB的功能。

缺点

虽然Spring的组件代码是轻量级的,但它的配置却是重量级的。一开始,Spring用XML配置,而且是很多XML配 置。Spring 2.5引入了基于注解的组件扫描,这消除了大量针对应用程序自身组件的显式XML配置。

Spring 3.0引入 了基于Java的配置,这是一种类型安全的可重构配置方式,可以代替XML。所有这些配置都代表了开发时的损耗。因为在思考Spring特性配置和解决业务问题之间需要进行思维切换,所以编写配置挤占了编写应用程序逻辑的时间。和所有框架一样,Spring实用,但与此同时它要求的回报也不少。

除此之外,项目的依赖管理也是一件耗时耗力的事情。在环境搭建时,需要分析要导入哪些库的坐标,而且还需要分析导入与之有依赖关系的其他库的坐标,一旦选错了依赖的版本,随之而来的不兼容问题就会严重阻碍项目的开发进度SSM整合:Spring、Spring MVC、Mybatis、Spring-Mybatis整合包、数据库驱动,引入依赖的数量繁多、容易存在版本冲突。

2.3 Spring Boot解决上述spring问题

SpringBoot对上述Spring的缺点进行的改善和优化,基于约定优于配置的思想,可以让开发人员不必在配置与逻辑 业务之间进行思维的切换,全身心的投入到逻辑业务的代码编写中,从而大大提高了开发的效率,一定程度上缩短 了项目周期。

起步依赖

起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖,这些东西加在一起即支持某项功能。
简单的说,起步依赖就是将具备某种功能的依赖坐标打包到一起,并提供一些默认的功能。

自动配置

springboot的自动配置,指的是springboot会自动将一些配置类的bean注册进ioc容器,我们可以需要的地方使用@autowired或者@resource等注解来使它。
“自动”的表现形式就是我们只需要引我们想用功能的包,相关的配置我们完全不用管,springboot会自动注入这些配置bean,我们直接使用这些bean即可。springboot: 简单、快速、方便地搭建项目,对主流开发框架的无配置集成,极大提高了开发、部署效率。

3- 入门案例

3.1 环境准备

我们将学习如何快速的创建一个Spring Boot应用,并且实现一个简单的Http请求处理。通过这个例子对Spring Boot有一个初步的了解,并体验其结构简单、开发快速的特性。
环境准备

  • jdk: 1.8
  • Maven-3.6
  • SpringBoot 2.x 最新版

开发工具

  • IDEA

3.2 SpringBoot 快速构建

案例需求:请求Controller中的方法,并将返回值响应到页面。

使用Spring Initializr方式构建Spring Boot项目

本质上说,Spring Initializr是一个Web应用,它提供了一个基本的项目结构,能够帮助我们快速构建一个基础的Spring Boot项目。

选择当前最新的稳定版本,创建工程时候选中web依赖。

Spring Boot项目就创建好了,创建好的Spring Boot项目结构如图。
使用Spring Initializr方式构建的Spring Boot项目会默认生成项目启动类;

存放前端静态资源和页面的文件夹、编写项目配置的配置文件以及进行项目单元测试的测试类。

pom.xml 分析

打开 pom.xml,看看Spring Boot项目的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--父依赖-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.5</version>
        <relativePath/> 
    </parent>
    <groupId>cn.guardwhy</groupId>
    <artifactId>springboot_demo01</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot_demo01</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--web场景启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--Springboot单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!--打包插件-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

创建一个用于Web访问的Controller

在主程序的同级目录下,新建一个controller包,一定要在同级目录下,否则识别不到
在包中新建一个HelloController类

package cn.guardwhy.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String hello(){
        return "Hello Spring Boot!!!";
    }
}

运行项目

运行主程序启动类SpringbootDemo01Application,项目启动成功后。

在控制台上会发现SpringBoot项目默认启动的端口号为8080,此时,可以在浏览器上访问http://localhost:8080/hello

页面输出的内容是“Hello Spring Boot!!!”,至此,构建Spring Boot项目就完成了。

3.3 项目打包

将项目打成jar包,点击 maven的 package!!!

如果打包成功,则会在target目录下生成一个 jar包。

打成了jar包后,就可以在任何服务器上运行了,执行java -jar xxx.jar命令!!!

执行结果

以上是关于Android与uni-app 互相通信案例(包含源代码)的主要内容,如果未能解决你的问题,请参考以下文章

借助ESP8266 WIFI模块,实现Android手机有人网络调试助手(或Android手机网络调试助手)与单片机互相通信。

借助ESP8266 WIFI模块,实现Android手机有人网络调试助手(或Android手机网络调试助手)与PC端串口调试助手互相通信。

android studio中使用AIDL进行客户端与服务端互相通信

android Fragment与Activity交互,互相发数据(附图具体解释)

Android BLE与终端通信——Google API BLE4.0低功耗蓝牙文档解读之案例初探

React Native 入门——js与native互相通信