工作好几个月了,在公司才开始接触Java,android.一切从零开始。
为了尽快与公司项目同步,胡乱啃了基本android书,就开始上手一些项目,记得最开始是老大让做一个练手项目:基于android TV的远程电子监控,做的差不多了就没有继续往下进行。后来就一直是做一些修复bug,添加模块的工作。
近段在学习socket,在网上也找了一些示例,比如android手机QQ示例。觉得挺有意思,想玩一玩,瞎弄了很久,终于有一点心得了,在此列出来跟大家分享一下。
由于初学,很多地方捉襟见肘,有不足之处,还望大侠们多多指教。关
于socket的一些基本的常识就不在这里瞎扯了。做了一个简单的由android手机控制pc的一些功能的小实例,跟大家分享一下:
例子的功能有:在手机上控制自己的电脑关机,重启,获取电脑的截屏。先看PC端的server部分:

在服务器端开启一个serversocket:

code:

package com.xluo.Server;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;

import com.xluo.common.UserData;
import com.xluo.common.UserMessage;

public class StartServer {
public StartServer(){
ServerSocket ss;
try{
ss = new ServerSocket(5001);//服务端口号,可自行定义,但要和客户端的端口请求号保持一致,而且最好为大于1024的整数,
System.out.println("服务器已启动 at "+new Date());
while(true){
Socket s = ss.accept();
String ClientAddr = s.getInetAddress().toString();
System.out.println(ClientAddr);
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());//获取socket中的对象
UserData ud = (UserData)ois.readObject();//获取从客户端发过来的对象,UserData为自定义的Java文件
boolean shutdown = ud.getShutdown();//是否为关机请求
boolean restart = ud.getRestart();//重启请求
boolean PShow = ud.getGetPicture();//截屏请求
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());//获取socket输出对象
UserMessage um = new UserMessage();//预返回客户端对象
if(shutdown){
um.setType(1);
oos.writeObject(um);//传送消息给客户端
Runtime.getRuntime().exec("cmd.exe /c shutdown -s -t 00");//在PC上执行关机命令
}else if(restart){
um.setType(1);
oos.writeObject(um);
Runtime.getRuntime().exec("cmd.exe /c shutdown -r -t 00");//重启命令
}else if(PShow){
um.setType(1);
um.setB(CopyScreen.getByteFile());//获取截屏并转换成byte[]类型赋值给um对象
oos.writeObject(um);
}
s.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}

这里纠结了我很久的的一个问题是从客户端发送数据到服务端,以获取对象的方式去读取socket中的数据(还有一些其他的方式),失败了很多次,后来才发现客户端发送的对象类必须与服务端接受的类在同一个包名下而且类名也要相同,现在想觉得是一个好弱智的问题,但当时就是不知道,真是瞎子走路一样。。。

在服务端可能大家对截屏CopyScreen这个类比较感兴趣,下面贴一下代码:

package com.xluo.Server;

import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;

import javax.imageio.ImageIO;

public class CopyScreen {
 private static Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
 public CopyScreen(){
  
 }
 public static byte[] getByteFile() throws Exception{ //得到截屏图片的二进制流
  BufferedImage bi = null;
     bi = (new Robot()).createScreenCapture(new Rectangle(0,0,(int) d.getWidth(),(int) d.getHeight()));//截屏图片的BufferedImage对象
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  ImageIO.write(bi,"png",baos);
  byte[] b = null;
  b = baos.toByteArray();
  return b;
 }
}

其实很简单,首先利用Robot的createScreenCapture做出图片,然后转换成byte流就ok了

到这里,其实server端的工作已经做完了,但是可能有些跟我一样的小白还想知道作为在socket中传递的数据对象文件。

从上面可以看出我定义了两个作为传递数据的对象:1.UserData.java 服务端用于接收,2.UserMessage.java服务端用于发送,这两个文件在客户端就恰好想法,即UserData用于发送,而UserMessage用于接收

下面看一下两个文件:

UserData.java:

package com.xluo.common;

import java.io.Serializable;

public class UserData implements Serializable {
 /**
  *
  */
 private static final long serialVersionUID = 1L;
 private boolean Shutdown;
 private boolean Restart;
 private boolean GetPicture;
 
