intentservice和聊天的本地测试

来源:互联网 发布:如何当一名网络作家 编辑:程序博客网 时间:2024/05/21 08:47

最近,公司的项目要做android手机端的相互聊天功能。每个手机在连接网络的时候,会被网络提供商提供一个动态的ip地址,所以,手机端之间的聊天和pc之间的聊天方法,在通讯上是不存在啥大的区别的。


现在给出个demo,在手机上建立个服务来接受另外的ip地址发送过来的数据,在手机上开启socket端口来发送数据。

界面布局,是个点击按钮,每点击一次就发送一次数据给服务。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <Button        android:id="@+id/btn_lclick"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentLeft="true"        android:layout_alignParentTop="true"        android:text="click" /></RelativeLayout>

相当于客户端的发送socket类:

public class LocalClient extends Activity implements OnClickListener {private Socket socket;private InputStream in;private BufferedReader reader;private OutputStream out;private InetAddress ipaddress;private StringBuffer sb;private String line;private Button click;private Intent intent;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.acy_chant);sb=new StringBuffer();SetIp();init();// 启动服务intent = new Intent(LocalClient.this, LocalService.class);startService(intent);}public void init() {click = (Button) findViewById(R.id.btn_lclick);click.setOnClickListener(this);}public void SetIp() {/** * ip地址 */try {// 如果没有网络,会返回localhost/::1地址,是ipv6地址ipaddress = InetAddress.getByName(GetIp());} catch (Exception e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}/** * 获取ip地址 *  * @return */public String GetIp() {try {for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {NetworkInterface intf = en.nextElement();for (Enumeration<InetAddress> ipAddr = intf.getInetAddresses(); ipAddr.hasMoreElements();) {InetAddress inetAddress = ipAddr.nextElement();// ipv4地址if (!inetAddress.isLoopbackAddress()&& InetAddressUtils.isIPv4Address(inetAddress.getHostAddress())) {return inetAddress.getHostAddress();}}}} catch (Exception ex) {}return "";}@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif (v == click) {// 开启线程处理通讯new Thread() {public void run() {try {// 连接socket = new Socket(ipaddress, 9090);Log.i("**open**", "开启本地端口");// 输出流out = socket.getOutputStream();BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));writer.write("client:hello world\n");writer.flush();// 输入流in = socket.getInputStream();reader = new BufferedReader(new InputStreamReader(in));line = reader.readLine();sb.append(line);Log.i("**client***", sb.toString());} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}};}.start();}}/** * 退出时,关闭服务 */@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();stopService(intent);Log.i("**close service**", "关闭服务");}}

相当于服务端的service,接受发送的数据:

public class LocalService extends IntentService {private Context context;private String name;private boolean isRun = false;private int Port = 9090;private ServerSocket ss;private Socket socket;private InputStream in;private OutputStream out;private BufferedReader reader;private StringBuffer sb;private String line = null;public LocalService() {super("localservice");// TODO Auto-generated constructor stub}public LocalService(Context context, String name) {// 必须调用父类的有参构造方法,因为父类的无参构造方法已经被有参方法覆盖了。super("localservice");this.context = context;this.name = name;}/** * 初始化 */@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();sb = new StringBuffer();try {ss = new ServerSocket(Port);Log.i("***start service***", "启动 服务");isRun = true;} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();Log.i("ss exception", e.getMessage());}}/** * 在子线程中处理长连接 */@Overrideprotected void onHandleIntent(Intent intent) {// TODO Auto-generated method stubwhile (true) {try {Log.i("****into***", "进入服务子线程长连接");socket = ss.accept();Log.i("***get client**", "获取客户端发送的请求");// 输入流in = socket.getInputStream();reader = new BufferedReader(new InputStreamReader(in));line = reader.readLine();sb.append(line);//reader.close();Log.i("**service**", sb.toString());// 输出流out = socket.getOutputStream();BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));writer.write("server:yes!!\n");writer.flush();} catch (Exception e) {e.printStackTrace();Log.i("service exception", e.getMessage());}}}@Overridepublic void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();}}

现在是测试效果:

1.界面:

2.运行时的log:

3.发送数据后的log:


基本的就这样,有兴趣的小伙伴可以自己的增添功能,因为这是没链接服务器的情况,所以比较简单和粗糙。


注意:

1.在写着个的时候,遇到过socket is close 的异常,导致数据没接收到。网上说着可能是有服务器和客户端断开链接的情况导致的,以后遇到要了解这样的情况。而我这的情况是由于没有初始化的对象导致的,那样也会导致socket断开链接。

2.对于inputstream的处理。有两种方式,一种是用:inputstream.read()。读取字节数组的方式,来读取流。一种是使用BufferedReader来封装输入流,然后用reader.readLine(),来读取流。

但,使用封装的BufferedReader来读取数据,会导致阻塞问题,要读取到"\n"的时候结尾。否则会一直阻塞,使得流不能读取。

3.在获取ip地址的时候,开启的模拟器的ip地址分配是10.0的地址,二我们发送给模拟器的ip地址,其实是pc的ip地址,所以用模拟器测试的话,你需要改下地址。

4.intentservice在配置清单中,写的是service,而不是intentservice:

    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity android:name="com.chant.LocalClient" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <service android:name="com.chant.LocalService" >        </service>

5.对流的处理也可以使用 :datainputstream dataoutputstream

public static void main(String[] args) {ServerSocket server = null;Socket socket = null;DataInputStream in = null;DataOutputStream out = null;// 循环等待客户端的访问try {// 开启服务器端口,限定最大访问队列server = new ServerSocket(8089, 1000);while (true) {// 阻塞直到有客户端连接socket = server.accept();// 获取输入流in = new DataInputStream(socket.getInputStream());String str = in.readUTF();System.out.println(str);// 获取输出流out = new DataOutputStream(socket.getOutputStream());// 发送与机器无关的utf-8编码的字符串out.writeUTF("service: welcome to service");// 清空此数据输入流out.flush();}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {// 关闭相关的流操作try {if (socket != null) {socket.close();}if (in != null) {in.close();}if (out != null) {out.close();}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

data流,允许流以机器无关的方法的方式从底层中读取java数据类型,输入流可以使用readUTF()来读取流。不过该方法已经过时了,建议使用bufferedreader和write来封装流。


0 0
原创粉丝点击