• 【安卓开发】安卓网络编程


    一、安卓Socket客户端

    .java

    package com.example.ycy;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.util.Scanner;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.View;
    
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
        
        public void handlerMessage(){
        	try {
    			//1.创建客户端套接字,填充ip地址和端口号
    			Socket client = new Socket("192.168.0.15",8888);
    			
    			//2.获取输出流,用来发送数据
    			OutputStream out = client.getOutputStream();
    			
    			String message = "message from Andriod";
    			
    			//4.发送数据
    			//用getBytes()方法将字符串转化为字节数组
    			out.write(message.getBytes());
    		} 
    		 catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
        }
        
        public void sendMessage(View v){
        	new Thread(new Runnable() {		//网络线程不能跑在主线程,需要再创建一个线程
    			
    			@Override
    			public void run() {
    				// TODO Auto-generated method stub
    				handlerMessage();
    			}
    		}).start();
        }
        
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    .xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".MainActivity" >
    
        <Button 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="sendMessage"
            android:text="发送消息"
            />
    
    RelativeLayout>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    效果显示:

    在这里插入图片描述

    注意:

    网络访问不能在主线程(UI线程)中进行,否则程序会崩溃,要创建线程来发起网络访问。



    二、安卓Socket客户端优化(小车遥控器拓展)

    代码:

    package com.example.ycy;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.util.Scanner;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.View;
    
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
        
        public void handlerMessage(final String message){
        	
    		new Thread(new Runnable() {
    					
    			@Override
    			public void run() {
    				// TODO Auto-generated method stub
    				try {
    					//1.创建客户端套接字,填充ip地址和端口号
    					Socket client = new Socket("192.168.0.15",8888);
    							
    					//2.获取输出流,用来发送数据
    					OutputStream out = client.getOutputStream();						
    							
    					//4.发送数据
    					//用getBytes()方法将字符串转化为字节数组
    					out.write(message.getBytes());			
    				} 
    					catch (IOException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}					
    			}
    		}).start();
        	
        }
        
        public void sendMessage(View v){
        	
        	switch(v.getId()){
        		case R.id.fw:
        			handlerMessage("goForward");
        			break;
        		case R.id.bc:
        			handlerMessage("goBack");
        			break;
        		case R.id.lf:
        			handlerMessage("goLeft");
        			break;
        		case R.id.rt:
        			handlerMessage("goRight");
        			break;
        		
        	}
        	
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    效果显示:

    在这里插入图片描述



    三、Android非UI线程修改空间程序崩溃问题

    如果我们想要不断刷新修改一个控件(比如文本控件)的内容,我们应该如何做呢?

    既然要刷新,就必然会用到 sleep() 方法去睡眠等待刷新时间,但是在之前我们曾经出错过,sleep() 方法不能出现在 UI 线程里,否则程序会崩溃,那么我们就再创建一个线程来刷新修改控件内容:

    .java

    package com.example.ycy;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
    
    	public TextView textView;	//关联TextView控件
    	
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            textView = (TextView) findViewById(R.id.textView);	//关联TextView控件
        }
    
    
        public void changeText(View v){
        	new Thread(new Runnable() {
    			
    			@Override
    			public void run() {
    				// TODO Auto-generated method stub
    				for (int i = 0; i < 10; i++) {
    					textView.setText("yangchenyanghandsome");
    					
    					try {
    						Thread.sleep(3000);
    					} catch (InterruptedException e) {
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					}
    				}
    			}
    		}).start();
        }
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    .xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".MainActivity" >
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/hello_world" />
    
        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/textView"
            android:layout_below="@+id/textView"
            android:layout_marginTop="34dp"
            android:onClick="changeText"
            android:text="修改文本" />
    
    RelativeLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    运行结果:

    在这里插入图片描述

    我们可以看到,程序又崩溃了。怎么办呢?

    一种新的解决办法:Handler类(倒计时软件)

    既然再新线程内不能修改控件,那么我们利用 Handler类 去处理 UI 线程和新线程无法处理的业务,就是在新线程中,我们将新线程不能处理的业务封装在重写了的 Handler类 中的 handleMessage() 方法中, 当在新线程中需要执行响应业务的时候,我们通过给 Handler 类的对象发送消息,触发这个事件,让handleMessage() 方法去处理响应的业务,这样就能解决这个问题,这里我们通过应用 Handler类 将以上功能修改为倒计时软件:

    .java

    package com.example.ycy;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.view.View;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
    
    	public TextView textView;	//关联TextView控件
    	
    	public Handler h;
    	
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
            textView = (TextView) findViewById(R.id.textView);	//关联TextView控件
            
            h = new Handler(){	//匿名内部类,UI主线程的家里的电话,接到电话去处理一些其他进程无法处理的事件
            	@Override
            	public void handleMessage(Message msg) {	//区分事件类型
            		// TODO Auto-generated method stub
            		super.handleMessage(msg);
            		textView.setText(msg.what+"s");
            	}
            };
        }
    
    
        public void changeText(View v){
        	
        	new Thread(new Runnable() {
    			
    			@Override
    			public void run() {
    				// TODO Auto-generated method stub
    				for (int i = 10; i >= 0; i--) {
    					Message msg = new Message();	//为了传递参数i
    					msg.what = i;
    					//打电话把UI线程不能处理的事情交给UI线程的Handler去做
    					h.sendMessage(msg);
    					
    					try {
    						Thread.sleep(1000);
    					} catch (InterruptedException e) {
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					}
    					
    				}
    			}
    		}).start();
        }
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    .xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".MainActivity"
        android:background="#000000"
         >
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:textSize="50dp"
            android:textColor="#ffffff"
            android:text="10s" />
    
        <Button
            android:id="@+id/button1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
    		android:layout_centerHorizontal="true"
            android:onClick="changeText"
            android:background="#ffffff"
            android:text="Begin" />
    
    RelativeLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    效果显示:

    点击 Begin 前:

    在这里插入图片描述

    点击 Begin 后:

    在这里插入图片描述

    倒计时完毕:

    在这里插入图片描述



    四、Android网络接收数据并刷新界面(综合练习)

    .java

    package com.example.ycy;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.view.View;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
    
    	Handler handler;
    	TextView tx;
    	
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
            tx = (TextView) findViewById(R.id.tx);
            
            //这里是关于Handler处理文本框变化的代码
            handler = new Handler(){
            	@Override
            	public void handleMessage(Message msg) {
            		// TODO Auto-generated method stub
            		super.handleMessage(msg);
            		
            		Bundle b = msg.getData();	//先把Bundle获取
            		
            		String string = b.getString("msg");		//再把b中的msg读出来
            		
            		tx.setText(string);
            	}
            };
        }
        
        public void handlerMessage(final String message, final Handler h){
        	
    		new Thread(new Runnable() {
    					
    			@Override
    			public void run() {
    				// TODO Auto-generated method stub
    				try {
    					//1.创建客户端套接字,填充IP地址和端口号
    					Socket client = new Socket("192.168.0.15",8880);
    							
    					//2.获取输出流,用来发送数据
    					OutputStream out = client.getOutputStream();						
    							
    					//4.发送数据
    					//用getBytes()方法将字符串转化为字节数组
    					out.write(message.getBytes());		
    					
    					//5.接收数据
    					InputStream in = client.getInputStream();
    					byte[] data = new byte[128];
    					int len = 0;
    					len = in.read(data);
    					String str = new String(data, 0, len);
    					
    					Message msg = new Message();	
    					
    					Bundle b = new Bundle();
    					b.putString("msg", str);
    					msg.setData(b);		//把b放在msg中
    					
    					h.sendMessage(msg);		//触发Handler处理机制
    					
    				} 
    					catch (IOException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}					
    			}
    		}).start();
        	
        }
        
        public void sendMessage(View v){
        	
        	switch(v.getId()){
        		case R.id.fw:
        			handlerMessage("goForward",handler);
        			break;
        	} 	
        }   
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94

    .xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#000000"
        tools:context=".MainActivity" >
    
           <Button
               android:id="@+id/fw"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:onClick="sendMessage" 
               android:textColor="#ffffff"
               android:text="发起网络请求" />
    	
           <TextView 
               android:id="@+id/tx"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:textSize="35dp"
               android:layout_centerInParent="true"
               android:textColor="#ffffff"
               />
    
    RelativeLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    效果显示:

    在这里插入图片描述



    五、WebView控件之自制浏览器APP

    .java

    package com.example.ycy;
    
    import android.os.Bundle;
    import android.app.Activity;
    import android.view.KeyEvent;
    import android.view.Menu;
    import android.webkit.WebView;
    import android.webkit.WebViewClient;
    import android.widget.EditText;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);        
            setContentView(R.layout.activity_main);
            
            //关联浏览器控件
            final WebView wb = (WebView) findViewById(R.id.webView1);
            //关联输入框控件
            final EditText ed = (EditText) findViewById(R.id.ed);
            //创建浏览器客户端,防止页面访问浏览器发生跳转
            wb.setWebViewClient(new WebViewClient());
            
            //输入框调用动作监听方法
            ed.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    			
    			@Override
    			//重写动作监听条件
    			public boolean onEditorAction(TextView arg0, int arg1, KeyEvent event) {
    				// TODO Auto-generated method stub
    				//获取输入框中的内容并转化为字符串
    				String str = ed.getText().toString();
    				//浏览页面
    				wb.loadUrl(str);
    				//如果监听到回车,返回true
    				return (event.getKeyCode() == KeyEvent.KEYCODE_ENTER);
    			}
    		});           
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    .xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity" >
    
        <LinearLayout 
            android:id="@+id/ll"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            >
            <EditText 
                android:id="@+id/ed"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:hint="请输入网址"		
                />	
            
        LinearLayout>
    
    
        <WebView
            android:layout_below="@id/ll"
            android:id="@+id/webView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            />
    
    RelativeLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    注意要在 AndroidMainfest 中加上网络访问权限:

    <uses-permission android:name="android.permission.INTERNET"/>
    
    • 1

    在这里插入图片描述

    效果显示:

    在这里插入图片描述

  • 相关阅读:
    生成老年人的声音sox
    【VisualStudio使用】快捷键
    计算机毕业设计Java华夏球迷俱乐部网站设计与实现(源码+系统+mysql数据库+lw文档)
    深度解析BERT:从理论到Pytorch实战
    2022年最新《谷粒学院开发教程》:8 - 前台登录功能
    Django框架基本语法(二)
    AJAX--Express速成
    Spring(三)IoC 相关内容
    搜索二叉树实现(非递归版本)
    Git知识汇总
  • 原文地址:https://blog.csdn.net/qq_62361050/article/details/126119992