 public void setShutdown(boolean bl){
  this.Shutdown = bl;
 }
 public boolean getShutdown(){
  return this.Shutdown;
 }
 public void setRestart(boolean bl){
  this.Restart = bl;
 }
 public boolean getRestart(){
  return this.Restart;
 }
 public void setGetPicture(boolean bl){
  this.GetPicture = bl;
 }
 public boolean getGetPicture(){
  return this.GetPicture;
 }
}

我习惯把它理解成为流动数据库(纯属个人理解)

UserMessage.java:

package com.xluo.common;

import java.io.Serializable;

public class UserMessage implements Serializable {
 /**
  *
  */
 private static final long serialVersionUID = 1L;
 private int Type ;
 private byte[] b; //用于传递图片的byte数组
 
 public void setType(int t){
  this.Type = t;
 }
 public int getType(){
  return this.Type;
 }
 public void setB(byte[] b){
  this.b = b;
 }
 public byte[] getB(){
  return this.b;
 }
}

我们再来看看客户端:

客户端其实也很简单在一个apk的主界面上画三个按钮,然后分别做关机,重启,获取图片的请求。

具体代码如下:

package com.xluo.pcphone;

import com.xluo.common.UserData;
import com.xluo.common.UserMessage;
import com.xluo.socket.UserSocket;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.Toast;
import android.support.v4.app.NavUtils;

public class MainActivity extends Activity implements android.view.View.OnClickListener {

private Button bt1,bt2,bt3;
 private UserData ud ;
 
 private Handler mHandler = new Handler(){    //使用handler来处理线程中发送过来的数据
  public void handleMessage(Message msg){
   switch(msg.what){
   case 1:
    UserMessage um = (UserMessage)msg.obj;
    if(um.getType() == 1 && um.getB() == null){
     Toast.makeText(MainActivity.this, "操作成功", Toast.LENGTH_SHORT).show();
    }
    break;
   case 0:
    Toast.makeText(MainActivity.this, "连接服务器失败!", Toast.LENGTH_SHORT).show();
    break;
   default:
    break;
   }
   
  }
 };
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
       
        bt1 = (Button)findViewById(R.id.shutdown);
        bt2 = (Button)findViewById(R.id.restart);
        bt3 = (Button)findViewById(R.id.spicture);
       
        bt1.setOnClickListener(this);
        bt2.setOnClickListener(this);
        bt3.setOnClickListener(this);
    }

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

public void onClick(View v) {
  // TODO Auto-generated method stub
  switch(v.getId()){   
  case R.id.shutdown: //关机按钮事件
   ud = new UserData();
   ud.setShutdown(true);
   new UserSocket(mHandler,ud).start(); //启动线程,发送请求
   break;
  case R.id.restart: //重启按钮事件
   ud = new UserData();
   ud.setRestart(true);
   new UserSocket(mHandler,ud).start();
   break;
  case R.id.spicture://获取图片按钮事件
   Intent i = new Intent();
   i.setClass(this, PictureShow.class);
   startActivity(i); //跳转到新的activity
   break;
  }
 }

}

这个文件没什么可讲的,下面我们来看这里启动的线程,

UserSocket.java:

package com.xluo.socket;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;

import com.xluo.common.UserData;
import com.xluo.common.UserMessage;

