###1、項目描述
實驗室小夥伴們經過APP鏈接實驗室路由器,比對路由器Mac地址進行簽到。此外小夥伴們還可經過APP進行請假,上傳請假理由、日期等信息,便於實驗室平常管理。html
###2、APP截圖 node
###3、相關github開源項目 感謝開源:android
/*卡片佈局*/
compile 'com.android.support:cardview-v7:+' /*meterial風格對話框*/ compile 'com.afollestad.material-dialogs:core:0.9.1.0' /*Meterial UI控件*/ compile 'com.github.navasmdc:MaterialDesign:1.5[@aar](https://my.oschina.net/AAR)' compile 'com.wdullaer:materialdatetimepicker:2.5.0' /*懸浮按鈕*/ compile 'com.getbase:floatingactionbutton:1.10.1' /*輸入框*/ compile 'com.rengwuxian.materialedittext:library:2.1.4' /*訪問網絡工具類*/ compile 'com.lzy.net:okgo:2.0.0' /*Gson Json轉化成bean工具類*/ compile 'com.google.code.gson:gson:2.3.1' /*andrroid工具包*/ compile 'com.blankj:utilcode:1.3.3'
###4、數據庫設計 主要設計三個對象:用戶、請假記錄、簽到記錄。
**約束:**一個用戶天天只能有一條簽到記錄,同時用戶簽到過允許再次簽到。
**解決方法:**給每條簽到記錄經過用戶名加日期生成一個unique_id可預見字段,用戶簽到時查詢數據庫是否存在存在此字段的記錄。
其中版本更新代碼目前並無實現。git
###5、關鍵代碼 5.一、比對路由器Mac地址:github
/*比對路由器的MAC地址*/ public boolean checkLabMac(){ //獲取WiFIMac地址 if(NetworkUtils.isWifiConnected(MainActivity.this)){ WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE); WifiInfo info = wifi.getConnectionInfo(); str_mac=info.getBSSID(); if(!str_mac.equals(Constant.E412_MAC)){ signSuccess("非實驗室WIFI,沒法簽到!"); return false; }else { return true; } }else{ signSuccess("WIFI未鏈接,請先鏈接實驗室WIFI!"); return false; } }
5.二、訪問網絡與Gson解析數據:
訪問網絡工具類:compile 'com.lzy.net:okgo:2.0.0'Gson Json, 地址:https://github.com/jeasonlzy/okhttp-OkGo
轉化成bean工具類:compile 'com.google.code.gson:gson:2.3.1' Gson轉換Json到Bean須要創建相應的Bean與Json字段一一對應,否則會出錯。
若是Json和Bean字段對應不上,或者服務端傳過來的字段命名不規範,加一個 @SerializedName,解決方案:http://blog.csdn.net/bzy601638015/article/details/32916281 web
經過谷歌瀏覽器插件PostMan模擬登陸 chrome
這裏以用戶登陸訪問網絡爲例: /*用戶名密碼校驗*/ public void checkUser(){ /*構造請求體*/ HashMap<String, String> params = new HashMap<>(); params.put("username", str_username); params.put("password", str_password); JSONObject jsonObject = new JSONObject(params); /*發送登陸請求*/ OkGo.post(Api.LOGIN)// .tag(this)// .upJson(jsonObject.toString())// .execute(new StringCallback() { @Override public void onSuccess(String s, Call call, Response response) { /*關閉提示框*/ /* int code = conn.getResponseCode();//返回碼200請求成功,若是請求碼不是200,則提示服務器出錯*/ login=new ResponseLogin(); login= JsonUtils.fromJson(s,ResponseLogin.class); md.dismiss(); if(login.getStatus().equals(Constant.SUCCESS)){ /*若是勾選了記住密碼,且登陸成功,就保存用戶名密碼*/ if(checkBox.isCheck()){ /*記住用戶名密碼*/ PreferencesUtils.putString(LoginActivity.this,"username",str_username); PreferencesUtils.putString(LoginActivity.this,"password",str_password); } toActivity(MainActivity.class); Toast.makeText(LoginActivity.this,"登錄成功",Toast.LENGTH_SHORT).show(); LoginActivity.this.finish(); }else{ if(login.getMsg().equals(Constant.ERROR_SYSTEM)){ Toast.makeText(LoginActivity.this,"系統錯誤",Toast.LENGTH_SHORT).show(); return; }if(login.getMsg().equals(Constant.ERROR_USERNAME)){ Toast.makeText(LoginActivity.this,"用戶不存在",Toast.LENGTH_SHORT).show(); return; }if(login.getMsg().equals(Constant.ERROR_PASSWORD)){ Toast.makeText(LoginActivity.this,"密碼錯誤",Toast.LENGTH_SHORT).show(); return; } } } }); } JSON對應Bean,服務端值放回成功或者失敗信息,只有兩個字段。 public class ResponseLogin implements Serializable { private String status; private String msg; public void setStatus(String status) { this.status = status; } public String getStatus() { return status; } public void setMsg(String msg) { this.msg = msg; } public String getMsg() { return msg; } }
5.三、使用時間選擇器問題:
使用時間選擇器是,樣例代碼是之間經過Activity實現結構,而後重寫方法,若是用這種方式一個Activity中貌似只能用一個Dialog選擇時間(不知道本身理解是否是對的,歡迎指正),而這裏有兩個位置須要選擇時間。因此選擇匿名內部類的方式實現選擇時間功能。數據庫
btn_startTime.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //彈出日期選擇對話框 Calendar now = Calendar.getInstance(); DatePickerDialog dialog= DatePickerDialog.newInstance(new DatePickerDialog.OnDateSetListener(){ @Override public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) { String date =year+"-"+(monthOfYear+1)+"-"+dayOfMonth; startTime.setText(date); }},now.get(Calendar.YEAR), now.get(Calendar.MONTH), now.get(Calendar.DAY_OF_MONTH)); dialog.show(getFragmentManager(), "Datepickerdialog"); } }); btn_endTime.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //彈出日期選擇對話框 Calendar now = Calendar.getInstance(); DatePickerDialog dialog= DatePickerDialog.newInstance(new DatePickerDialog.OnDateSetListener(){ @Override public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) { String date =year+"-"+(monthOfYear+1)+"-"+dayOfMonth; endTime.setText(date); }},now.get(Calendar.YEAR), now.get(Calendar.MONTH), now.get(Calendar.DAY_OF_MONTH)); dialog.show(getFragmentManager(), "Datepickerdialog"); } });
5.四、關於Toolbar菜單字體顏色背景顏色問題:
使用Toorbar的時候,它的菜單字體爲白色,菜單背景爲灰白色,蠻難看。
解決方案:http://www.cnblogs.com/oyjt/p/4762640.htmljson
5.五、關於仿知乎懸浮按鈕問題:
主頁上仿知乎懸浮按鈕,github上例子的佈局是相對佈局,可是本身經常使用的是線性佈局,想着把它用在線性佈局中,給它調位置一直沒成功,只能將就的把主頁改爲相對佈局吧,效果也還不錯。
可給按鈕添加圖標以及顏色:瀏覽器
<com.getbase.floatingactionbutton.FloatingActionButton android:id="@+id/action_a" android:layout_width="wrap_content" android:layout_height="wrap_content" fab:fab_colorNormal="@color/blue" fab:fab_title="我要請假" fab:fab_icon="@drawable/holiday" fab:fab_colorPressed="@color/white_pressed"/>
地址:https://github.com/futuresimple/android-floating-action-button
5.六、下拉刷新上拉加載更多:
下拉刷新再本項目中貌似並無多大意義,由於用戶每次查看本身的記錄的時候,只弄了個上拉分頁加載更多。注意傳入當前頁數出現的問題。 上拉加載更多參考代碼:https://github.com/wangnaiwen/RecyclerViewRefresh
5.七、引入CheckBox時,默認選中不起做用:
發現materialdesign是代碼提示自動引入的,
須要將其修改成:修改成 xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:materialdesign="http://schemas.android.com/apk/res-auto" 這是自定義屬性引入有問題形成的。
參考個人另外一個小結:http://www.javashuo.com/article/p-hcgxabto-z.html
5.八、本地測試時,Natapp內外網映射工具:
開機重啓後natapp映射的本地路徑就變了,天天都得修改,若是你沒有關機習慣倒也無所謂。注意用node.js作服務端時須要在www文件中將默認的3000端口改爲80端口。
###6、最後相關網址分享: 阿里狂拽酷炫的圖標庫:地址:http://www.iconfont.cn/plus
**API測試工具PostMan:**下載地址: http://chromecj.com/web-development/2014-09/60/download.html
**內外網映射工具:**作服務端開發時APP需訪問我本地電腦,這是能夠經過免費的內外網映射,不須要經過阿里雲測試(微信公衆號開發也能夠經過此服務 )。 地址:https://natapp.cn/
項目源碼: https://github.com/dpc761218914/SignIn
Node.js服務端源碼: https://github.com/dpc761218914/SignIn_Server