Android应用与framework的socket通信实例

关于Android应用与Framework的socket通信,相信关心这个问题的朋友们已经看过《android使用socket使底层和framework通信》这篇文章,美中不足的是作者只贴出一些关键的代码片段而并没有放出源码。我这里还是以一个能实际运行的例子为基础来讲,这样也方便大家学习。

首先看一下效果,如下图。我填写姓名"Potter",选择性别"Mr"然后点击发送,底层socket收到消息后将消息直接返回给我,我将返回的结果(Mr.Potter)直接显示在Result。


ok,有了初步了解后我们现在来看一下如何一步步实现这个例子。

1、配置init.rc。我在init.rc加入如下配置

  1. service htfskservice /system/bin/htfsk  
  2. socket htfsk stream 666 system system  
  3. oneshot  

这里配置了一个名为 “htfskservice” 的服务,手机开机后该服务会自启动并运行/system/bin目录下的脚本htfsk(步骤二将提到如何生成这个脚本)。

同时这里还配置了一个名为 "htfsk" 的socket,并且只有拥有system权限的应用才允许连接这个socket,如何使应用获取system权限可以参考http://my.unix-center.net/~Simon_fu/?p=531这篇文章。


2、编写socket服务端代码,生成可执行脚本htfsk。


首先来看下socket服务端代码 htfsk.c ,内容如下:

  1. #define SOCKET_NAME "htfsk"  
  2.   
  3. #include <stdio.h>  
  4. #include <stdlib.h>  
  5. #include <errno.h>  
  6. #include <string.h>  
  7. #include <sys/types.h>  
  8. #include <netinet/in.h>  
  9. #include <sys/socket.h>  
  10. #include <sys/wait.h>  
  11. #include <sys/un.h>  
  12. #include <cutils/sockets.h>  
  13. #include <utils/Log.h>  
  14. #include <android/log.h>  
  15.   
  16.   
  17. int main(){  
  18.     char log[200];   
  19.   
  20.     int connect_number = 6;  
  21.     int fdListen = -1, new_fd = -1;  
  22.     int ret;  
  23.     struct sockaddr_un peeraddr;  
  24.     socklen_t socklen = sizeof (peeraddr);  
  25.     int numbytes ;  
  26.     char buff[256];  
  27.     //这一步很关键,就是获取init.rc中配置的名为 "htfsk" 的socket  
  28.     fdListen = android_get_control_socket(SOCKET_NAME);  
  29.     if (fdListen < 0) {  
  30.     sprintf(log,"Failed to get socket '" SOCKET_NAME "' errno:%d", errno);  
  31.     __android_log_write(ANDROID_LOG_DEBUG,"FTM_JNI",log);   
  32.     exit(-1);  
  33.     }  
  34.     //开始监听  
  35.     ret = listen(fdListen, connect_number);      
  36.       
  37.     sprintf(log,"Listen result %d",ret);  
  38.     __android_log_write(ANDROID_LOG_DEBUG,"FTM_JNI",log);   
  39.       
  40.     if (ret < 0) {  
  41.         perror("listen");  
  42.         exit(-1);  
  43.     }  
  44.     //等待Socket客户端发启连接请求  
  45.     new_fd = accept(fdListen, (struct sockaddr *) &peeraddr, &socklen);  
  46.     sprintf(log,"Accept_fd %d",new_fd);  
  47.     __android_log_write(ANDROID_LOG_DEBUG,"FTM_JNI",log);   
  48.     if (new_fd < 0 ) {  
  49.         sprintf(log,"%d",errno);  
  50.         __android_log_write(ANDROID_LOG_DEBUG,"FTM_JNI",log);   
  51.         perror("accept error");  
  52.         exit(-1);  
  53.     }  
  54.       
  55.     while(1){  
  56.     //循环等待Socket客户端发来消息  
  57.     __android_log_write(ANDROID_LOG_DEBUG,"FTM_JNI","Waiting for receive");  
  58.     if((numbytes = recv(new_fd,buff,sizeof(buff),0))==-1){  
  59.         sprintf(log,"%d",errno);  
  60.         __android_log_write(ANDROID_LOG_DEBUG,"FTM_JNI",log);   
  61.         perror("recv");  
  62.         continue;  
  63.     }  
  64.     //发送消息回执给Socket客户端  
  65.     if(send(new_fd,buff,strlen(buff),0)==-1)  
  66.     {  
  67.         perror("send");  
  68.         close(new_fd);  
  69.         exit(0);  
  70.     }         
  71.     }  
  72.       
  73.     close(new_fd);  
  74.     close(fdListen);  
  75.     return 0;  
  76. }  