import android.os.Handler;
import android.os.Message;
public class UserSocket extends Thread{
 private Handler mHandler;
 private UserData ud;
 public UserSocket(Handler h,Object ob){
  this.mHandler = h;   //需要handler处理收到服务器发送过来的数据
  this.ud = (UserData) ob; //将要发送给服务器的数据对象
 }
 public void run(){
  Socket s = new Socket();
  try{
   s.connect(new InetSocketAddress("10.16.6.163",5001),3000);//10.16.6.163为pc的ip,5001为端口号(与服务端监听的端口号一致),3000为连接超时时间(3秒)
   Message msg = new Message(); //实例化要返回给handler的对象
   UserMessage um = new UserMessage(); //作为数据接收对象
   if(!s.isConnected()){ //如果连接不成功
    msg.what = 0;
   }else{
    msg.what = 1;
    ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
    oos.writeObject(ud);  //发送请求
    ObjectInputStream ois = new ObjectInputStream(s.getInputStream()); 
    um = (UserMessage) ois.readObject(); //得到数据包
   }
   msg.obj = um;赋值给msg的对象
   mHandler.removeCallbacksAndMessages(msg.obj);
   mHandler.sendMessage(msg);//返回给handler
  }catch(Exception e){
   e.printStackTrace();
  }
  
 }
}

这个线程的工作就是保持跟服务端通信,得到消息和发送消息

下面我们看一下获取图片的activity

PictureShow.java:

package com.xluo.pcphone;

import com.xluo.common.UserData;
import com.xluo.common.UserMessage;
import com.xluo.socket.UserSocket;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Window;
import android.widget.ImageView;
import android.widget.Toast;

public class PictureShow extends Activity {
 private ImageView iv = null;
 
 private UserData ud = new UserData();

private Handler mHandler = new Handler(){
  public void handleMessage(Message msg){
   switch(msg.what){
   case 1:
    UserMessage um = (UserMessage)msg.obj;  //得到数据包
    byte[] b = um.getB();  //把数据包中的图片流拿出来
    if(b.length != 0){
     Bitmap bm = getBitmap(b); //转换成bitmap
     iv.setImageBitmap(bm); //显示图片
    }
    break;
   case 0:
    Toast.makeText(PictureShow.this, "连接服务器失败!", Toast.LENGTH_SHORT);
   }
   
  }
  
 };
 
 @Override
 public void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);
  requestWindowFeature(Window.FEATURE_NO_TITLE);
  setContentView(R.layout.screen_picture);
  
  iv = (ImageView)findViewById(R.id.screen_picture_img);
  
  ud.setGetPicture(true);
  new UserSocket(mHandler,ud).start();
  Toast.makeText(PictureShow.this,"按返回键后退",Toast.LENGTH_SHORT);
 }
 
 private Bitmap getBitmap(byte[] b){ //把二进制图片转换成bitmap
  if(b.length != 0)
  {
   return BitmapFactory.decodeByteArray(b, 0, b.length);
  }else{
   return null;
  }
 }
}

实例基本完成了,功能很简单,而且而无美观科研,仅供和我一样菜鸟的童鞋共勉,如有大侠莅临,还望指点江山。小生在学校是学php的,现在工作需要,只得埋头啃Java,玩android。现在正跟中国的社会主义一样,处于初级阶段,很多的东西需要学习。我是一只粪斗小菜鸟,望大家多批评指教!

(附:如转载请注明出处!)

