需求:android下写的 native C 发送消息。

android service 程序接受消息,并根据消息的类别模拟鼠标事件。

需求限制:native C 是个独立的程序。

andriod 服务也是个独立的服务。

思路:在 native C 程序和android服务之间建立socket链接,使用socket 链接进行通信。






-----------------------------------------------------------------------------------网上的资源,在此备份-------------------------------------------------------------------------------------------------


<pre name="code" class="html">方式一:java做服务器端,native做client端1. 建立java应用程序,建立Server 类<pre name="code" class="html">/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.example.hellojni;import android.app.Activity;import android.os.Bundle;import android.util.Log;import android.net.LocalServerSocket;import android.net.LocalSocket;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;public class HelloJni extends Activity{    public static final String SOCKET_NAME = "server_test";    private static final String TAG = "SocketService";    private LocalServerSocket mServerSocket = null;    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);Log.v(TAG, "onCreate");        try {            mServerSocket = new LocalServerSocket(SOCKET_NAME);        } catch (IOException e) {            Log.v(TAG, "in onCreate, making server socket: " + e);            return;        }        Thread t = new Thread() {                @Override public void run() {                    LocalSocket socket = null;                    while (true) {                        try {                            Log.v(TAG, "Waiting for connection...");                            socket = mServerSocket.accept();                            Log.v(TAG, ".....Got socket: " + socket);                            if (socket != null) {                                startEchoThread(socket);                            } else {                                return;  // socket shutdown?                            }                        } catch (IOException e) {                            Log.v(TAG, "in accept: " + e);                        }                    }                }            };        t.start();    }private void startEchoThread(final LocalSocket socket) {        Thread t = new Thread() {                @Override public void run() {                    try {                        InputStream is = socket.getInputStream();                        OutputStream os = socket.getOutputStream();                        InputStreamReader isr = new InputStreamReader(is);                        while (true) {                            char[] data = new char[128];                            int ret = isr.read(data);                            for(int i=0;i<ret;i++){                                Log.d(TAG, "data["+i+"]="+data[i]);                            }                            byte[] values = TypeUtils.float2Byte(-1234567.122f);                            float fd = -1234567.122f;                            Log.d(TAG, " fd="+fd);                            for(int i=0;i<values.length;i++){                                Log.d(TAG, "values["+i+"]="+values[i]);                            }                            os.write(values);                            os.flush();                           Log.v(TAG, "after write: ");                        }                    } catch (IOException e) {                        Log.v(TAG, "in echo thread loop: " + e.getMessage());                    }                }            };        t.start();    }}





2.将float转换成byte[]数组的工具类

import java.nio.ByteBuffer;import java.nio.FloatBuffer;public class TypeUtils {    public static byte[] floatToByte(float v) {        ByteBuffer bb = ByteBuffer.allocate(4);        byte[] ret = new byte[4];        FloatBuffer fb = bb.asFloatBuffer();        fb.put(v);        bb.get(ret);        return ret;    }    public static byte[] float2Byte(float f) {        byte[] b = new byte[4];        int l = Float.floatToIntBits(f);        for (int i = 0; i < b.length; i++) {            b[i] = new Integer(l).byteValue();            l = l >> 8;        }        return b;    }    public static byte[] doubleToByte(double d) {        byte[] b = new byte[8];        long l = Double.doubleToLongBits(d);        for (int i = 0; i < b.length; i++) {            b[i] = new Long(l).byteValue();            l = l >> 8;        }        return b;    }    public static float byteToFloat(byte[] v) {        ByteBuffer bb = ByteBuffer.wrap(v);        FloatBuffer fb = bb.asFloatBuffer();        return fb.get();    }    public static float byte2Float(byte[] b) {        int l = 0;        l = b[0];        l &= 0xff;        l |= ((int) b[1] << 8);        l &= 0xffff;        l |= ((int) b[2] << 16);        l &= 0xffffff;        l |= ((int) b[3] << 24);        l &= 0xffffffffl;        return Float.intBitsToFloat(l);    }}



.在 native中建立client

#include <cutils/sockets.h>static union FloatValue{char val[4];float f;} mf_t;static __inline__ intqemud_fd_write(int fd, const void* buff, int len){ int len2; do { len2 = write(fd, buff, len); } while (len2 < 0 && errno == EINTR); return len2;}static __inline__ intqemud_fd_read(int fd, void* buff, int len){ int len2; do { len2 = read(fd, buff, len); } while (len2 < 0 && errno == EINTR); return len2;}int main(int argc, char **argv){ int fd; char answer[200]; char name[5]= "test!"; int namelen = 5; /* connect to qemud control socket */ fd = socket_local_client( "server_test", ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM ); if (fd < 0) { printf("no qemud control socket: %s \n", strerror(errno)); return -1; } /* send service name to connect */ if (qemud_fd_write(fd, name, namelen) != namelen) { printf("can't send service name to qemud: %s \n", strerror(errno)); close(fd); return -1; } printf(".... before qemud_fd_read \n"); /* read answer from daemon */ int res =qemud_fd_read(fd, answer, 200); printf(" .....after qemud_fd_read "); if (res) { printf("connect to service through qemud res =%d answer0 =%d ,answer1 =%d answer2 =%d ,answer3 =%d \n",res,answer[0],answer[1],answer[2],answer[3]); mf_t.val[0] = answer[0]; mf_t.val[1] = answer[1]; mf_t.val[2] = answer[2]; mf_t.val[3] = answer[3]; printf(" .....after convert f=%f \n",mf_t.f); close(fd); return -1; } return 0;}
----------------------------------------------------------------------------------------------------------------------------------------------------------------------


android 中使用socket使native和framework通信

一般的native和framework的通信是通过jni,但是这一般只是framework调用native,native如果有消息要怎样通知上层呢?android中GSP模块提供一种解决思路,但是实现有些复杂,这里介绍一种使用socket通信的方法可以使native和framework自由通信,具体实现如下:
android中使用jni对linux中的socket进行了封装。使用起来十分的方便。
由于android是基于linux的,所以linux的代码会在java之前先执行,所以一般native端是服务器。framework端是客户端。
java层主要代码:
LocalSocket s =null;
LocalSocketAddress l;
s = new LocalSocket();
l = new LocalSocketAddress(SOCKET_NAME,LocalSocketAddress.Namespace.RESERVED);
s.connect(l);

到此时如果socket连接没有问题,就可以像正常的读写了。
native层主要代码:
s_fdListen = android_get_control_socket(SOCKET_NAME);
ret = listen(s_fdListen, n);
s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen);

如果连接没有问题就可以使用linux中的write/read来对socket进行读和写了;
这里有必要解释一下 SOCKET_NAME,它的值是一个字符串,它在init.rc中定义的一个字符串。也就是说,我们可以通过修改init.rc中来申请我们需要的socket资源。
这里以ril为例来说明:
service ril-daemon /system/bin/rild
socket rild stream 660 root radio
socket rild-debug stream 660 radio system
user root
group radio cache inet misc audio

以上是摘自android 2.2 源码中的system\core\rootdir\init.rc中的片段。至于其具体含义可以参见init.c和system/core/init/readme.txt文件。他的作用是由init.c来解析init.rc,并为我们启动一个名为rild的守护进程,它是一个可执行程序,我们通过adb shell在system/bin中可以找到对应的rild文件。socket表示为这个守护进程分配一个socket资源,这个socket资源可以在/dev/socket/下找到rild。也就是本文要这里最关键的地方,socket能不能通就看守护进程能不能很好的起来。上面 SOCKET_NAME也就是这里定义的字符串(在ril.java和ril.cpp中就有一个字符串常量SOCKET_NAME_RIL,他的值就是rild,和上面的对应)。
如果我们要自定义一个socket来进行通信,我们可以在init.rc的最后面加上
service myserver-daemon /system/bin/server
socket server stream 666
oneshot

system/bin/server就是我们编译生成的服务器程序,在里面我们调用
s_fdListen = android_get_control_socket(“server”);
ret = listen(s_fdListen, n);
s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen);

就可以建立一个服务器端程序。
java只需要使用最上面的代码就可以和native通信了,注意 SOCKET_NAME值必须上下统一和init.rc中的相等,此处为“rild”。这里的oneshot必须有,没有的话,你的server很可能起不来。
剩下的只剩下编译了。
关于编译可以参考ril中的中的Android.mk和rild.c和ril.cpp,自己把头文件挑出即可。
先用mm编译自己加的模块,编译好后,将添加的模块考出,在源码的根目录下make snod。将编译输出文件加到system.img中。最后将system.img和randisk.img拷到sdk对应的平台中。即可。主要这两个img文件都要拷,system.img中有你的可执行程序,而randisk.img中有你的init.rc。userdata.img不确定。
此时只需要用java写一个客户端程序即可。

更多相关文章

  1. Android程序怎样禁止横竖屏切换?
  2. android通过manifest.xml设置程序安装的位置
  3. 安卓程序的入口点
  4. gcc手动编译android可执行程序
  5. AIDL进程间通信详解

随机推荐

  1. 安卓android LinearLayout添加边框
  2. Android(安卓)process
  3. android-浅谈
  4. android JNI (二) 第一个 android工程
  5. Android中背景选择器
  6. JavaScript与Android之间的交互
  7. Android(安卓)开发网址收藏
  8. Android的View动画
  9. SimpleAdapter
  10. Android:ADT 22.2.1 发布