写好服务端代码后我们要将他编译成可执行脚本htfsk,编译的Android.mk内容如下:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE_TAGS :=optional
LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
LOCAL_SHARED_LIBRARIES := libcutils liblog
LOCAL_MODULE:= htfsk
LOCAL_SRC_FILES:=htfsk.c
LOCAL_PRELINK_MODULE := false
include $(BUILD_EXECUTABLE)

编译成功后就会在/system/bin/目录下找到生成的可执行脚本htfsk


3、编写客户端java代码。核心代码如下:

  1. import java.io.BufferedReader;  
  2. import java.io.IOException;  
  3. import java.io.InputStreamReader;  
  4. import java.io.PrintWriter;  
  5.   
  6. import android.net.LocalSocket;  
  7. import android.net.LocalSocketAddress;  
  8. import android.util.Log;  
  9.   
  10. /** 
  11.  * Socket客户端 
  12.  *  
  13.  * @author lai_zs 
  14.  * @date:2012-3-17 下午12:15:09 
  15.  */  
  16. public class SocketClient {  
  17.     private final String SOCKET_NAME = "htfsk";  
  18.     private LocalSocket client;  
  19.     private LocalSocketAddress address;  
  20.     private boolean isConnected = false;  
  21.     private int connetTime = 1;  
  22.   
  23.     public SocketClient() {  
  24.         client = new LocalSocket();  
  25.         address = new LocalSocketAddress(SOCKET_NAME, LocalSocketAddress.Namespace.RESERVED);  
  26.         new ConnectSocketThread().start();  
  27.     }  
  28.   
  29.     /** 
  30.      * 发送消息 
  31.      * @param msg 
  32.      * @return 返回Socket服务端的消息回执 
  33.      */  
  34.     public String sendMsg(String msg) {  
  35.         if (!isConnected) {  
  36.             return "Connect fail";  
  37.         }  
  38.         try {  
  39.             BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));  
  40.             PrintWriter out = new PrintWriter(client.getOutputStream());  
  41.             out.println(msg);  
  42.             out.flush();  
  43.             return in.readLine();  
  44.         } catch (IOException e) {  
  45.             e.printStackTrace();  
  46.         }  
  47.         return "Nothing return";  
  48.     }  
  49.   
  50.     /** 
  51.      * 异步连接Socket,如果连接不上会尝试重复连接十次 
  52.      *  
  53.      * @author Administrator 
  54.      *  
  55.      */  
  56.     private class ConnectSocketThread extends Thread {  
  57.         @Override  
  58.         public void run() {  
  59.             while (!isConnected && connetTime <= 10) {  
  60.                 try {  
  61.                     sleep(1000);  
  62.                     Log.i("SocketClient","Try to connect socket;ConnectTime:"+connetTime);  
  63.                     client.connect(address);  
  64.                     isConnected = true;  
  65.                 } catch (Exception e) {  
  66.                     connetTime++;  
  67.                     isConnected = false;  
  68.                     Log.i("SocketClient","Connect fail");  
  69.                 }  
  70.             }  
  71.         }  
  72.     }  
  73.   
  74.     /** 
  75.      * 关闭Socket 
  76.      */  
  77.     public void closeSocket() {  
  78.         try {  
  79.             client.close();  
  80.         } catch (IOException e) {  
  81.             e.printStackTrace();  
  82.         }  
  83.     }  
  84.   
  85. }  


总结:经过以上三个步骤本实例就基本完成了,源码工程MySocket我已经上传至http://download.csdn.net/detail/goleftgoright/4183596


工程MySocket使用步骤:

1、配置init.rc。

2、将工程MySocket拷贝到android源码的/packages/apps目录下编译就可以了。


编译成功后就可以刷机了,手机开机启动后可以看到 /dev/socket 目录下服务端Socket已经成功启动了,如下图:


再来试一下,微笑





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值