鉴于自己的痛苦,研究一个socket在多个界面切换时保持链接的问题,令我纠结很久,现在我提供客户端的源码给有需要的人参考。
1、ApplicationUtil类:
import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; import android.app.Application; public class ApplicationUtil extends Application{ private Socket socket; private DataOutputStream out = null; private DataInputStream in = null; public void init() throws IOException, Exception{ this.socket = new Socket("192.168.1.104",10202); this.out = new DataOutputStream(socket.getOutputStream()); this.in = new DataInputStream(socket.getInputStream()); } public Socket getSocket() { return socket; } public void setSocket(Socket socket) { this.socket = socket; } public DataOutputStream getOut() { return out; } public void setOut(DataOutputStream out) { this.out = out; } public DataInputStream getIn() { return in; } public void setIn(DataInputStream in) { this.in = in; } }
AndroidMainifest.xml中application的配置:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.login" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="15" /> <application android:name="com.util.ApplicationUtil" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".LoginActivity" android:label="@string/title_activity_main" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".MainActivity"/> </application> <!-- 振动需要的权限 --> <uses-permission android:name="android.permission.VIBRATE"/> <!-- 声明网络权限 --> <uses-permission android:name="android.permission.INTERNET"/> </manifest>
2、LoginActivity类:
import java.io.BufferedWriter; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import java.net.UnknownHostException; import com.login.R; import com.util.ApplicationUtil; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class LoginActivity extends Activity{ private EditText usernameT; private EditText passwordT; private Button loginButton; private Socket socket; private DataOutputStream out; private DataInputStream in; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.login); usernameT = (EditText) findViewById(R.id.username); passwordT = (EditText) findViewById(R.id.password); loginButton = (Button) findViewById(R.id.login); loginButton.setOnClickListener(new OnClickListener(){ public void onClick(View v) { ApplicationUtil appUtil = (ApplicationUtil) LoginActivity.this.getApplication(); try { appUtil.init(); Socket socket = appUtil.getSocket(); out = appUtil.getOut(); in = appUtil.getIn(); } catch (IOException e1) { e1.printStackTrace(); } catch (Exception e1) { e1.printStackTrace(); } String username = usernameT.getText().toString(); String password = passwordT.getText().toString(); MD5 md5 = new MD5(); String ss = md5.MD5(username+"|"+password); try { //发送数据 String str = "[login]|"+ss; out.writeBytes(str); out.flush(); System.out.println("str ===> "+str); //创建一个缓冲字节数 int r = in.available(); while(r==0){ r = in.available(); } byte[] b = new byte[r]; in.read(b); String result = new String(b,"utf-8"); System.out.println("result = "+result); if(result.equals("登陆成功0")){ Intent intent = new Intent(); intent.setClass(LoginActivity.this, MainActivity.class); startActivity(intent); } else { Intent intent = new Intent(); intent.setClass(LoginActivity.this, MainActivity.class); startActivity(intent); } } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }); } }
3、MainActivity类:
import java.io.BufferedReader; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; import com.image.TestActivity; import com.login.R; import com.util.ApplicationUtil; import android.media.RingtoneManager; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.provider.MediaStore.Audio; import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { private EditText mess; private Socket socket; private Handler handler; private DataInputStream in; private NotificationManager nm; private Notification n; private int messageNotificationID = 0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.success); mess = (EditText) findViewById(R.id.message); ApplicationUtil appUtil = (ApplicationUtil) MainActivity.this.getApplication(); socket = appUtil.getSocket(); in = appUtil.getIn(); handler = new Handler(){ @Override public void handleMessage(Message msg) { //如果来自子线程 if(msg.what == 0x123){ mess.append(msg.obj.toString()+"\n"); //消息通知 mynoti(); } } }; //调用线程 myThread(); } //JAVA可以设置读写缓冲区的大小-setReceiveBufferSize(int size), setSendBufferSize(int size)。 public void myThread(){ Thread oneThread = new Thread(new Runnable(){ public boolean isRunning = true; public void run() { while(isRunning){ try { Thread.sleep(1000); //创建一个缓冲字节数 int r = in.available(); while(r==0){ r = in.available(); } byte[] b = new byte[r]; in.read(b); String content = new String(b,"utf-8"); //每当读到来自服务器的数据后,发送消息通知程序页面显示数据 Message msg = new Message(); msg.what = 0x123; msg.obj = content; Log.v("ho", content); handler.sendMessage(msg); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } }); oneThread.start(); } public void mynoti(){ NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); // 创建一个通知 Notification mNotification = new Notification(); //用系统自带的铃声 mNotification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6"); // mNotification.sound = Uri.parse("file:///sdcard/wen.mp3"); //mNotification.defaults=Notification.DEFAULT_SOUND; //Notification.FLAG_INSISTENT; //让声音、振动无限循环,直到用户响应 //Notification.FLAG_AUTO_CANCEL; //通知被点击后,自动消失 //Notification.FLAG_NO_CLEAR; //点击‘Clear‘时,不清楚该通知(QQ的通知无法清除,就是用的这个) mNotification.flags = Notification.FLAG_NO_CLEAR; ; //通知时发出的振动 //第一个参数: 振动前等待的时间 //第二个参数: 第一次振动的时长、以此类推 long[] vir = {0,100,200,300}; mNotification.vibrate = vir; mNotificationManager.notify(messageNotificationID, mNotification); messageNotificationID++; } }
4、MD5类:
import java.security.MessageDigest; public class MD5 { // MD5加码。32位 public static String MD5(String inStr) { MessageDigest md5 = null; try { md5 = MessageDigest.getInstance("MD5"); } catch (Exception e) { System.out.println(e.toString()); e.printStackTrace(); return ""; } char[] charArray = inStr.toCharArray(); byte[] byteArray = new byte[charArray.length]; for (int i = 0; i < charArray.length; i++) byteArray[i] = (byte) charArray[i]; byte[] md5Bytes = md5.digest(byteArray); StringBuffer hexValue = new StringBuffer(); for (int i = 0; i < md5Bytes.length; i++) { int val = ((int) md5Bytes[i]) & 0xff; if (val < 16) hexValue.append("0"); hexValue.append(Integer.toHexString(val)); } return hexValue.toString(); } }
6、login.xml和success.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:orientation="vertical"> <TableLayout android:layout_width="fill_parent" android:layout_height="wrap_content" > <TableRow> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="账号:" /> <EditText android:id="@+id/username" android:layout_width="200dp" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:layout_marginRight="10dp" android:hint="账号" /> </TableRow> <TableRow> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="密码:" /> <EditText android:id="@+id/password" android:password="true" android:layout_width="200dp" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:layout_marginRight="10dp" android:hint="密码" /> </TableRow> </TableLayout> <Button android:id="@+id/login" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:layout_marginRight="10dp" android:text="登录" /> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:orientation="vertical"> <TextView android:id="@+id/success" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="不断接受信息,并提示" /> <EditText android:id="@+id/message" android:layout_width="fill_parent" android:layout_height="wrap_content" android:cursorVisible="false" /> </LinearLayout>
以上都是客户端,服务端就自己写,socket代码差不多。
时间: 2024-10-05 04:19:16