socket学习之电脑手机通信相关推荐

  1. android学习: 酷狗手机遥控器

    前言: 学习,掌握Android下套接字的使用.与MFC套接字的通信. 1. 需求: 手机端控制电脑酷狗播放, 上/下一曲, 声音增/减 2. 分析: 手机端用Android , 电脑使用MFC框架实 ...

  2. python共享内存通信mapofview_python map eval strPython socket模块实现的udp通信功能示例...

    本文实例讲述了Python socket模块实现的udp通信功能.分享给大家供大家参考,具体如下: socket介绍 socket(简称 套接字) 是进程间通信的一种方式,它与其他进程间通信的一个主要 ...

  3. 电脑连接linux系统怎么样,如今连Linux都弄不懂-当时我如果那么学习培训电脑操作系统就好啦...

    本文作者:黄小斜 文中思维脑图 介绍 学编程,操作系统你务必要把握的基本知识,那麼电脑操作系统究竟是什么呢? 这还用说么,电脑操作系统不就是说Windows.Linux.Mac.IOS.Android ...

  4. Android中通过Socket直接与RILD进行通信

    点击打开链接 1 RIL_J与RIL_C通信 上层通常要和RILD通信,是通过Socket,在RIL_JAVA层实现: 沿着这样代码流程进行Framework--native: Phone--RIL_ ...

  5. 单片机蓝牙烧录_实现蓝牙HC-05、06与单片机的连接及与手机通信

    蓝牙(Bluetooth):是一种无线技术标准,可实现固定设备.移动设备和楼宇个人域网之间的短距离数据交换(使用2.4-2.485GHz的ISM波段的UHF无线电波).蓝牙技术最初由电信巨头爱立信公司 ...

  6. 手机app和单片机蓝牙通讯c语言,单片机怎么和手机通信,你知道吗?

    原标题:单片机怎么和手机通信,你知道吗? 在用单片机做产品的时候,难免会用到单片机和手机通信,能和手机通信的方案有很多这种,像常用的蓝牙,Wifi等等,当然还有更高层次的通过互联网,一般我们使用比较多 ...

  7. ROS学习笔记-多机器人通信(1)-实现两台机器通信

    ROS是一个分布式的计算环境.一个正在运行的ROS可以在多个机器人之间分布成几十甚至上百个节点.取决于系统的配置方式,任何节点可能需要随时与任何其他节点进行通信,为实现使用同一个master控制多台机 ...

  8. 【STM32】标准库与HAL库对照学习教程八--串口通信详解

    [STM32]标准库与HAL库对照学习教程八--串口通信详解 一.前言 二.准备工作 三.通信的基本概念 1.通信方式 2.串行通信与并行通信 (1)串行通信 (2)并行通信 3.异步通信与同步通信 ...

  9. html适应自动缩放,HTML+Css让网页自动适应电脑手机屏幕

    HTML+Css让网页自动适应电脑手机屏幕 2019-02-03 编程之家 https://www.jb51.cc 编程之家收集整理的这篇文章主要介绍了HTML+Css让网页自动适应电脑手机屏幕,编程 ...

  10. Android基础入门教程——7.6.1 Socket学习网络基础准备

    Android基础入门教程--7.6.1 Socket学习网络基础准备 标签(空格分隔): Android基础入门教程 本节引言: 为了照顾没学过Java Socket的初学者,或者说捋一捋Andro ...

最新文章

  1. vue @click 绑定多个方法 执行顺序_Vue干货,学完这些就够用了
  2. kali学习日记第二篇 -- Nessus
  3. WDF驱动中KMDF与UMDF区别
  4. mysql回收权限_mysql回收权限不成功,请问如何破?
  5. Django Rest Framework
  6. YUV422转RGB24
  7. (10)FPGA专业术语(第2天)
  8. Spring Cloud 服务消费者 Feign (三)
  9. WINDOWS:OPEN62541编译
  10. 现在主流人工智能(AI)方法的本质是什么?
  11. 微信小程序怎么开店?怎么开一个小程序店铺
  12. Linux(Ubuntu)中对音频批量转换格式MP3转WAV/PCM转WAV
  13. 关于j2me mmapi的player接口的一些理解.
  14. C++中的sort函数排序(快速排序)
  15. 实用selenium+python实现web自动化测试
  16. SQLMap使用|命令大全(干货)
  17. 程序员编程艺术:面试和算法心得
  18. 微信小程序中使用Base64编码解码
  19. 如何从外网SSH访问家中的树莓派?
  20. Unity虚拟现实(VR)无编码游戏开发视频教程

热门文章

  1. C基础:程序执行时间的计算方法的三种方式
  2. 高性能网络编程(一):单台服务器并发TCP连接数到底可以有多少?
  3. python获取验证码失败_python 爬虫:验证码一直错误
  4. Scott Page  斯科特佩奇《模型思维》读书笔记
  5. 马尔可夫------马尔可夫不等式
  6. 3、在hilens_kit安装ros后,运行小车导航
  7. Ubuntu下安装Qt
  8. [TimLinux] Python3 Coverity zeep/SOAP 库使用示例
  9. 样本标准差分母为什么是n-1
  10. 华为电脑和手机一碰传_华为手机怎么一碰传文件到电脑教程