AllJoyn+Android开发案例-android跨设备调用方法

AllJoyn+Android开发案例-android跨设备调用方法AllJoyn+Android开发案例-android跨设备调用方法

大家好,又见面了,我是你们的朋友全栈君。

AllJoyn+Android开发案例-android跨设备调用方法
项目需要涉及AllJoyn开源物联网框架。前面主要了解了一些AllJoyn基本的概念,像总线,总线附件,总线对象,总线接口这样的概念,以及之间的关系和跨设备、平台的调用功能。项目最终的目的实现是,跨平台的方法调用如:windows调用android,以及对于设备事件的订阅功能。
入手的步骤:
1.实现android端的跨设备方法(自定义)调用案例-java
2.实现windows端的跨设备方法(自定义)调用案例-c++
3.实现windows端和android端的跨设备方法调用案例-(window用C++,android用java)
4.结合实际项目实现跨平台、跨设备的方法调用和订阅功能
现阶段我们来尝试实现android端的跨设备方法(自定义)调用案例-java
上面一篇关于博客–AllJoyn+Android开发的一般步骤,主要概念上描述了如何实现调用,这篇文章我们结合android代码实现,走一遍流程,加深理解和记忆。参考地址http://blog.csdn.net/jsjdtb356/article/details/51084886。
官网参考地址(很重要):https://allseenalliance.org/framework/documentation/develop/api-guide/core/java
开源代码(core API+很多实例-android studio可运行):https://allseenalliance.org/framework/download
step1:
新建android studio project,选择file/project structrue 设置好java sdk,android sdk,android ndk的路径。
AllJoyn+Android开发案例-android跨设备调用方法
step2:
添加两个库文件,一个是alljoyn.jar库文件,一个是liballjoyn_java.so库文件,下载地址是https://allseenalliance.org/framework/download。版本我下载的是15.04,如下图。
AllJoyn+Android开发案例-android跨设备调用方法
我的.jar的绝对路径:G:\alljoyn\alljoyn-android\core\alljoyn-15.04.00b-rel\java\jar\alljoyn.jar
我的.so的绝对路径:G:\alljoyn\alljoyn-android\core\alljoyn-15.04.00b-rel\java\lib\liballjoyn_java.so
大家根据自己的解压位置去找就好了。
添加到工程后如下图所示:
AllJoyn+Android开发案例-android跨设备调用方法
project视图下,添加的路径和文件夹名称,没有文件夹则建立对应名称的文件夹。然后将jar添加作库。
step3:

实现流程
大致画一个示意图:
AllJoyn+Android开发案例-android跨设备调用方法

server代码实现:一个activity用于交互,button开启一个service;service中具体实现alljoyn代码;一个总线接口,总线对象要实现的接口;service上代码如下。

package com.example.siemens.testgetmethod;

import android.app.Service;
import android.content.Intent;
import android.net.wifi.WifiConfiguration;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

import org.alljoyn.bus.BusAttachment;
import org.alljoyn.bus.BusObject;
import org.alljoyn.bus.Mutable;
import org.alljoyn.bus.SessionOpts;
import org.alljoyn.bus.SessionPortListener;
import org.alljoyn.bus.Status;

import javax.net.ssl.SSLEngineResult;

public class MyService extends Service {

    private final String TAG="MyService";

    public MyService() {
//        super();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
//        throw new UnsupportedOperationException("Not yet implemented");
        return null;
    }

    public int onStartCommand(Intent intent, int flags, int startId) {
//        Log.i(TAG, "onStartCommand()");
        return START_STICKY;
    }

    public void onDestroy() {
//        backgroundHandler.exit();
    }

    public void onCreate(){
        Log.i(TAG,"onCreate method.");
        //mbus初始化
        mBus=new BusAttachment(getPackageName(),BusAttachment.RemoteMessage.Receive);
        startBusThread();
        if(backgroundHandler!=null)
            backgroundHandler.connect();
        else
            return;
    }

    private void startBusThread(){
        HandlerThread handlerThread=new HandlerThread("My HandlerThread");
        handlerThread.start();
        Looper loop=handlerThread.getLooper();
        backgroundHandler=new BackgroundHandler(loop);
        Log.i(TAG,"startBusThread method.");
    }

    //请求都在线程中执行
    private BackgroundHandler backgroundHandler=null;
    private final int CONNECT=2;

    //私有内部不可变类
    private final class BackgroundHandler extends Handler{
        public BackgroundHandler(Looper looper){
            super(looper);
        }

        public void connect(){
            Log.i(TAG,"backgroundHandler.connect()");
            Message msg=backgroundHandler.obtainMessage(CONNECT);//相当于message.what=2;
            backgroundHandler.sendMessage(msg);
        }

        public void handleMessage(Message msg){
            switch(msg.what){
                case CONNECT:
                    doConnect();
                    break;
                default:
                    break;
            }
        }
    }

