我選擇在 Android 上加入 HTTP 服務器,這樣只要把域名或地址接通,便能在瀏覽器上輸入地址,透過互聯網直接連線。到時在家中的路由器按埠號把數據分發到紅米就行了。利用瀏覽器的好處是不同平台都有,不用安裝特別程式。
我不懂 Android 編程,所以這次試驗遇到不同問題。首先是 NanoHTTPD 有很多版本,網上的教學也有很多版本,通通都不適用最新的版本。public Response serve(IHTTPSession session) 就是新版本的格式。既然不能照抄,那只好參考舊版的編寫方式,加上自己的思考去做。好不容易改好了,畫面也出現了,瀏覽器卻連不上。找了很久,原來是舊版不用 server.start(),新版要。好了,成功連上了,但想連線是在畫面顯示當刻時間,發現那時要更新介面,不如 iOS 般簡單、直接、容易。又找了一會,成功以 Handler 來達成。今回學到不少。下一步就是加入 OTG + Arduino 連線。這樣基本的硬件功能便已齊全。
//======================================================================================== // AMIGO Camera //---------------------------------------------------------------------------------------- // Created by Pacess on 2014-07-30 // Copyright (c) 2014 Sita Technology Company. All rights reserved. //======================================================================================== //---------------------------------------------------------------------------------------- // 0 1 2 3 4 5 6 7 8 9 // 56789012345678901234567890123456789012345678901234567890123456789012345678901234567890 package com.pacess.amigocamera; import android.widget.TextView; import android.app.Activity; import android.app.Fragment; import android.os.Message; import android.os.Handler; import android.os.Bundle; import android.net.wifi.WifiManager; import android.util.Log; import android.view.LayoutInflater; import android.view.ViewGroup; import android.view.MenuItem; import android.view.Menu; import android.view.View; import java.text.SimpleDateFormat; import java.io.IOException; import java.lang.Runnable; import java.util.Date; //======================================================================================== public class MainActivity extends Activity { //---------------------------------------------------------------------------------------- // Defines private static final int PORT = 8080; //---------------------------------------------------------------------------------------- // Class variables private TextView statusTextView; private HTTPServer httpServer; //---------------------------------------------------------------------------------------- Handler handler = new Handler() { @Override public void handleMessage(Message message) { if (statusTextView == null) {return;} String timeStamp = (String)message.obj; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("Last request: "); stringBuilder.append(timeStamp); statusTextView.setText(stringBuilder.toString()); } }; //---------------------------------------------------------------------------------------- @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d("MainActivity", "onCreate"); if (savedInstanceState != null) {return;} getFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit(); } //---------------------------------------------------------------------------------------- @Override protected void onResume() { super.onResume(); Log.d("MainActivity", "onResume"); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String timeString = dateFormat.format(new Date()); statusTextView = (TextView)findViewById(R.id.status); if (statusTextView == null) { Log.d("MainActivity", "### statusTextView is null..."); } else { statusTextView.setText("Time stamp: "+timeString); } WifiManager wifiManager = (WifiManager)getSystemService(WIFI_SERVICE); int ipAddress = wifiManager.getConnectionInfo().getIpAddress(); final String ipString = String.format("%d.%d.%d.%d", (ipAddress & 0xff), (ipAddress >> 8 & 0xff), (ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff)); TextView textView = (TextView)findViewById(R.id.ipAddress); textView.setText("http://"+ipString+":"+PORT); try { httpServer = new HTTPServer(); httpServer.start(); Log.d("MainActivity", "HTTP server started..."); } catch (IOException e) { e.printStackTrace(); } } //---------------------------------------------------------------------------------------- @Override protected void onPause() { super.onPause(); Log.d("MainActivity", "onPause"); if (httpServer == null) {return;} httpServer.stop(); Log.d("MainActivity", "HTTP server stopped"); } //---------------------------------------------------------------------------------------- @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; } //---------------------------------------------------------------------------------------- @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will automatically handle clicks // on the Home/Up button, so long as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) {return true;} return super.onOptionsItemSelected(item); } //======================================================================================== // A placeholder fragment containing a simple view. public static class PlaceholderFragment extends Fragment { //---------------------------------------------------------------------------------------- public PlaceholderFragment() { } //---------------------------------------------------------------------------------------- @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_main, container, false); return rootView; } } //======================================================================================== public class HTTPServer extends NanoHTTPD { //---------------------------------------------------------------------------------------- public HTTPServer() throws IOException { super(PORT); Log.d("HTTPServer", "Server start "+PORT); } //---------------------------------------------------------------------------------------- @Override public Response serve(IHTTPSession session) { Log.d("HTTPServer", "Server response"); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); final String timeString = dateFormat.format(new Date()); //---------------------------------------------------------------------------------------- // Use handler to update user interface Thread thread = new Thread(new Runnable() { @Override public void run() { Message message = handler.obtainMessage(); message.obj = timeString; message.sendToTarget(); } }); thread.start(); //---------------------------------------------------------------------------------------- // Create response HTML StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("<html>"); stringBuilder.append("<body>"); stringBuilder.append("<b>AMIGO Camera - ").append(timeString).append("</b><hr>"); stringBuilder.append("<b>Headers</b> = ").append(String.valueOf(session.getHeaders())).append("<br>"); stringBuilder.append("<b>Method</b> = ").append(String.valueOf(session.getMethod())).append("<br>"); stringBuilder.append("<b>URI</b> = ").append(String.valueOf(session.getUri())).append("<br>"); stringBuilder.append("<b>Parameters</b> = ").append(String.valueOf(session.getParms())).append("<br>"); stringBuilder.append("</body>"); stringBuilder.append("</html>"); return new NanoHTTPD.Response(stringBuilder.toString()); } } }