android通信_android蓝牙通信 - CSDN
精华内容
参与话题
  • android网络通信(十二)

    千次阅读 2019-05-11 11:53:06
    App开发常用的一些网络通信技术,主要包括如何使用多线程完成异步操作、如何进行HTTP接口调用与图片获取、如何实现文件上传和下载操作、如何运用Socket通信技术。 一、 多 线 程 介绍多线程技术在App开发中的具体...

    App开发常用的一些网络通信技术,主要包括如何使用多线程完成异步操作、如何进行HTTP接口调用与图片获取、如何实现文件上传和下载操作、如何运用Socket通信技术。

    一、 多  线  程 

    介绍多线程技术在App开发中的具体运用,首先说明如何利用Message配合Handler完成主线程与分线程之间的简单通信;然后阐述进度对话框的用法,以及如何自定义实现文本进度条与文本进度圈;接着讲述异步任务AsyncTask的具体用法和注意事项;最后分析异步服务IntentService的实现原理和开发步骤。

      1.消息传递Message

               Android系统存在限制,只有主线程才能直接操作界面,因此分线程想修改界面就得另想办法。

              多线程技术并非单单用于拍照预览,还用于网络通信、后台服务等耗时场合,并且这些场合往往希望操纵现有的界                   面。这要求有一种用于线程之间相互通信的机制。

               为此,Android设计了一个Message消息工具,通过结合Handler与Message可简单有效地实现线程之间的通信。                     分线程将消息传递给主线程,再由主线程来操作界面。

    主线程与分线程之间传递消息的步骤

              1). 在主线程中构造一个Handler对象,并启动分线程

                        启动分线程有两种方式,既可通过Handler对象的post方法启动Thread,也可直接调用Thread对象的start方                      法。

              2). 在分线程中构造一个Message对象的消息包

                       Message是多线程通信中的消息包裹,类似于Intent机制的Bundle工具。

              3). 在分线程中通过Handler对象将Message消息发出去

                       处理器Handler的消息发送操作主要是各类send方法。

             4). 主线程中的Handler对象处理接收到的消息

                      主线程根据收到的Message消息内容分别进行相应处理。

      2.进度对话框ProgressDialog

                      分线程在处理事务期间不允许用户继续操作界面控件,这时可通过进度对话框ProgressDialog提示用户等待。                               下面是进度对话框的常用方法。

                            setTitle:设置对话框的标题文本。

                            setMessage:设置对话框的消息内容。

                            setProgressStyle:设置进度条的样式。

                            setProgress:设置当前进度的数值。

                            show:显示对话框。

                            dismiss:关闭对话框。

    进度对话框的展示效果

    自定义进度条(上)

               (1). 在长条样式中增加文字说明

                         1)通过自定义层次图形修改长条样式的展示效果。

                          2)重写ProgressBar的onDraw方法,往进度条上添加指定文本。

    自定义进度条(下)

               (2). 在圆圈进度中增加文字说明

                          仿照“ 圆弧进度动画”,先画个背景圆环,再根据进度比例画个前景圆弧,最后在圆心处添加进度文本。

      3.异步任务AsyncTask

                       Android提供了AsyncTask这个轻量级的异步任务工具,内部已经封装好Thread+Handler的线程通信机制。

                       AsyncTask是一个模板类(AsyncTask<Params, Progress, Result>),它的模板参数说明如下。

                                       Params:任务启动时的输入参数。

                                       Progress:任务执行过程中的进度。

                                       Result:任务执行完的结果参数

    如何使用AsyncTask(上)

                   开发者自定义的任务类需要实现以下方法。

                             onPreExecute:准备执行任务时触发。

                             doInBackground:在后台执行的业务处理。网络请求等异步处理操作都放在该方法中。注意,该方法运                                行于分线程,不能直接操作界面。

                              onProgressUpdate:在doInBackground方法中调用publishProgress方法时触发。该方法通常用于在处理                              过程中刷新进度条。

                               onPostExecute:任务执行完成时触发。

                               onCancelled :调用任务对象的cancel方法时触发。

    如何使用AsyncTask(下)

                    AsyncTask有如下可直接调用的启停方法。

                                execute:开始执行异步处理任务。

                                executeOnExecutor:以指定的线程池模式执行任务。

                                publishProgress:更新进度。

                                get:获取处理结果。

                                cancel:取消任务。

                                isCancelled:判断该任务是否取消。

                                getStatus:获取任务状态。

    使用AsyncTask的注意事项

                  AsyncTask在简单场合已经足够使用,如果要用于大量并发处理,就要注意以下两点:

                              (1)AsyncTask默认的线程池模式是SERIAL_EXECUTOR,即按照先后顺序依次调用。假设有两个网                                            络请求任务,第一个是文件下载,第二个是接口调用,那么接口调用任务会等待文件下载完毕后执行,                                          而不是在调用时立刻执行。                                     

                                (2)由于顺序模式存在排队等待的情况,因此Android提供了executeOnExecutor方法,允许开发者指                                           定任务线程池。但该线程池的最大线程个数是CPU个数的两倍再加1,所以线程池的处理能力依赖于手                                           机的CPU数量。

      4. 异步服务IntentService

                后台服务经常要做一些耗时操作,比如批量处理、文件导入、网络访问等,此时不应该影响用户在界面上的操                             作,而应该开启分线程执行耗时操作。可以通过Thread+Handler机制实现异步处理,也可以通过Android封装好的                         异步服务IntentService处理。

                  使用IntentService有两个好处:

                       (1)免去复杂的消息通信流程;

                       (2)处理完成后无须手工停止服务,开发者可集中精力进行业务逻辑的编码。

    IntentService的实现步骤

                       SDK源码里的IntentService实现步骤如下:

                      (1)创建异步服务时,初始化分线程的Handler对象。

                      (2)异步服务开始运行时,通过Handler对象将请求数据送给分线程。

                      (3)分线程在Handler对象的handleMessage方法中,先通过onHandleIntent方法执行具体的事务处理,再调                          用stopSelf结束指定标识的服务。

    使用IntentService的注意事项

                      (1)增加一个构造方法,并分配内部线程的唯一名称。

                      (2)onStartCommand方法要调用父类的onStartCommand,因为父类方法会向分线程传递消息。

                      (3)耗时处理的业务代码要写在onHandleIntent方法中,不可写在onStartCommand方法中。因为                                               onHandleIntent方法位于分线程,而onStartCommand方法位于主线程。

                      (4)IntentService实现了onStart方法,却未实现onBind方法,意味着异步服务只能用普通方式启停,不能用                               绑定方式启停。

    二、HTTP接口访问

           介绍HTTP接口访问的相关技术与具体使用,首先说明如何利用连接管理器ConnectivityManager检测网络连接的状态;然后阐述App用于接口调用的移动数据格式JSON的构建与解析;接着举例说明通过HttpURLConnection实现基本的接口调用;最后讲述利用HttpURLConnection从网络获取小图片的方法。

      1.网络连接检查

               添加网络权限配置后,可利用连接管理器ConnectivityManager检测网络连接。

               调用连接管理器对象的getActiveNetworkInfo方法,返回一个NetworkInfo实例,通过该实例可获取详细的网络连接               信息。

               下面是NetworkInfo的常用方法。

                      getType:获取网络类型。

                     getState:获取网络状态。状态为CONNECTED表示已连接。

                     getSubtype:获取网络子类型。

    网络连接的检查结果

      2. 移动数据格式JSON

                网络通信的交互数据格式有两大类,分别是JSON和XML 。

                对于App来说,基本采用JSON格式与服务器通信。

    JSON相比XML的优势主要有两个:

              (1)手机流量很贵,表达同样的信息,JSON串比XML串短很多。

              (2) JSON串解析得更快,也更省电,XML不但慢而且耗电。

    如何解析json串(上)

                Android自带JSON解析工具,提供对下列两个对象的解析处理:

                1). JSONObject

                          JSONObject的常用方法如下:

                           构造函数:从指定字符串构造一个JSONObject对象。

                           getJSONObject:获取指定名称的JSONObject对象。

                           getString:获取指定名称的字符串。

                           getInt:获取指定名称的整型数。

                           getDouble:获取指定名称的双精度数。

                           getBoolean:获取指定名称的布尔数。

                           getJSONArray:获取指定名称的JSONArray数组对象。

                           put:添加一个JSONObject对象。

    如何解析json串(下)

                         2). JSONArray

                                 JSONArray的常用方法如下:

                                 length:获取JSONArray数组的长度。

                                 getJSONObject:获取JSONArray数组在指定位置的JSONObject对象。

                                 put:往JSONArray数组中添加一个JSONObject对象

      3.JSON串与实体类自动转换

                                json解析除了系统自带的org.json,谷歌公司也提供了一个增强库gson,专门用于json串的自动解析。

                               由于gson是第三方库,因此首先要修改模块的build.gradle文件,在里面的dependencies节点下添加下                                 面一行配置,表示导入指定版本的gson库:

                                   implementation "com.google.code.gson:gson:2.8.2"

    如何使用gson库

                               在java源码的文件头部添加如下一行导入语句,表示后面会用到Gson工具类:

                                     import com.google.gson.Gson;

                               Gson常用的方法有两个:

                               (1)一个方法名叫toJson,可把数据对象转换为json字符串;

                               (2)另一个方法名叫fromJson,可将json字符串自动解析为数据对象。

      4. HTTP接口调用

                              HTTP接口调用的代码标准有两个,分别是HttpURLConnection与HttpClient。

                              移动端的代码标准基本采用更轻量级的HttpURLConnection。

                              HTTP接口调用主要有GET和POST两种方式:

                                              (1)GET方式只是简单的数据获取操作,类似于数据库的查询操作;

                                              (2)POST方式有提交具体的表单信息,类似于数据库的增、删、改操作。

    如何使用HttpURLConnection

                            HttpURLConnection实例从URL对象的openConnection方法获得。

                            下面是它的常用方法。

                             setRequestMethod:设置请求类型。

                             setConnectTimeout:设置连接的超时时间。

                             setRequestProperty:设置请求包头的属性信息。

                             getOutputStream:获取HTTP输出流。在此写入要发送的数据。

                             connect:建立HTTP连接。

                             getInputStream:获取HTTP输入流。在此读出接收的数据。

                             getResponseCode:获取HTTP返回码。

                             disconnect:断开HTTP连接。

    HTTP调用的特殊情况处理

                             HTTP访问还要处理好几种特殊情况,否则就不会正常工作。常见的特殊情况有两种:

                                      1. URL串中对汉字的转义处理

                                                 使用GET方式传递请求数据,参数放在URL中直接传送过去。如果参数值有汉字,就进行                                                       UTF8编码转义处理,比如“你”要转为“%E4%BD%A0”。同理,对于服务器返回的UTF8编码也要                                                      进行反转义。

                                      2. 返回内容为压缩数据时的解压处理

                                                 HTTP请求的包头带有Accept-Encoding:gzip,deflate,表示客户端支持gzip压缩。服务器可                                                能返回gzip压缩的应答数据,此时应答包头中会有Content-Encoding:gzip。此时压缩数据必须先                                                  解压才能正常读取。

    HTTP接口调用的实现例子

                                利用Google Map的开放API,通过HTTP调用传入经纬度的数值,然后对方返回一个JSON格式的地址                                       信息字符串,通过解析JSON串就能得到具体的地址。

                                 下面是根据经纬度成功获取地址信息的效果图。

      5.HTTP图片获取

                           HttpURLConnection还可用于获取网络小图片。比如验证码图片、头像图标等,这些小图不大,一般也无                              须缓存,可直接从网络上获取最新的图片。

                          通过HttpURLConnection获取图片的关键代码如下,主要是利用BitmapFactory的decodeStream方法得到位                              图数据:            

                           // 从HTTP连接获取输入流        

                          InputStream is = conn.getInputStream();      

                          // 对输入流中的数据进行解码,得到位图对象        

                           resp_data.bitmap = BitmapFactory.decodeStream(is);

    HTTP图片获取的实现效果

    三、上传和下载

                     介绍App与服务器之间上传文件和下载文件的实现与管理,首先对下载管理器DownloadManager进行详细说明;然后              阐述基于Fragment技术的文件对话框实现;最后介绍通过HttpURLConnection的POST方式如何实现文件的上传操作。

    1. 下载管理器DownloadManager

                使用HttpURLConnection虽然可以获取小图片,但是这么做有诸多限制,比如:

                (1)无法断点续传,一旦中途失败,只能从头开始获取。

                (2)只能获取图片,不能获取其他文件。

                (3)不是真正意义上的下载操作,没法设置下载参数。

       因为下载功能比较常用且业务功能相对统一,所以Android提供了专门的下载工具—— DownloadManager统一管理下载               操作。

    如何使用DownloadManager

                  下载管理器DownloadManager的对象从系统服务

                  Context.DOWNLOAD_SERVICE中获取,具体使用过程分为3步:

                  1). 构建下载请求

                             要想使用下载功能,首先得构建一个下载请求,说明从哪里下载、下载参数是什么、下载的文                                               件保存到哪里等。

                  2). 进行下载操作

                             构建完下载请求才能进行下载的相关操作。

                 3). 查询下载进度

                              如果App自身也想了解当前的下载进度,就要调用下载管理器的query方法。该方法返回结果集的Cursor                           游标,通过游标即可获得下载信息。

    下载服务涉及到的下载事件

                  系统的下载服务还提供3种下载事件,开发者可通过监听对应的广播消息进行相应的处理。

                 1). 下载完成事件 在下载完成时,系统会发出名为DownloadManager.ACTION_DOWNLOAD_COMPLETE的广                             播。

                 2). 下载进行时的通知栏点击事件 在下载过程中,只要用户点击通知栏上的下载任务,系统就会发出行为名称是                              DownloadManager.ACTION_NOTIFICATION_CLICKED的广播。

                 3). 下载完成后的通知栏点击事件 在不同时刻点击通知栏上的下载任务会触发不同的事件。

    动态展示图片下载进度的效果

    2.  文件对话框

                   下载和上传操作涉及文件的保存和打开,就像电脑上的文件对话框,既可选择文件又可保存文件。然而Android                 没有提供现成的文件对话框控件,需要开发者自己实现文件对话框。

                   这里文件对话框的实现采用了DialogFragment。Fragment拥有如下子类,分别用于不同场合。 

                          DialogFragment:用于对话框的碎片。

                          ListFragment:用于列表的碎片,目的是取代ListActivity。

                          PreferenceFragment:用于参数设置页面,目的是取代PreferenceActivity。

                          WebViewFragment:用于网页视图的碎片。

    文件对话框的实现效果

    3.  文件上传

                     文件上传的场合不是很多,通常用于上传用户头像、朋友圈发布图片和视频动态等,而且上传文件需要后端服                    务器配合。

                     Android没有提供专门的文件上传工具,开发者得自己写代码实现上传功能。

                     简单实现文件上传的话,按照HTTP访问的POST流程,只是要采取multipart/form-data的方式分段传输,并加                     入分段传输的边界字符串。

    文件上传的实现效果

            文件上传的效果如下图所示。倘若上传成功,还应给出服务器对应的文件下载地址,这样才好验证上传成功与否。

     四、套接字Socket

                 介绍套接字Socket的技术手段与具体用途,首先说明如何使用网络地址工具InetAddress判断某个网络地址的连通性,然          后阐述Socket技术在计算机网络中所处的层次、应用方向以及基本用法。

    1. 网络地址InetAddress

          检查设备自身与某个网络地址的连通性用到了InetAddress工具,这是对网络地址的一个封装。

          下面介绍该工具的主要方法说明。

                  getByName:根据主机IP或主机名称获取InetAddress对象。

                  getHostAddress:获取主机的IP地址。

                  getHostName:获取主机的名称。

                  isReachable:判断该地址是否可到达,即是否连通。

    检查网络地址连通性的效果

    2. Socket通信

              计算机网络有一个大名鼎鼎的TCP/IP协议,TCP/IP是一个协议组,分为3个层次:

               网络层:包括IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议。

              传输层:包括TCP协议和UDP协议。

              应用层:包括HTTP、FTP、TELNET、SMTP、DNS等协议。

              Socket属于传输层的技术, API实现TCP协议后即可用于HTTP通信,实现UDP协议后即可用于FTP通信,当然也                 可以直接在底层进行点对点通信。

    如何进行Socket编程(上)

                       Android的Socket编程主要使用Socket和ServerSocket两个类:

                     1). Socket

                              Socket是最常用的工具,客户端和服务端都要用到,描述了两边对套接字(Socket)处理的一般行为。主要方                     法如下:

                               connect:连接指定IP和端口。该方法用于客户端连接服务端。

                               getInputStream:获取输入流,即自身收到对方发过来的数据。

                               getOutputStream:获取输入流,即自身向对方发送的数据。

                               getInetAddress:获取网络地址对象。

                                isConnected:判断socket是否连上。

                                isClosed:判断socket是否关闭。

                                close:关闭socket。

    如何进行Socket编程(中)

                      2). ServerSocket ServerSocket仅用于服务端,在运行时不停地侦听指定端口。主要方法如下:

                                构造函数:指定侦听哪个端口。

                               accept:开始接收客户端的连接。有客户端连上时就返回一个Socket对象,若要持续侦听连接,则在循环语句                    中调用该函数。

                               getInetAddress:获取网络地址对象。

                               isClosed:判断socket服务器是否关闭。

                               close:关闭socket服务器。

    如何进行Socket编程(下)

                              举个Socket通信的案例,详细步骤说明如下:

                            (1)首先在客户端与服务端之间建立Socket连接。

                            (2)然后在Activity中启动Socket连接的线程,等待界面向Socket服务器发送消息,并准备接收消息。

                            (3)最后启动Socket服务器(其实一开始就要启动,这样App运行时才能马上连上后端服务器)。

    Socket通信的实现效果

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    展开全文
  • Android中网络通信的几种方式

    千次阅读 2018-06-11 17:16:04
    Android网络编程分为两种:基于http协议的,和基于socket的。 基于Http协议:HttpClient、HttpURLConnection、AsyncHttpClient框架等 基于Socket: (1)针对TCP/IP的Socket、ServerSocket (2)针对UDP/IP的...
    Android网络编程分为两种:基于http协议的,和基于socket的。
    基于Http协议:HttpClient、HttpURLConnection、AsyncHttpClient框架等
    基于Socket:
    (1)针对TCP/IP的Socket、ServerSocket
    (2)针对UDP/IP的DatagramSocket、DatagramPackage
    (3)Apache Mina框架

    一、HttpURLConnection的实现方式
    1. String response = null;  
    2. Url url = new URL(path);  
    3. HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // 新建连接实例  
    4. connection.setConnectTimeout(20000);// 设置连接超时时间,单位毫秒  
    5. //connection.setReadTimeout(20000);// 设置读取数据超时时间,单位毫秒  
    6. connection.setDoInput(true);// 是否打开输入流 true|false  
    7. connection.setRequestMethod(”POST”);// 提交方法POST|GET  
    8. //connection.setUseCaches(false);// 是否缓存true|false  
    9. //connection.setRequestProperty(“accept”, ”*/*”);  
    10. //connection.setRequestProperty(“Connection”, “Keep-Alive”);  
    11. //connection.setRequestProperty(“Charset”, “UTF-8”);  
    12. //connection.setRequestProperty(“Content-Length”, String.valueOf(data.length));  
    13. //connection.setRequestProperty(“Content-Type”, “application/x-www-form-urlencoded”);  
    14. connection.connect();// 打开连接端口  
    15. int responseCode = conn.getResponseCode();  
    16. BufferedReader reader = null;  
    17. if (responseCode == 200) {  
    18.     reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), “utf-8”));  
    19.     StringBuffer buffer = new StringBuffer();  
    20.     String line = ”“;  
    21.     while ((line = reader.readLine()) != null) {  
    22.         buffer.append(line);  
    23.     }  
    24.     response = buffer.toString();  
    25. else {  
    26.     response = ”返回码:”+responseCode;  
    27. }  
    28. reader.close();  
    29. conn.disconnect();  
    String response = null;
    Url url = new URL(path);
    HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // 新建连接实例
    connection.setConnectTimeout(20000);// 设置连接超时时间,单位毫秒
    //connection.setReadTimeout(20000);// 设置读取数据超时时间,单位毫秒
    connection.setDoInput(true);// 是否打开输入流 true|false
    connection.setRequestMethod("POST");// 提交方法POST|GET
    //connection.setUseCaches(false);// 是否缓存true|false
    //connection.setRequestProperty("accept", "*/*");
    //connection.setRequestProperty("Connection", "Keep-Alive");
    //connection.setRequestProperty("Charset", "UTF-8");
    //connection.setRequestProperty("Content-Length", String.valueOf(data.length));
    //connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    connection.connect();// 打开连接端口
    int responseCode = conn.getResponseCode();
    BufferedReader reader = null;
    if (responseCode == 200) {
        reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
        StringBuffer buffer = new StringBuffer();
        String line = "";
        while ((line = reader.readLine()) != null) {
            buffer.append(line);
        }
        response = buffer.toString();
    } else {
        response = "返回码:"+responseCode;
    }
    reader.close();
    conn.disconnect();
    二、HttpClient实现方式
    1. HttpResponse mHttpResponse = null;  
    2. HttpEntity mHttpEntity = null;  
    3. //创建HttpPost对象  
    4. //HttpPost httppost = new HttpPost(path);  
    5. //设置httpPost请求参数  
    6. //httppost.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8));  
    7. HttpGet httpGet = new HttpGet(path);     
    8. HttpClient httpClient = new DefaultHttpClient();  
    9. InputStream inputStream = null;  
    10. BufferedReader bufReader = null;  
    11. String result = ”“;  
    12. // 发送请求并获得响应对象  
    13. mHttpResponse = httpClient.execute(httpGet);//如果是“POST”方式就传httppost   
    14. if (mHttpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {  
    15.     // 获得响应的消息实体  
    16.     mHttpEntity = mHttpResponse.getEntity();  
    17.     // 获取一个输入流  
    18.     inputStream = mHttpEntity.getContent();  
    19.     bufReader = new BufferedReader(new InputStreamReader(inputStream));   
    20.     String line = ”“;  
    21.     while (null != (line = bufReader.readLine())) {  
    22.         result += line;  
    23.     }  
    24.     //result = EntityUtils.toString(mHttpResponse.getEntity());  
    25. }   
    26. if (inputStream != null) {  
    27.     inputStream.close();  
    28. }  
    29. bufReader.close();  
    30. if (httpClient != null) {  
    31.     httpClient.getConnectionManager().shutdown();  
    32. }  
    HttpResponse mHttpResponse = null;
    HttpEntity mHttpEntity = null;
    //创建HttpPost对象
    //HttpPost httppost = new HttpPost(path);
    //设置httpPost请求参数
    //httppost.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8));
    HttpGet httpGet = new HttpGet(path);   
    HttpClient httpClient = new DefaultHttpClient();
    InputStream inputStream = null;
    BufferedReader bufReader = null;
    String result = "";
    // 发送请求并获得响应对象
    mHttpResponse = httpClient.execute(httpGet);//如果是“POST”方式就传httppost 
    if (mHttpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
        // 获得响应的消息实体
        mHttpEntity = mHttpResponse.getEntity();
        // 获取一个输入流
        inputStream = mHttpEntity.getContent();
        bufReader = new BufferedReader(new InputStreamReader(inputStream)); 
        String line = "";
        while (null != (line = bufReader.readLine())) {
            result += line;
        }
        //result = EntityUtils.toString(mHttpResponse.getEntity());
    } 
    if (inputStream != null) {
        inputStream.close();
    }
    bufReader.close();
    if (httpClient != null) {
        httpClient.getConnectionManager().shutdown();
    }
    三、实用AsyncHttpClient框架的实现方式:
    1. AsyncHttpClient client = new AsyncHttpClient();    
    2. client.get(url, new AsyncHttpResponseHandler() {    
    3.     @Override    
    4.     public void onSuccess(int i, Header[] headers, byte[] bytes) {                
    5.         String response = new String(bytes, 0, bytes.length, “UTF-8”);                       
    6.     }    
    7.     @Override    
    8.     public void onFailure(int i, Header[] headers, byte[] bytes, Throwable throwable) {    
    9.   
    10.     }    
    11. });   
    AsyncHttpClient client = new AsyncHttpClient();  
    client.get(url, new AsyncHttpResponseHandler() {  
        @Override  
        public void onSuccess(int i, Header[] headers, byte[] bytes) {              
            String response = new String(bytes, 0, bytes.length, "UTF-8");                     
        }  
        @Override  
        public void onFailure(int i, Header[] headers, byte[] bytes, Throwable throwable) {  
    
        }  
    }); 
    四、使用WebView视图组件显示网页。
    1. myWebView.getSettings().setJavaScriptEnabled(true);    
    2. myWebView.setWebViewClient(new WebViewClient() {    
    3.     @Override    
    4.     public boolean shouldOverrideUrlLoading(WebView view, String url) {    
    5.         view.loadUrl(url);    
    6.         return true;    
    7.     }    
    8. });    
    9. myWebView.loadUrl(”http://”+networkAddress);    
    myWebView.getSettings().setJavaScriptEnabled(true);  
    myWebView.setWebViewClient(new WebViewClient() {  
        @Override  
        public boolean shouldOverrideUrlLoading(WebView view, String url) {  
            view.loadUrl(url);  
            return true;  
        }  
    });  
    myWebView.loadUrl("http://"+networkAddress);  

    小提示:

    对于HttpClient和HttpURLConnection我们该怎么选择呢?

    在Android 2.2版本之前,由于HttpClient有较少的bug,因此我们选择它来使用。然而在Android 2.3版本及以后,HttpURLConnection则是最佳的选择。HttpUrlConnection对大部分工作进行了包装,屏蔽了不需要的细节,体积较小,因而非常适用于Android项目。并且HttpUrlConnection直接在系统层面做了缓存策略处理,可以加快重复请求的速度。由于其压缩(GZip)和缓存机制可以有效地减少网络访问的流量,在提升速度和省电方面也起到了较大的作用。对于新的应用程序应该更加偏向于使用HttpURLConnection,因为在后续Google官方会将更多的时间放在优化HttpURLConnection上面。

    展开全文
  • Android 进程间通信的几种实现方式

    万次阅读 2018-05-08 18:10:24
    在不同应用程序之间交互数据(跨进程通讯),在android SDK中提供了4种用于跨进程通讯的方式。这4种方式正好对应于android系统中4种应用程序组件:Activity、Content Provider、Broadcast和Service。其中Activity...

    一、概述

           由于应用程序之间不能共享内存。在不同应用程序之间交互数据(跨进程通讯),在android SDK中提供了4种用于跨进程通讯的方式。这4种方式正好对应于android系统中4种应用程序组件:Activity、Content Provider、Broadcast和Service。其中Activity可以跨进程调用其他应用程序的Activity;Content Provider可以跨进程访问其他应用程序中的数据(以Cursor对象形式返回),当然,也可以对其他应用程序的数据进行增、删、改操 作;Broadcast可以向android系统中所有应用程序发送广播,而需要跨进程通讯的应用程序可以监听这些广播;Service和Content Provider类似,也可以访问其他应用程序中的数据,但不同的是,Content Provider返回的是Cursor对象,而Service返回的是Java对象,这种可以跨进程通讯的服务叫AIDL服务。



     Activity

      Activity的跨进程访问与进程内访问略有不同。虽然它们都需要Intent对象,但跨进程访问并不需要指定Context对象和Activity的 Class对象,而需要指定的是要访问的Activity所对应的Action(一个字符串)。有些Activity还需要指定一个Uri(通过 Intent构造方法的第2个参数指定)。

           在android系统中有很多应用程序提供了可以跨进程访问的Activity,例如,下面的代码可以直接调用拨打电话的Activity。

    1. Intent callIntent = new  Intent(Intent.ACTION_CALL, Uri.parse("tel:12345678" );  
    2. startActivity(callIntent);



    Content Provider 

          Android应用程序可以使用文件或SqlLite数据库来存储数据。Content Provider提供了一种在多个应用程序之间数据共享的方式(跨进程共享数据)。应用程序可以利用Content Provider完成下面的工作

    1. 查询数据
    2. 修改数据
    3. 添加数据
    4. 删除数据

            虽然Content Provider也可以在同一个应用程序中被访问,但这么做并没有什么意义。Content Provider存在的目的向其他应用程序共享数据和允许其他应用程序对数据进行增、删、改操作。
    Android系统本身提供了很多Content Provider,例如,音频、视频、联系人信息等等。我们可以通过这些Content Provider获得相关信息的列表。这些列表数据将以Cursor对象返回。因此,从Content Provider返回的数据是二维表的形式。


    广播(Broadcast) 
          广播是一种被动跨进程通讯的方式。当某个程序向系统发送广播时,其他的应用程序只能被动地接收广播数据。这就象电台进行广播一样,听众只能被动地收听,而不能主动与电台进行沟通。
    在应用程序中发送广播比较简单。只需要调用sendBroadcast方法即可。该方法需要一个Intent对象。通过Intent对象可以发送需要广播的数据。



    Service

    1.利用AIDL Service实现跨进程通信

            这是我个人比较推崇的方式,因为它相比Broadcast而言,虽然实现上稍微麻烦了一点,但是它的优势就是不会像广播那样在手机中的广播较多时会有明显的时延,甚至有广播发送不成功的情况出现。 

           注意普通的Service并不能实现跨进程操作,实际上普通的Service和它所在的应用处于同一个进程中,而且它也不会专门开一条新的线程,因此如果在普通的Service中实现在耗时的任务,需要新开线程。

           要实现跨进程通信,需要借助AIDL(Android Interface Definition Language)。Android中的跨进程服务其实是采用C/S的架构,因而AIDL的目的就是实现通信接口。

          首先举一个简单的栗子。

          服务端代码如下:

          首先是aidl的代码:

    [java] view plain copy
    1. package com.android.service;  
    2.   
    3. interface IData  
    4. {  
    5.     int getRoomNum();  
    6. }  

    RoomService的代码如下:

    [java] view plain copy
    1. package com.android.service;  
    2.   
    3. import android.app.Service;  
    4. import android.content.Intent;  
    5. import android.os.IBinder;  
    6. import android.os.RemoteException;  
    7.   
    8. public class RoomService extends Service{  
    9.   
    10.     private IData.Stub mBinder=new IData.Stub() {  
    11.           
    12.         @Override  
    13.         public int getRoomNum() throws RemoteException {  
    14.              return 3008;  
    15.         }  
    16.     };  
    17.   
    18.     @Override  
    19.     public IBinder onBind(Intent intent) {  
    20.         return mBinder;  
    21.     }  
    22.   
    23. }  
    AndroidManifest如下:

    [html] view plain copy
    1. <?<span id="19_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="19_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=xml&k0=xml&kdi0=0&luki=8&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="19" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">xml</span></a></span> version="1.0" encoding="utf-8"?>  
    2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
    3.     package="com.android.aidlsampleservice"  
    4.     android:versionCode="1"  
    5.     android:versionName="1.0" >  
    6.   
    7.     <uses-sdk  
    8.         android:minSdkVersion="8"  
    9.         android:targetSdkVersion="17" />  
    10.   
    11.     <application  
    12.         android:allowBackup="true"  
    13.         android:icon="@drawable/ic_launcher"  
    14.         android:label="@string/app_name"  
    15.         android:theme="@<span id="20_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="20_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=style&k0=style&kdi0=0&luki=5&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="20" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">style</span></a></span>/AppTheme" >        
    16.         <service android:name="com.android.service.RoomService">  
    17.             <intent-filter>  
    18.                 <action android:name="com.aidl.service.room"/>  
    19.             </intent-filter>  
    20.         </service>  
    21.     </application>  
    22.   
    23. </manifest>  
    然后运行该Service所在的Project即可。

    客户端代码如下:

    注意客户端也要有aidl文件,所以最简单的办法就是将Service端中aidl所在的包直接复制过去。另外要注意的是在onDestroy中要解除和Service的绑定。

    MainActivity.java的代码如下:

    [java] view plain copy
    1. package com.example.aidlsampleclient;  
    2.   
    3. import com.android.service.IData;  
    4.   
    5. import android.os.Bundle;  
    6. import android.os.IBinder;  
    7. import android.os.RemoteException;  
    8. import android.app.Activity;  
    9. import android.content.ComponentName;  
    10. import android.content.Intent;  
    11. import android.content.ServiceConnection;  
    12. import android.util.Log;  
    13. import android.view.Menu;  
    14. import android.widget.Button;  
    15. import android.widget.Toast;  
    16. import android.view.View;  
    17.   
    18. public class MainActivity extends Activity implements View.OnClickListener{  
    19.   
    20.       
    21.     private static final String TAG="MainActivity";  
    22.     private static final String ROOM_SERVICE_ACTION="com.aidl.service.room";  
    23.       
    24.     private Button bindServiceButton;  
    25.     private Button getServiceButton;  
    26.       
    27.       
    28.     IData mData;  
    29.       
    30.     private ServiceConnection conn=new ServiceConnection()  
    31.     {  
    32.   
    33.         @Override  
    34.         public void onServiceConnected(ComponentName name, IBinder service) {  
    35.           
    36.             Log.i(TAG,"----------------onServiceConnected--------");  
    37.             mData=IData.Stub.asInterface(service);  
    38.         }  
    39.   
    40.         @Override  
    41.         public void onServiceDisconnected(ComponentName name) {  
    42.           
    43.             Log.i(TAG,"----------------onServiceDisconnected-------------");  
    44.             mData=null;  
    45.               
    46.         }  
    47.           
    48.     };  
    49.       
    50.     private void initView()  
    51.     {  
    52.         bindServiceButton=(Button)findViewById(R.id.bindServiceButton);  
    53.         getServiceButton=(Button)findViewById(R.id.getServiceButton);  
    54.         bindServiceButton.setOnClickListener(this);  
    55.         getServiceButton.setOnClickListener(this);  
    56.     }  
    57.     @Override  
    58.     protected void onCreate(Bundle savedInstanceState) {  
    59.         super.onCreate(savedInstanceState);  
    60.         setContentView(R.layout.activity_main);  
    61.         initView();  
    62.     }  
    63.       
    64.     @Override  
    65.     public void onClick(View v) {  
    66.         // TODO Auto-generated method stub  
    67.         <span id="17_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="17_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=switch&k0=switch&kdi0=0&luki=10&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="17" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch</span></a></span>(v.getId())  
    68.         {  
    69.         case R.id.bindServiceButton:  
    70.             bindService();  
    71.             break;  
    72.         case R.id.getServiceButton:  
    73.             getService();     
    74.              break;  
    75.         default:  
    76.              break;  
    77.         }  
    78.     }  
    79.       
    80.       
    81.     private void bindService()  
    82.     {  
    83.         Intent intent=new Intent();  
    84.         intent.setAction(ROOM_SERVICE_ACTION);  
    85.         bindService(intent,conn,BIND_AUTO_CREATE);  
    86.     }  
    87.       
    88.     private void getService()  
    89.     {  
    90.         try  
    91.         {  
    92.             if(mData!=null)  
    93.             {  
    94.                 int roomNum=mData.getRoomNum();  
    95.                 showLongToast("RoomNum:"+roomNum);  
    96.             }  
    97.               
    98.         }  
    99.         catch(RemoteException ex)  
    100.         {  
    101.             ex.printStackTrace();  
    102.         }  
    103.           
    104.     }  
    105.       
    106.     private void showLongToast(String info)  
    107.     {  
    108.         Toast.makeText(getBaseContext(), info, Toast.LENGTH_LONG).show();  
    109.     }  
    110.   
    111.     @Override  
    112.     public boolean onCreateOptionsMenu(Menu menu) {  
    113.         // Inflate the menu; this adds items to the action bar if it is p<span id="18_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="18_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=res&k0=res&kdi0=0&luki=9&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="18" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">res</span></a></span>ent.  
    114.         getMenuInflater().inflate(R.menu.main, menu);  
    115.         return true;  
    116.     }  
    117.     @Override  
    118.     protected void onDestroy() {  
    119.         // TODO Auto-generated method stub  
    120.         super.onDestroy();  
    121.         unbindService(conn);  
    122.     }  
    123. }  
    activity_main.xml的代码如下:

    [html] view plain copy
    1. <RelativeLayout <span id="14_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="14_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=xml&k0=xml&kdi0=0&luki=8&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="14" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">xml</span></a></span>ns:android="http://schemas.android.com/apk/<span id="15_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="15_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=res&k0=res&kdi0=0&luki=9&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="15" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">res</span></a></span>/android"  
    2.     xmlns:<span id="16_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="16_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=tools&k0=tools&kdi0=0&luki=4&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="16" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">tools</span></a></span>="http://schemas.android.com/tools"  
    3.     android:layout_width="match_parent"  
    4.     android:layout_height="match_parent"  
    5.     android:paddingBottom="@dimen/activity_vertical_margin"  
    6.     android:paddingLeft="@dimen/activity_horizontal_margin"  
    7.     android:paddingRight="@dimen/activity_horizontal_margin"  
    8.     android:paddingTop="@dimen/activity_vertical_margin"  
    9.     tools:context=".MainActivity" >  
    10.   
    11.     <Button   
    12.         android:id="@+id/bindServiceButton"  
    13.         android:layout_width="fill_parent"  
    14.         android:layout_height="wrap_content"  
    15.         android:text="BindService"  
    16.         />  
    17.     <Button  
    18.         android:id="@+id/getServiceButton"  
    19.         android:layout_width="fill_parent"  
    20.         android:layout_height="wrap_content"  
    21.         android:text="GetService"  
    22.         android:layout_below="@id/bindServiceButton"  
    23.         />  
    24.          
    25. </RelativeLayout>  
    运行结果如下:

    bubuko.com,布布扣

          

           然后举一个稍微复杂一点的栗子,注意如果*.aidl文件中含有自定义的对象,那么该对象的类要实现Parcelable接口,并且要新建一个该类的aidl文件,否则会出现could not find import for class com.android.service.XX的错误,其中XX为类名。还是上面的栗子,但是aidl文件中添加了一些新的方法。仍以上面的RoomService为例,

         Service端的代码如下:

         Room类的代码为:

    [java] view plain copy
    1. package com.android.service;  
    2.   
    3. import android.os.Parcel;  
    4. import android.os.Parcelable;  
    5.   
    6. public class Room implements Parcelable{  
    7.   
    8.     //房间号  
    9.     private int roomNum;  
    10.     //房间大小  
    11.     private float roomSpace;  
    12.     //是否有空调  
    13.     private boolean hasAirConditioner;  
    14.     //是否有Wifi  
    15.     private boolean hasWifi;  
    16.     //房间内的装饰风格  
    17.     private String decorativeStyle;  
    18.       
    19.     public static final Parcelable.Creator<Room>CREATOR=new Parcelable.Creator<Room>() {  
    20.   
    21.         @Override  
    22.         public Room createFromParcel(Parcel source) {  
    23.             return new Room(source);  
    24.         }  
    25.   
    26.         @Override  
    27.         public Room[] newArray(int size) {  
    28.             // TODO Auto-generated method stub  
    29.             return null;  
    30.         }  
    31.           
    32.     };  
    33.       
    34.     public Room(int roomNum,float roomSpace,boolean hasAirConditioner,boolean hasWifi,String decorativeStyle)  
    35.     {  
    36.         this.roomNum=roomNum;  
    37.         this.roomSpace=roomSpace;  
    38.         this.hasAirConditioner=hasAirConditioner;  
    39.         this.hasWifi=hasWifi;  
    40.         this.decorativeStyle=decorativeStyle;  
    41.     }  
    42.       
    43.     private Room(Parcel source)  
    44.     {  
    45.         roomNum=source.readInt();  
    46.         roomSpace=source.readFloat();  
    47.         boolean[]tempArray=new boolean[2];  
    48.         source.readBooleanArray(tempArray);  
    49.        hasAirConditioner=tempArray[0];  
    50.        hasWifi=tempArray[1];  
    51.        decorativeStyle=source.readString();   
    52.     }  
    53.       
    54.     @Override  
    55.     public String toString()  
    56.     {  
    57.         StringBuilder sb=new StringBuilder();  
    58.         sb.append("Basic info of room is as follows:\n");  
    59.         sb.append("RoomNum:"+roomNum+"\n");  
    60.         sb.append("RoomSpace:"+roomSpace+"\n");  
    61.         sb.append("HasAirConditioner:"+hasAirConditioner+"\n");  
    62.         sb.append("HasWifi:"+hasWifi+"\n");  
    63.         sb.append("Decorative Style:"+decorativeStyle);  
    64.         return sb.toString();  
    65.           
    66.     }  
    67.       
    68.     @Override  
    69.     public int describeContents() {  
    70.         // TODO Auto-generated method stub  
    71.         return 0;  
    72.     }  
    73.   
    74.     @Override  
    75.     public void writeToParcel(Parcel dest,int flags) {  
    76.         dest.writeInt(roomNum);  
    77.         dest.writeFloat(roomSpace);  
    78.         dest.writeBooleanArray(new boolean[]{hasAirConditioner,hasWifi});  
    79.         dest.writeString(decorativeStyle);        
    80.     }  
    81.   
    82. }  

    Room的声明为:

    [java] view plain copy
    1. package com.android.service;  
    2. parcelable Room;  

    IRoom.aidl的代码为:

    [java] view plain copy
    1. package com.android.service;  
    2. import com.android.service.Room;  
    3.   
    4. interface IRoom  
    5. {  
    6.   Room getRoom();  
    7. }  
    RoomService的代码为:

    [java] view plain copy
    1. package com.android.service;  
    2.   
    3. import android.app.Service;  
    4. import android.content.Intent;  
    5. import android.os.IBinder;  
    6. import android.os.RemoteException;  
    7.   
    8. public class RoomService extends Service{  
    9.   
    10.     private IRoom.Stub mBinder=new IRoom.Stub() {  
    11.           
    12.         @Override  
    13.         public Room getRoom() throws RemoteException {  
    14.             Room room=new Room(3008,23.5f,true,true,"IKEA");  
    15.             return room;          
    16.         }  
    17.     };  
    18.       
    19.     @Override  
    20.     public IBinder onBind(Intent intent) {  
    21.         return mBinder;  
    22.     }  
    23.   
    24. }  
    由于AndroidManifest.xml的代码不变,因而此处不再贴出。下面是客户端的代码:

    [java] view plain copy
    1. package com.example.aidlsampleclient;  
    2. import com.android.service.IRoom;  
    3. import android.os.Bundle;  
    4. import android.os.IBinder;  
    5. import android.os.RemoteException;  
    6. import android.app.Activity;  
    7. import android.content.ComponentName;  
    8. import android.content.Intent;  
    9. import android.content.ServiceConnection;  
    10. import android.util.Log;  
    11. import android.view.Menu;  
    12. import android.widget.Button;  
    13. import android.widget.Toast;  
    14. import android.view.View;  
    15.   
    16. public class MainActivity extends Activity implements View.OnClickListener{  
    17.   
    18.       
    19.     private static final String TAG="MainActivity";  
    20.     //private static final String SERVICE_ACTION="com.aidl.service.data";  
    21.     private static final String ROOM_SERVICE_ACTION="com.aidl.service.room";  
    22.       
    23.     private Button bindServiceButton;  
    24.     private Button getServiceButton;  
    25.       
    26.       
    27.     IRoom mRoom;  
    28.       
    29.     private ServiceConnection conn=new ServiceConnection()  
    30.     {  
    31.   
    32.         @Override  
    33.         public void onServiceConnected(ComponentName name, IBinder service) {  
    34.           
    35.             Log.i(TAG,"----------------onServiceConnected--------");  
    36.             showLongToast("onServiceConnected");  
    37.             mRoom=IRoom.Stub.asInterface(service);  
    38.         }  
    39.   
    40.         @Override  
    41.         public void onServiceDisconnected(ComponentName name) {  
    42.           
    43.             Log.i(TAG,"----------------onServiceDisconnected-------------");  
    44.             mRoom=null;  
    45.               
    46.         }  
    47.           
    48.     };  
    49.       
    50.     private void initView()  
    51.     {  
    52.         bindServiceButton=(Button)findViewById(R.id.bindServiceButton);  
    53.         getServiceButton=(Button)findViewById(R.id.getServiceButton);  
    54.         bindServiceButton.setOnClickListener(this);  
    55.         getServiceButton.setOnClickListener(this);  
    56.     }  
    57.     @Override  
    58.     protected void onCreate(Bundle savedInstanceState) {  
    59.         super.onCreate(savedInstanceState);  
    60.         setContentView(R.layout.activity_main);  
    61.         initView();  
    62.     }  
    63.       
    64.     @Override  
    65.     public void onClick(View v) {  
    66.         // TODO Auto-generated method stub  
    67.         <span id="12_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="12_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=switch&k0=switch&kdi0=0&luki=10&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="12" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch</span></a></span>(v.getId())  
    68.         {  
    69.         case R.id.bindServiceButton:  
    70.             bindService();  
    71.             break;  
    72.         case R.id.getServiceButton:  
    73.             getService();     
    74.              break;  
    75.         default:  
    76.              break;  
    77.         }  
    78.     }  
    79.       
    80.       
    81.     private void bindService()  
    82.     {  
    83.         Intent intent=new Intent();  
    84.         intent.setAction(ROOM_SERVICE_ACTION);  
    85.         bindService(intent,conn,BIND_AUTO_CREATE);  
    86.     }  
    87.       
    88.     private void getService()  
    89.     {  
    90.         if(mRoom!=null)  
    91.         {  
    92.             try  
    93.             {  
    94.                 showLongToast(mRoom.getRoom().toString());  
    95.             }  
    96.             catch (RemoteException e)   
    97.             {  
    98.                 e.printStackTrace();  
    99.             }  
    100.         }  
    101.   
    102.     }  
    103.       
    104.     private void showLongToast(String info)  
    105.     {  
    106.         Toast.makeText(getBaseContext(), info, Toast.LENGTH_LONG).show();  
    107.     }  
    108.   
    109.     @Override  
    110.     public boolean onCreateOptionsMenu(Menu menu) {  
    111.         // Inflate the menu; this adds items to the action bar if it is p<span id="13_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="13_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=res&k0=res&kdi0=0&luki=9&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="13" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">res</span></a></span>ent.  
    112.         getMenuInflater().inflate(R.menu.main, menu);  
    113.         return true;  
    114.     }  
    115.     @Override  
    116.     protected void onDestroy() {  
    117.         // TODO Auto-generated method stub  
    118.         super.onDestroy();  
    119.         unbindService(conn);  
    120.     }  
    121. }  

    注意首先仍然是要将Room,IRoom的代码复制过去,否则会出错。

    运行结果如下:

    bubuko.com,布布扣

    显然,客户端已经成功读取到服务信息。

    注意,上面的所举的栗子其实不只是跨进程,还是跨应用。要注意的是,跨应用一定跨进程,但是跨进程不一定是跨应用。对于跨应用的情况,利用AIDL基本上是较好的解决了问题,但也只是“较好”而已,实际上并不完美,比如,如果要增加一个服务,如果利用AIDL的话,那么又要改写aidl文件,如果是涉及自定义对象,则还要增加自定义对象的声明,而且这种改变不只是Service端的改变,客户端也要跟着改变,显然这种解决方案不够优雅。

            那么,有没有更优雅的方法呢?

            当然有,那就是利用Service的onStartCommand(Intent intent, int flags, int startId)方法。

            服务端代码如下:

     

    [java] view plain copy
    1. package com.android.service;  
    2.   
    3. import android.app.Service;  
    4. import android.content.BroadcastReceiver;  
    5. import android.content.Context;  
    6. import android.content.Intent;  
    7. import android.content.IntentFilter;  
    8. import android.os.IBinder;  
    9. import android.os.RemoteException;  
    10. import android.util.Log;  
    11. import android.widget.Toast;  
    12.   
    13. public class RoomService extends Service{  
    14.   
    15.     private static final String TAG="RoomService";  
    16.     private static final int CLEAN_SERVICE=0x1;  
    17.     private static final int ORDER_SERVICE=0x2;  
    18.     private static final int PACKAGE_SERVICE=0x3;  
    19.     private static final String SERVICE_KEY="ServiceName";    
    20.     @Override  
    21.     public void onStart(Intent intent, int startId) {  
    22.        showLog("onStart");  
    23.     }  
    24.   
    25.     @Override  
    26.     public int onStartCommand(Intent intent, int flags, int startId) {  
    27.         //String action=intent.getAction();  
    28.         Log.i(TAG,"onStartCommand");  
    29.           
    30.         int actionFlag=intent.getIntExtra(SERVICE_KEY, -1);  
    31.         <span id="11_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="11_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=switch&k0=switch&kdi0=0&luki=10&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="11" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch</span></a></span>(actionFlag)  
    32.         {  
    33.         case CLEAN_SERVICE:  
    34.             showShortToast("Start Clean Service Right Now");  
    35.             break;  
    36.         case ORDER_SERVICE:  
    37.             showShortToast("Start Order Service Right Now");  
    38.             break;  
    39.         case PACKAGE_SERVICE:  
    40.             showShortToast("Start Package Service Right Now");  
    41.             break;  
    42.         default:  
    43.             break;  
    44.         }  
    45.         return super.onStartCommand(intent, flags, startId);  
    46.     }  
    47.   
    48.     private void showLog(String info)  
    49.     {  
    50.         Log.i(TAG,info);  
    51.     }  
    52.       
    53.     private void showShortToast(String info)  
    54.     {  
    55.         Toast.makeText(getBaseContext(), info, Toast.LENGTH_SHORT).show();  
    56.     }  
    57.     @Override  
    58.     public void onDestroy() {  
    59.         // TODO Auto-generated method stub  
    60.         showLog("onDestroy");  
    61.         super.onDestroy();  
    62.     }  
    63.   
    64.     @Override  
    65.     public void onCreate() {  
    66.         // TODO Auto-generated method stub  
    67.         showLog("onCreate");  
    68.         super.onCreate();  
    69.     }  
    70.   
    71.   
    72.     @Override  
    73.     public IBinder onBind(Intent intent) {  
    74.         showLog("onBind");  
    75.         return null;  
    76.     }  
    77.   
    78.     @Override  
    79.     public boolean onUnbind(Intent intent) {  
    80.         showLog("onUnbind");  
    81.         return super.onUnbind(intent);  
    82.     }  
    83.       
    84. }  
    客户端代码如下:

    [java] view plain copy
    1. package com.example.aidlsampleclient;  
    2. import com.android.service.IRoom;  
    3. import com.android.service.RoomService;  
    4.   
    5. import android.os.Bundle;  
    6. import android.os.IBinder;  
    7. import android.os.RemoteException;  
    8. import android.app.Activity;  
    9. import android.content.ComponentName;  
    10. import android.content.Intent;  
    11. import android.content.ServiceConnection;  
    12. import android.util.Log;  
    13. import android.view.Menu;  
    14. import android.widget.Button;  
    15. import android.widget.Toast;  
    16. import android.view.View;  
    17.   
    18. public class MainActivity extends Activity implements View.OnClickListener{  
    19.   
    20.     private static final String TAG="MainActivity";  
    21.     private static final String ROOM_SERVICE_ACTION="com.aidl.service.room";  
    22.       
    23.     private static final int CLEAN_SERVICE=0x1;  
    24.     private static final int ORDER_SERVICE=0x2;  
    25.     private static final int PACKAGE_SERVICE=0x3;  
    26.       
    27.     private static final String SERVICE_KEY="ServiceName";  
    28.       
    29.     private Button cleanButton;  
    30.     private Button orderButton;  
    31.     private Button packageButton;  
    32.       
    33.     private void initView()  
    34.     {  
    35.         cleanButton=(Button)findViewById(R.id.cleanButton);  
    36.         orderButton=(Button)findViewById(R.id.orderButton);  
    37.         packageButton=(Button)findViewById(R.id.packageButton);  
    38.       
    39.         cleanButton.setOnClickListener(this);  
    40.         orderButton.setOnClickListener(this);  
    41.         packageButton.setOnClickListener(this);  
    42.     }  
    43.     @Override  
    44.     protected void onCreate(Bundle savedInstanceState) {  
    45.         super.onCreate(savedInstanceState);  
    46.         setContentView(R.layout.activity_main);  
    47.         initView();  
    48.     }  
    49.       
    50.     @Override  
    51.     public void onClick(View v) {  
    52.         // TODO Auto-generated method stub  
    53.         <span id="9_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="9_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=switch&k0=switch&kdi0=0&luki=10&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="9" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch</span></a></span>(v.getId())  
    54.         {  
    55.         case R.id.cleanButton:  
    56.             cleanAction();  
    57.             break;  
    58.         case R.id.orderButton:  
    59.             orderAction();  
    60.             break;  
    61.         case R.id.packageButton:  
    62.             packageAction();  
    63.             break;  
    64.         default:  
    65.              break;  
    66.         }  
    67.     }  
    68.           
    69.     private void cleanAction()  
    70.     {  
    71.         startAction(ROOM_SERVICE_ACTION,CLEAN_SERVICE);  
    72.     }  
    73.       
    74.     private void orderAction()  
    75.     {  
    76.         startAction(ROOM_SERVICE_ACTION,ORDER_SERVICE);  
    77.     }  
    78.       
    79.     private void packageAction()  
    80.     {  
    81.         startAction(ROOM_SERVICE_ACTION,PACKAGE_SERVICE);  
    82.     }  
    83.       
    84.     private void startAction(String actionName,int serviceFlag)  
    85.     {  
    86.         //Intent intent=new Intent(this,RoomService.class);  
    87.         Intent intent=new Intent();  
    88.         intent.setAction(actionName);  
    89.         intent.putExtra(SERVICE_KEY, serviceFlag);  
    90.         this.startService(intent);  
    91.     }  
    92.       
    93.     private void showLongToast(String info)  
    94.     {  
    95.         Toast.makeText(getBaseContext(), info, Toast.LENGTH_LONG).show();  
    96.     }  
    97.   
    98.     @Override  
    99.     public boolean onCreateOptionsMenu(Menu menu) {  
    100.         // Inflate the menu; this adds items to the action bar if it is p<span id="10_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="10_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=res&k0=res&kdi0=0&luki=9&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="10" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">res</span></a></span>ent.  
    101.         getMenuInflater().inflate(R.menu.main, menu);  
    102.         return true;  
    103.     }  
    104.     @Override  
    105.     protected void onDestroy() {  
    106.         // TODO Auto-generated method stub  
    107.         super.onDestroy();  
    108.     }  
    109. }  
    运行结果如下:

    bubuko.com,布布扣


    bubuko.com,布布扣



    bubuko.com,布布扣



    显然,此时客户端顺利获取了服务。

            上面举的是跨应用的例子,如果是在同一个应用的不同进程的话,则有更简单的实现方法。

            RoomService的代码如下:

    [java] view plain copy
    1. <<span id="6_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="6_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=span&k0=span&kdi0=0&luki=2&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="6" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">span</span></a></span> <span id="7_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="7_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=style&k0=style&kdi0=0&luki=5&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="7" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">style</span></a></span>="font-size:18px;">package com.android.service;  
    2.   
    3. import com.android.actions.Actions;  
    4.   
    5. import android.app.Service;  
    6. import android.content.BroadcastReceiver;  
    7. import android.content.Context;  
    8. import android.content.Intent;  
    9. import android.content.IntentFilter;  
    10. import android.os.IBinder;  
    11. import android.os.RemoteException;  
    12. import android.util.Log;  
    13. import android.widget.Toast;  
    14.   
    15. public class RoomService extends Service{  
    16.   
    17.     private static final String TAG="RoomService";  
    18.     @Override  
    19.     public void onStart(Intent intent, int startId) {  
    20.        showLog("onStart");  
    21.     }  
    22.   
    23.     @Override  
    24.     public int onStartCommand(Intent intent, int flags, int startId) {  
    25.         //String action=intent.getAction();  
    26.         Log.i(TAG,"onStartCommand");  
    27.         String action=intent.getAction();  
    28.         if(Actions.CLEAN_ACTION.equals(action))  
    29.         {      
    30.             showShortToast("Start Clean Service Right Now");  
    31.         }  
    32.         else if(Actions.ORDER_ACTION.equals(action))  
    33.         {  
    34.             showShortToast("Start Order Service Right Now");  
    35.         }  
    36.         else if(Actions.PACKAGE_ACTION.equals(action))  
    37.         {  
    38.             showShortToast("Start Package Service Right Now");  
    39.         }  
    40.         else  
    41.         {  
    42.             showShortToast("Wrong action");  
    43.         }  
    44.         return super.onStartCommand(intent, flags, startId);  
    45.     }  
    46.   
    47.     private void showLog(String info)  
    48.     {  
    49.         Log.i(TAG,info);  
    50.     }  
    51.       
    52.     private void showShortToast(String info)  
    53.     {  
    54.         Toast.makeText(getBaseContext(), info, Toast.LENGTH_SHORT).show();  
    55.     }  
    56.     @Override  
    57.     public void onDestroy() {  
    58.         // TODO Auto-generated method stub  
    59.         showLog("onDestroy");  
    60.         super.onDestroy();  
    61.     }  
    62.   
    63.     @Override  
    64.     public void onCreate() {  
    65.         // TODO Auto-generated method stub  
    66.         showLog("onCreate");  
    67.         super.onCreate();  
    68.     }  
    69.   
    70.   
    71.     @Override  
    72.     public IBinder onBind(Intent intent) {  
    73.         showLog("onBind");  
    74.         return null;  
    75.     }  
    76.   
    77.     @Override  
    78.     public boolean onUnbind(Intent intent) {  
    79.         showLog("onUnbind");  
    80.         return super.onUnbind(intent);  
    81.     }  
    82.       
    83. }</<span id="8_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="8_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=span&k0=span&kdi0=0&luki=2&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="8" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">span</span></a></span>>  

            MainActivity的代码如下:

    [java] view plain copy
    1. package com.android.activity;  
    2. import com.android.activity.R;  
    3. import com.android.service.RoomService;  
    4.   
    5. import android.app.Activity;  
    6. import android.content.Intent;  
    7. import android.os.Bundle;  
    8. import android.view.Menu;  
    9. import android.widget.Button;  
    10. import android.widget.Toast;  
    11. import android.view.View;  
    12. import com.android.actions.Actions;  
    13.   
    14. public class MainActivity extends Activity implements View.OnClickListener{  
    15.   
    16.     private static final String TAG="MainActivity";  
    17.   
    18.     private static final String SERVICE_KEY="ServiceName";  
    19.       
    20.     private Button cleanButton;  
    21.     private Button orderButton;  
    22.     private Button packageButton;  
    23.       
    24.     private void initView()  
    25.     {  
    26.         cleanButton=(Button)findViewById(R.id.cleanButton);  
    27.         orderButton=(Button)findViewById(R.id.orderButton);  
    28.         packageButton=(Button)findViewById(R.id.packageButton);  
    29.       
    30.         cleanButton.setOnClickListener(this);  
    31.         orderButton.setOnClickListener(this);  
    32.         packageButton.setOnClickListener(this);  
    33.     }  
    34.     @Override  
    35.     protected void onCreate(Bundle savedInstanceState) {  
    36.         super.onCreate(savedInstanceState);  
    37.         setContentView(R.layout.activity_main);  
    38.         initView();  
    39.     }  
    40.       
    41.     @Override  
    42.     public void onClick(View v) {  
    43.         // TODO Auto-generated method stub  
    44.         <span id="4_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="4_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=switch&k0=switch&kdi0=0&luki=10&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="4" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch</span></a></span>(v.getId())  
    45.         {  
    46.         case R.id.cleanButton:  
    47.             cleanAction();  
    48.             break;  
    49.         case R.id.orderButton:  
    50.             orderAction();  
    51.             break;  
    52.         case R.id.packageButton:  
    53.             packageAction();  
    54.             break;  
    55.         default:  
    56.              break;  
    57.         }  
    58.     }  
    59.           
    60.     private void cleanAction()  
    61.     {  
    62.         startAction(Actions.CLEAN_ACTION);  
    63.     }  
    64.       
    65.     private void orderAction()  
    66.     {  
    67.         startAction(Actions.ORDER_ACTION);  
    68.     }  
    69.       
    70.     private void packageAction()  
    71.     {  
    72.         startAction(Actions.PACKAGE_ACTION);  
    73.     }  
    74.       
    75.     private void startAction(String actionName)  
    76.     {  
    77.         Intent intent=new Intent(this,RoomService.class);  
    78.         intent.setAction(actionName);  
    79.         this.startService(intent);  
    80.     }  
    81.       
    82.     private void showLongToast(String info)  
    83.     {  
    84.         Toast.makeText(getBaseContext(), info, Toast.LENGTH_LONG).show();  
    85.     }  
    86.   
    87.     @Override  
    88.     public boolean onCreateOptionsMenu(Menu menu) {  
    89.         // Inflate the menu; this adds items to the action bar if it is p<span id="5_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="5_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=res&k0=res&kdi0=0&luki=9&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="5" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">res</span></a></span>ent.  
    90.         getMenuInflater().inflate(R.menu.main, menu);  
    91.         return true;  
    92.     }  
    93.     @Override  
    94.     protected void onDestroy() {  
    95.         // TODO Auto-generated method stub  
    96.         super.onDestroy();  
    97.     }  
    98. }  

    从打印的log可看出,客户端每调用一次Context.startService(Intent),Service就会重新执行一次onStartCommand---->onStart;但是使用AIDL的话,绑定服务之后,不会重复执行onStart,显然后者的代价更小。

    Service:前台Service,像我们经常用的天气、音乐其实都利用了前台Service来实现


    展开全文
  • Android串口通信Android Studio)

    万次阅读 多人点赞 2017-12-21 15:23:30
    android 串口通信

    用到谷歌开源serialPort api
    下载链接:serialPort-api

    以下项目用的so库是谷歌原库,没有做修改

    新建项目:

    1、先把下载的api中这些文件拷进项目的相应位置
    这里写图片描述

    SerialPort类是咱们Android可以调用的类,

    jni目录下放着c源码和h头文件,

    jniLibs下面放的就是so库。

    注意:因为用的谷歌原生so库,所以SerialPort类的包名一定要是android_serialport_api,如果想修改这个包名,就需要重新生成对应的so库

    这里写图片描述

    这是SerialPort类,里面的open和close方法在报错,这个不用管。

    2、在build.gradle中添加如下代码:
    这里写图片描述

    sourceSets {
                main { jni.srcDirs = [] }
            }

    3、这样就可以串口通信了
    这是串口操作类:

    package utils;
    
    import android.util.Log;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import android_serialport_api.SerialPort;
    
    /**
     * Created by WangChaowei on 2017/12/7.
     */
    
    public class SerialPortUtils {
    
        private final String TAG = "SerialPortUtils";
        private String path = "/dev/ttyS1";
        private int baudrate = 9600;
        public boolean serialPortStatus = false; //是否打开串口标志
        public String data_;
        public boolean threadStatus; //线程状态,为了安全终止线程
    
        public SerialPort serialPort = null;
        public InputStream inputStream = null;
        public OutputStream outputStream = null;
        public ChangeTool changeTool = new ChangeTool();
    
    
        /**
         * 打开串口
         * @return serialPort串口对象
         */
        public SerialPort openSerialPort(){
            try {
                    serialPort = new SerialPort(new File(path),baudrate,0);
                    this.serialPortStatus = true;
                    threadStatus = false; //线程状态
    
                    //获取打开的串口中的输入输出流,以便于串口数据的收发
                    inputStream = serialPort.getInputStream();
                    outputStream = serialPort.getOutputStream();
    
                    new ReadThread().start(); //开始线程监控是否有数据要接收
            } catch (IOException e) {
                Log.e(TAG, "openSerialPort: 打开串口异常:" + e.toString());
                return serialPort;
            }
            Log.d(TAG, "openSerialPort: 打开串口");
            return serialPort;
        }
    
        /**
         * 关闭串口
         */
        public void closeSerialPort(){
            try {
                inputStream.close();
                outputStream.close();
    
                this.serialPortStatus = false;
                this.threadStatus = true; //线程状态
                serialPort.close();
            } catch (IOException e) {
                Log.e(TAG, "closeSerialPort: 关闭串口异常:"+e.toString());
                return;
            }
            Log.d(TAG, "closeSerialPort: 关闭串口成功");
        }
    
        /**
         * 发送串口指令(字符串)
         * @param data String数据指令
         */
        public void sendSerialPort(String data){
            Log.d(TAG, "sendSerialPort: 发送数据");
    
            try {
                byte[] sendData = data.getBytes(); //string转byte[]
                this.data_ = new String(sendData); //byte[]转string
                if (sendData.length > 0) {
                    outputStream.write(sendData);
                    outputStream.write('\n');
                    //outputStream.write('\r'+'\n');
                    outputStream.flush();
                    Log.d(TAG, "sendSerialPort: 串口数据发送成功");
                }
            } catch (IOException e) {
                Log.e(TAG, "sendSerialPort: 串口数据发送失败:"+e.toString());
            }
    
        }
    
        /**
         * 单开一线程,来读数据
         */
        private class ReadThread extends Thread{
            @Override
            public void run() {
                super.run();
                //判断进程是否在运行,更安全的结束进程
                while (!threadStatus){
                    Log.d(TAG, "进入线程run");
                    //64   1024
                    byte[] buffer = new byte[64];
                    int size; //读取数据的大小
                    try {
                        size = inputStream.read(buffer);
                        if (size > 0){
                            Log.d(TAG, "run: 接收到了数据:" + changeTool.ByteArrToHex(buffer));
                            Log.d(TAG, "run: 接收到了数据大小:" + String.valueOf(size));
                            onDataReceiveListener.onDataReceive(buffer,size);
                        }
                    } catch (IOException e) {
                        Log.e(TAG, "run: 数据读取异常:" +e.toString());
                    }
                }
    
            }
        }
    
        //这是写了一监听器来监听接收数据
        public OnDataReceiveListener onDataReceiveListener = null;
        public static interface OnDataReceiveListener {
            public void onDataReceive(byte[] buffer, int size);
        }
        public void setOnDataReceiveListener(OnDataReceiveListener dataReceiveListener) {
            onDataReceiveListener = dataReceiveListener;
        }
    
    }
    

    4、activity中只贴串口数据监听事件

            //串口数据监听事件
            serialPortUtils.setOnDataReceiveListener(new SerialPortUtils.OnDataReceiveListener() {
                @Override
                public void onDataReceive(byte[] buffer, int size) {
                    Log.d(TAG, "进入数据监听事件中。。。" + new String(buffer));
                    //
                    //在线程中直接操作UI会报异常:ViewRootImpl$CalledFromWrongThreadException
                    //解决方法:handler
                    //
                    mBuffer = buffer;
                    handler.post(runnable);
                }
                //开线程更新UI
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        textView_status.setText("size:"+ String.valueOf(mBuffer.length)+"数据监听:"+ new String(mBuffer));
                    }
                };
            });



    demo下载:可供参考

    展开全文
  • Android开发之网络通讯详解

    万次阅读 多人点赞 2016-03-21 13:59:16
    真正的才智是刚毅的志向
  • Android 通信方式

    2018-08-21 10:26:18
    最常用的通信方式是Binder、Socket、Handler,当然也有少量其他的IPC方式,比如杀进程Process.killProcess()采用的是signal方式。 1. Binder Binder通信采用c/s架构,从组件视角来说,包含Client、Server、...
  • React Native与Android通信交互

    万次阅读 热门讨论 2019-02-28 10:55:57
    在前两篇的内容中,和大家分享了Android原生集成RN,以及RN的增量热更新。关于详细的内容,点击如下具体了解: Android App巧妙集成React Native最详教程 React Native 实现热部署、增量热更新 本篇内容同样...
  • Unity与Android通信

    千次阅读 2018-05-18 22:43:38
    选择Android Library 三.为Library命名,在这里我命名为BmobPay 四.选中如下图的两个.xml文件,右键选择点击delete,删除 五.安装unity,在unity的安装目录下,找到以下图文件路径,复制classes.jar文件 六....
  • Android通信机制之Android架构(一)

    千次阅读 2018-02-28 10:41:20
    前言: Android框架给... 一、Android四大组件短程通信:一个完整的app是包含很多个类的,那Android是如何知道他们之间的关联关系,各个类之间又是如何通信的呢?Android给开发者提供了一个Intent(意图)来传递...
  • 单片机传来多字节数据,想让前一个字节显示在一个textview,后一个字节显示在另一个texiview里该怎么弄呢
  • 浅谈arduino与android通信

    万次阅读 2016-05-29 16:16:30
    arduino与android通信一般使用wifi和蓝牙模块,相对较为便宜。 也可以使用USB Host Shield,这个可使Arduino非常方便的与一个USB从设备通讯,例如USB键盘、鼠、摇杆、U盘数据读取、相机、蓝牙、USB GPS接收器、安卓...
  • PC通过USB连接Android通信(Socket)

    千次阅读 2016-11-18 18:01:15
    Android端Socket服务器 /** * Created by Jack Stone on 2016/11/17. * Socket服务器,PC可以通过USB连接、ADB端口映射连接本服务器,不需要通过Wifi和网络 */ public class TCPConnect implements Runnable { ...
  • H5和Android通信容器BridgeWebView的使用

    千次阅读 2016-12-30 18:45:20
    开源地址:https://github.com/open-android/BridgeWebViewPS:如果觉得这个系列的每篇文章太长,那就直接看视频吧运行效果使用步骤1. 在project的build.gradle添加如下代码(如下图)allprojects { repositories { ...
  • ESP8266与Android通信简单TCP服务端设计

    千次阅读 2016-12-31 13:22:03
    Android利用Socket简单的实现TCP通信
  • Html5与android通信

    千次阅读 2016-09-07 14:53:34
    在开发HybridApp中,h5页面如何与android本地数据通信呢? h5网页的数据如何传递给原生androidandroid原生数据如何在h5网页上显示获取呢? 下面通过一个小例子,帮助那些被卡在Hybrid门槛之外的同学(曾经的我也是...
  • Android USB OTG通信

    千次阅读 2018-09-09 17:11:11
    发启(initiate)数据交换的一方称为主机 (host),另一方称为外设(peripheral),两者通过总线实现通信,由主机负责供电。一个 USB 系 统里只有一个主机,但可以有多个外设,外设的主要信息记录在描述符(descriptor)里...
  • Unity和Android相互通信

    千次阅读 2017-09-19 15:16:02
    该安卓方法内部又回调unity中一个换颜色的方法,从而为小球换颜色,有些人会说为什么搞这么复杂,点击屏幕直接调unity换颜色方法不就得了,我想说的是我们此处演示是为了说明清楚unity如何调android以及android如何...
  • 巧用Android网络通信技术,在网络上直接传输对象

    万次阅读 多人点赞 2016-10-19 23:00:01
    要做一个优秀的Android应用,使用到网络通信技术是必不可少的,很难想象一款没有网络交互的软件最终能发展得多成功。那么我们来看一下,一般Android应用程序里都是怎么实现网络交互的,这里拿一个Boook对象为例,...
  • 本来这篇文章应该讲一下Flutter的插件开发,但是在插件开发的基础是PlatformChannel,也就是Flutter与Android/iOS Native的通信,理解了这一个知识点,Flutter的插件开发也就不在话下。 1.PlatformChannel概述 Flu.....
  • pc与android通过usb socket实现手机通信Demo

    千次下载 热门讨论 2020-07-27 23:31:08
    a.PC客户端与Android服务端的Socket同步通信(USB) b.操作步骤如下: ----------------------------------------------------------- 1.请将测试数据文件夹中的ucliulanqi.apk copy到c:\下进行测试 2. 将android...
1 2 3 4 5 ... 20
收藏数 171,206
精华内容 68,482
关键字:

android通信