手機居然可以控制電腦瀏覽器顯示,一開始我也是吃了一驚,但就是可以的,而且只需要修改手機端的程序,不需要修改瀏覽器。基本原理是手機與瀏覽器通過socket 通信。
前言
這個東西最初我是看簡書一個大神的文章知道的
http://www.lxweimin.com/p/89ccae3e590b
《調試手機中數據庫的福音:Android-Debug-Database》
文章介紹了老外的一個庫Android-Debug-Database ,通過這個庫,可以在瀏覽器顯示與修改當前應用的數據庫,sharepreferce等內容。這可刷新了我的世界觀。在我的想象中,手機與電腦通信,起碼要寫兩個軟件,一個是手機端,一個電腦端的。結果,這個庫,只需要寫手機端的。我想,估計是瀏覽器已經是一個標準的客戶端,手機只需要完成服務器的搭建即可。
下圖是我通過手機,在電腦瀏覽器顯示一段基本的html代碼,酷炫得不行
通信過程##
整個過程是手機作為服務器端,瀏覽器作為客戶端。大概通信步驟如下
1.使電腦與手機位于同一局域網。實操就是直接用usb連接手機與電腦,并進行端口轉發,將電腦端口9989的數據,轉發到手機9989端口(當然你也可以用其他端口,要保證端口沒有被占用)
adb forward tcp:9989 tcp:9989
2.手機開啟一個socket,,指定手機端口9989監聽客戶端連接
mServerSocket = new ServerSocket(9989);
Socket socket = mServerSocket.accept();
3.瀏覽器向電腦端口9989 發送http請求,該請求被轉發到手機的9989端口,通信連通。具體就是在瀏覽器輸入一個網址http://localhost:9989/
3.連接后,手機返回html文件給瀏覽器,瀏覽器進行顯示。
//返回html給瀏覽器
String route = "wenfeng.html";
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output = new PrintStream(socket.getOutputStream());
byte[] bytes;
bytes = loadContent(route, mAssets);
//把狀態返回給瀏覽器
output.println("HTTP/1.0 200 OK");
output.println("Content-Type: " + "text/html");
output.println("Content-Length: " + bytes.length);
output.println();
output.write(bytes);
output.flush();
看看代碼##
在oncreate開啟socket,進行監聽
public class MainActivity extends AppCompatActivity {
private ClientServer mclient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mclient = new ClientServer(this,9989);
mclient.start(); //開啟監聽
}
}
連接成功后,把html文件返回給瀏覽器,并且返回狀態碼給瀏覽器。
public class ClientServer implements Runnable {
private static final String TAG = "ClientServer";
private final int mPort;
private boolean mIsRunning;
private ServerSocket mServerSocket;
private Context context;
public ClientServer(Context context, int port) {
mPort = port;
this.context=context;
}
public void start() {
Log.i("wenfeng","start");
mIsRunning = true;
new Thread(this).start();
}
@Override
public void run() {
try {
mServerSocket = new ServerSocket(mPort);
Log.i("wenfeng","wait for accept"); //等待連接
Socket socket = mServerSocket.accept();
handle(socket); //處理連接
} catch (SocketException e) {
// The server was stopped; ignore.
Log.i("wenfeng","SocketException",e);
} catch (IOException e) {
Log.i("wenfeng","IOException",e);
} catch (Exception ignore) {
}
}
public void handle(Socket socket) throws IOException {
BufferedReader reader = null;
PrintStream output = null;
try {
AssetManager mAssets = context.getResources().getAssets();
String route = "wenfeng.html";
output = new PrintStream(socket.getOutputStream());
byte[] bytes;
//裝載wenfeng.html文件,用于返回給瀏覽器
bytes = loadContent(route, mAssets);
//返回服務器狀態
output.println("HTTP/1.0 200 OK");
output.println("Content-Type: " + "text/html");
output.println("Content-Length: " + bytes.length);
output.println();
//返回數據
output.write(bytes);
output.flush();
} finally {
try {
if (null != output) {
output.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//該函數用于裝載html文件
public static byte[] loadContent(String fileName, AssetManager assetManager) throws IOException {
InputStream input = null;
try {
ByteArrayOutputStream output = new ByteArrayOutputStream();
input = assetManager.open(fileName);
byte[] buffer = new byte[1024];
int size;
while (-1 != (size = input.read(buffer))) {
output.write(buffer, 0, size);
}
output.flush();
return output.toByteArray();
} catch (FileNotFoundException e) {
return null;
} finally {
try {
if (null != input) {
input.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
例子的傳送門,可以體驗一下。
https://github.com/wenfengtou/RubbishDemo
日更中,歡迎關注。