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的路径。

step2:

加入两个库文件,一个是alljoyn.jar库文件,一个是liballjoyn_java.so库文件。下载地址是https://allseenalliance.org/framework/download。版本号我下载的是15.04,例如以下图。

我的.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

大家依据自己的解压位置去找就好了。

加入到project后例如以下图所看到的:

project视图下,加入的路径和目录名称。没有目录则建立相应名称的目录。然后将jar加入作库。

step3:

实现流程大致画一个示意图:

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上总线对象在总线附件上注冊的路径。

查看原文