最近接到一個需求,需要實作一個區域網路的圖檔二維碼分享功能;具體怎麼樣呢,先看下面的效果圖:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLkNGNjZTZ5IzM1QTNxcDNlJGM4YmM3YjMlF2MkVTOihDM1QWZ3QTMm9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
由于是區域網路,請使用真機,如果有兩個手機更好了,連接配接同個區域網路就可以看到;如果是隻有一個手機,那就電腦上看把, html 的布局有點醜,因為主要是 适配手機,我也不擅長這一塊,見怪不怪吧。
一、需求分析
要實作區域網路,一般就是搭建個 ServerSocket,裝置連接配接時輸出網址即可
二維碼分享,沒啥好說,zxing .
咦,好像就沒了啊,關鍵是區域網路這個伺服器了, 搭建 Android 的區域網路,自己寫的話,估計調試都調到很久,github 搜了一下,主要有三個,AndServer ,國人寫的,思路比較适合我們,但有時會遇到連接配接逾時的問題,不知道是不是我網絡的問題;還有 NanoHttpd 和 AndroidAsync,NanoHttpd 适合java,且調試不好調試,最後選擇了 AndroidAsync,接入簡單,而且接口也比較好用。(以上隻是個人觀點),但 AndroidAsync 關于伺服器方面的資料還是比較少的,是以得看源碼了,不過這裡也做了一些封裝,到時可以參考一下。
二、代碼配置
區域網路,首先需要有網絡,是以這裡直接檢查網絡好了,需要檢測 WiFi 是否能檢測到,這裡的 WiFi 的 IP 擷取也比較簡單,當檢測到 WiFi 連接配接了,直接拿就是了:
//wifi是否連接配接
if (CusUtil.isWifiConnected()){
//擷取 ip
DEVICE_IP = CusUtil.getWifiIpaddr();
StringBuilder sb = new StringBuilder();
sb.append("請在同個wifi下,掃描該二維碼,或者浏覽器中輸入: \n")
.append("http://"+DEVICE_IP+":"+SERVER_PORT)
.append("\n或者輸入:\n")
.append("http://"+DEVICE_IP+":"+SERVER_PORT+"/password");
textView.setText(sb.toString());
}else{
textView.setText("您還未連接配接 wifi ");
}
如果 WiFi 擷取了,則開始配置資料,主要是 ip 和port,當然還有添加攔截器,圖檔和密碼還是需要攔截的。
private void startLanServer(){
mCheckRequestHandle = CheckRequestHandle.create(this,DEVICE_IP,SERVER_PORT);
//配置資料,builder 模式
LanServerBean bean = LanServerBean.lanBuilder()
.setPort(SERVER_PORT)
.setIpAddr(DEVICE_IP)
//配置預設 html 字元串
.setDefaultHtml(CusUtil.getDefaultString(DEVICE_IP,SERVER_PORT))
//添加攔截,當檢測 image,輸出圖檔
.registerHandler("image", ImageRequestHandle.create(this))
//添加攔截,當檢測 password,彈出密碼驗證框
.registerHandler("password",mCheckRequestHandle)
.builder();
if (mServiceBinder != null) {
mServiceBinder.startLanServer(bean);
}
}
如果自己有新的需求,也可以繼續添加攔截器,攔截器也比較簡單,AndroidAsync 的 api 還是比較人性化的:
public class ImageRequestHandle implements HttpServerRequestCallback {
private static final String TAG = "ImageRequestHandle";
private Context mContext;
private ImageRequestHandle(Context context){
mContext = context;
}
public static ImageRequestHandle create(Context context){
return new ImageRequestHandle(context);
}
@Override
public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
try {
InputStream is = mContext.getAssets().open("beauty.jpg");
//輸入圖檔
response.sendStream(is,is.available());
} catch (Exception e) {
e.printStackTrace();
}
}
}
html 的擷取都是在 assets 中,而一些動态的,比如 ip 和 端口,則是通過 代碼重新添加,關于 html 的基礎,就不解釋啦,自己去撸吧:
/**
* 輸出驗證密碼的html
* @return
*/
public static String getCheckPasswordHtml(String ipaddr,int port,String password){
StringBuilder sb = new StringBuilder();
sb.append(CusUtil.getAssetsString("checkpass.html")).append("\n")
.append("<button class=\"button\" onclick=\"checkPassword(")
.append(password+",'"+"http://"+ipaddr+":"+port+"')\">确定</button>").append("\n")
.append(" </div>").append("\n")
.append(" </div>").append("\n")
.append(" </body>").append("\n")
.append(" </html>").append("\n");
return sb.toString();
}
三、擴充
繼續區域網路分享圖檔已經懂了,那麼像區域網路傳輸檔案,資訊共享等等,都是可以搞的。比如比較火的 WiFi 傳書,就是這個原理。多去折騰吧。
四、代碼位址
完整的文章代碼可以檢視Github位址:
https://github.com/LillteZheng/LanServer原文釋出時間為:2018-0717
本文作者:LillteZheng
本文來自雲栖社群合作夥伴“
安卓巴士Android開發者門戶”,了解相關資訊可以關注“
”。