    //创建总线附件对象,getPackageName()出现NullPointerException异常,先于构造函数执行,此时对象为null,所以放到oncreate里边去
//    private BusAttachment mBus=new BusAttachment(getPackageName(),BusAttachment.RemoteMessage.Receive);
    private BusAttachment mBus=null;
    //创建总线对象
    private MyBusObject myBusObject=new MyBusObject();
    //总线对象类,实现总线接口和总线对象接口
    class MyBusObject implements MyInterface,BusObject{
//        public void show(String args){
//            Toast.makeText(getApplicationContext(),args,Toast.LENGTH_SHORT).show();     //会调用的远程方法
//
//        }
//
//        public int add(int a,int b){                        //会调用的远程方法
//            return a+b;
//        }
        public String cat(String a,String b){
            a=a.replace('H','T');
            b=b.replace('W','B');
            return a+b;
        }
    }

    //session的端口号
    private static final short CONTACT_PORT=42;
    //总线对象,总线附件等连接到总线上的实现函数,创建的是service
    private void doConnect(){
        org.alljoyn.bus.alljoyn.DaemonInit.PrepareDaemon(getApplicationContext());  //启动守护进程

        Status status=mBus.registerBusObject(myBusObject,"/myBusObject");                     //注册总线对象
        if (Status.OK != status) {
            System.out.println("BusAttachment.registerBusObject() failed: " + status);
            System.exit(0);
            return;
        }

        //总线附件连接到总线上
        status=mBus.connect();
        if (status != Status.OK) {
            Log.i(TAG,"BusAttachment connect to bus failed.");
            System.exit(0);
            return;
        }

        //通信的session port 设置
        Mutable.ShortValue contactPort = new Mutable.ShortValue(CONTACT_PORT);
        SessionOpts sessionOpts = new SessionOpts();
        sessionOpts.traffic = SessionOpts.TRAFFIC_MESSAGES;
        sessionOpts.isMultipoint = false;
        sessionOpts.proximity = SessionOpts.PROXIMITY_ANY;
        sessionOpts.transports = SessionOpts.TRANSPORT_ANY;

        //绑定通信的session port
        status=mBus.bindSessionPort(contactPort,sessionOpts,new SessionPortListener(){
            @Override
            public boolean acceptSessionJoiner(short sessionPort, String joiner, SessionOpts sessionOpts){
                if (sessionPort == CONTACT_PORT) {
                    return true;
                } else {
                    return false;
                }
            }
        });
        if (status != Status.OK) {
            Log.i(TAG,"bind certain session port failed.");
            System.exit(0);
            return;
        }

        //向总线请求一个名称
        int flags = 0; //do not use any request name flags
        status = mBus.requestName("com.test.well.known.name", flags);
        if (status != Status.OK) {
            Log.i(TAG,"request name from bus failed.");
            System.exit(0);
            return;
        }

        //在总线上宣告name的存在
        status = mBus.advertiseName("com.test.well.known.name", SessionOpts.TRANSPORT_ANY);
        if (status != Status.OK) {
            Log.i(TAG,"advertise name on bus failed.");
            mBus.releaseName("com.test.well.know.name");
            System.exit(0);
            return;
        }else
            Toast.makeText(getApplicationContext(),"advertise name=com.test.well.known.name",Toast.LENGTH_SHORT).show();

    }

    static{
        System.loadLibrary("alljoyn_java");
    }
}

注意:静态初始化块中的loadlibrary不能少掉。上面的例子参照的是chat源码。

接口代码:

package com.example.siemens.testgetmethod;

import org.alljoyn.bus.BusException;
import org.alljoyn.bus.annotation.BusInterface;
import org.alljoyn.bus.annotation.BusMethod;

/**
 * Created by Siemens on 2016/4/8.
 */
@BusInterface (name = "org.my.interface.name")
public interface MyInterface {
//    @BusMethod
//    void show(String test) throws BusException;
//    @BusMethod
//    int add(int a,int b) throws BusException;
    @BusMethod
    String cat(String a,String b) throws BusException;
}

注意:格式必须按照这种格式来,上面接口的name属性后面的值很重要client要对应。

client代码如下:

package com.example.siemens.testgetmethodclient;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

import org.alljoyn.bus.BusAttachment;
import org.alljoyn.bus.BusListener;
import org.alljoyn.bus.Mutable;
import org.alljoyn.bus.ProxyBusObject;
import org.alljoyn.bus.SessionListener;
import org.alljoyn.bus.SessionOpts;
import org.alljoyn.bus.Status;

public class MyService extends Service {

    private final String TAG="MyClientService";
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
//        throw new UnsupportedOperationException("Not yet implemented");
        return null;
    }

    private BusAttachment mBus=null;
    private static final short CONTACT_PORT=42;

    //代理总线对象;接口对象
    private ProxyBusObject mProxyObj;
    public MyInterface mInterface;
//    public MyInterface getmInterface(){
//        return mInterface;
//    }

    //application对象
    private ClientApplication mApplication;

    @Override
    public void onCreate(){
        mApplication=(ClientApplication)getApplication();

        //守护进程不能忘
        org.alljoyn.bus.alljoyn.DaemonInit.PrepareDaemon(getApplicationContext());  //启动守护进程

        mBus=new BusAttachment(getApplication().getPackageName(),BusAttachment.RemoteMessage.Receive);

        //连接两次?
//        Status status=mBus.connect();
//        if (Status.OK != status) {
//            Log.i(TAG,"client busattachment first connect to bus failed.");
//            System.exit(0);
//            return;
//        }

        mBus.registerBusListener(new BusListener(){
            @Override
            public void foundAdvertisedName(String name, short transport,String namePrefix){
                mBus.enableConcurrentCallbacks();
                short contactPort = CONTACT_PORT;
                SessionOpts sessionOpts = new SessionOpts();
                sessionOpts.traffic = SessionOpts.TRAFFIC_MESSAGES;
                sessionOpts.isMultipoint = false;
                sessionOpts.proximity = SessionOpts.PROXIMITY_ANY;
                sessionOpts.transports = SessionOpts.TRANSPORT_ANY;

                Mutable.IntegerValue sessionId = new Mutable.IntegerValue();

                Status status = mBus.joinSession(name,contactPort,sessionId,sessionOpts,new SessionListener());

                mProxyObj = mBus.getProxyBusObject("com.test.well.known.name", "/myBusObject", sessionId.value, new Class[]{MyInterface.class});
                mInterface=mProxyObj.getInterface(MyInterface.class);

                //personal add
                mApplication.setTestInterface(mInterface);
            }
        });


        //连接两次??官网API问题???
        Status status=mBus.connect();
        if (Status.OK != status) {
            Log.i(TAG,"client busattachment second connect to bus failed.");
            System.exit(0);
            return;
        }

        //找到指定名称的busAttachment
        status = mBus.findAdvertisedName("com.test.well.known.name");
        if (status != Status.OK) {
            Log.i(TAG,"client findAdvertisedName failed.");
            System.exit(0);
            return;
        }
        else
            Toast.makeText(getApplicationContext(),"find name=com.test.well.known.name success.",Toast.LENGTH_SHORT).show();

    }

    static{
        System.loadLibrary("alljoyn_java");
    }
}

同时client端app也需要知道总线接口,但是要通过代理对象获得方法的具体实现,也要包含接口类,同server接口类。

总结:有4个client和server需要统一的地方。1.advertise的那个name,客户端是根据这个名称找server。2.接口类,server和client都要知道,server提供实现,client不知道具体实现。3.session设置的端口号,client的session port要和server统一。4.client要知道,server上总线对象在总线附件上注册的路径。


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/151688.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • Linux中,常常会用到 vim ,其中 q ,wq wq!的区别,以及 vim -r 的作用[通俗易懂]

    w->表示保存退出wq!->表示强制保存退出,可以保存”readonly”只读文件q->在vim中表示退出q!->表示强制不保存退出,不对文件进行保存wq和wq!的区别如下:有些文件设置了只读,一般不是修改文件的,但是如果你是文件的owner或者root的话,通过wq!还是能保存文件退出如果文件设置为只读了的话,用:wq命令是不能保存并退出的,但是最高权限者可通过wq!来进行文件的保存并退出文件。已设定选项‘readonly’(请加!强制执行)!.

    2022年4月13日
  • Could not find a version that satisfies the requirement tensorflow问题汇总+解决!!!

    Could not find a version that satisfies the requirement tensorflow问题汇总+解决!!!前言:极力推荐使用Anaconda——————————————————————————一般报错就是:问题一CouldnotfetchURLhttps://pypi.python.org/simple/….然后就是:问题二Couldnotfindaver…

    2022年6月25日
  • Sublime插件推荐

    Sublime插件推荐常用插件推荐Alignment:自动对齐代码SublimeLinter提示编写代码中存在的不规范和错误的写法SublimeCodeIntel代码提示和补全BracketHighlighter代码匹配SideBarEnhancements侧栏右键功能增强ConvertToUTF8,GBK编码兼容Emmet让编写代码变得简单HTML-CSS-JSPrettifyHTML…

    2022年6月24日
  • request对象[通俗易懂]

    request对象[通俗易懂]request对象request对象封装了由客户端生成的HTTP请求的所有细节,主要包括HTTP头信息、系统信息、请求方式和请求参数等。通过request对象提供的相应方法可以处理客户端浏览器提交的

    2022年7月2日
  • kernelprocessorpower警告_kernel thread priority floor

    kernelprocessorpower警告_kernel thread priority floorechoworkqueue:workqueue_queue_work>/sys/kernel/debug/tracing/set_eventcat/sys/kernel/debug/tracing/trace_pipe>/data/trace_pipe.log

    2022年9月24日
  • leetcode数组汇总_leetcode经典题

    leetcode数组汇总_leetcode经典题原题链接给定一个由整数数组 A 表示的环形数组 C,求 C 的非空子数组的最大可能和。在此处,环形数组意味着数组的末端将会与开头相连呈环状。(形式上,当0 <= i < A.length 时 C[i] = A[i],且当 i >= 0 时 C[i+A.length] = C[i])此外,子数组最多只能包含固定缓冲区 A 中的每个元素一次。(形式上,对于子数组 C[i], C[i+1], …, C[j],不存在 i <= k1, k2 <= j 其中 k1 % A.leng

    2022年8月8日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号