Commit e5cade54cb1a00441e356baf8ee8ae854cc60a53

Authored by wugian
1 parent 21e65601

control smart screen

Showing 37 changed files with 4367 additions and 3 deletions
... ... @@ -43,11 +43,11 @@
43 43 <activity
44 44 android:name=".activity.StartActivity"
45 45 android:theme="@style/AppStartTheme">
46   - <intent-filter>
  46 + <!-- <intent-filter>
47 47 <action android:name="android.intent.action.MAIN"/>
48 48
49 49 <category android:name="android.intent.category.LAUNCHER"/>
50   - </intent-filter>
  50 + </intent-filter>-->
51 51 </activity>
52 52 <activity android:name=".activity.SearchNewActivity"/>
53 53 <activity android:name=".activity.PlayListActivity"/>
... ... @@ -128,5 +128,15 @@
128 128 </activity>
129 129 <!--门禁相关服务,必要!!!-->
130 130 <service android:name="com.bluetoothle.GREENBluetoothLeService" android:enabled="true"/>
  131 +
  132 + <activity android:name="com.xgimi.smartscreen.ConfigActivity"/>
  133 + <activity android:name="com.xgimi.smartscreen.MainActivity">
  134 + <intent-filter>
  135 + <action android:name="android.intent.action.MAIN"/>
  136 +
  137 + <category android:name="android.intent.category.LAUNCHER"/>
  138 + </intent-filter>
  139 + </activity>
  140 + <service android:name="com.xgimi.smartscreen.service.ConfigService"/>
131 141 </application>
132 142 </manifest>
\ No newline at end of file
... ...
... ... @@ -19,7 +19,6 @@ import android.widget.Spinner;
19 19 import android.widget.TableRow;
20 20 import android.widget.TextView;
21 21 import android.widget.Toast;
22   -
23 22 import com.gimi.common.cinema.model.SambaMsg;
24 23 import com.gimi.common.cinema.utils.T;
25 24 import com.gimi.common.cinema.utils.WifiApManger;
... ... @@ -28,6 +27,7 @@ import com.xgimi.gimicinema.BuildConfig;
28 27 import com.xgimi.gimicinema.R;
29 28 import com.xgimi.gimicinema.mview.ISettingView;
30 29 import com.xgimi.gimicinema.presenter.SettingPresenter;
  30 +import com.xgimi.smartscreen.ConfigActivity;
31 31
32 32 import java.util.ArrayList;
33 33 import java.util.HashMap;
... ... @@ -326,4 +326,9 @@ public class SettingActivity extends BaseActivity implements ISettingView {
326 326 Intent intent = new Intent(this, SwitchControlActivity.class);
327 327 startActivity(intent);
328 328 }
  329 +
  330 + public void setSmartScreen(View view) {
  331 + Intent intent = new Intent(this, ConfigActivity.class);
  332 + startActivity(intent);
  333 + }
329 334 }
... ...
  1 +package com.xgimi.smartscreen;
  2 +
  3 +import android.app.Activity;
  4 +import android.app.ProgressDialog;
  5 +import android.content.DialogInterface;
  6 +import android.content.Intent;
  7 +import android.os.AsyncTask;
  8 +import android.os.Bundle;
  9 +import android.text.TextUtils;
  10 +import android.util.Log;
  11 +import android.view.View;
  12 +import android.widget.Button;
  13 +import android.widget.EditText;
  14 +import android.widget.Toast;
  15 +import com.xgimi.gimicinema.R;
  16 +import com.xgimi.smartscreen.confignetwork.ChTask;
  17 +import com.xgimi.smartscreen.confignetwork.IChListener;
  18 +import com.xgimi.smartscreen.confignetwork.IChResult;
  19 +import com.xgimi.smartscreen.confignetwork.IChTask;
  20 +import com.xgimi.smartscreen.confignetwork.task.__IChTask;
  21 +import com.xgimi.smartscreen.service.WifiAdminSimple;
  22 +
  23 +import java.util.List;
  24 +
  25 +public class ConfigActivity extends Activity {
  26 +
  27 + private static final String TAG = "ConfigActivity";
  28 +
  29 + private EditText mEdtApSsid;
  30 + private EditText mEdtApPassword;
  31 + private Button mBtnConfig;
  32 +
  33 + private WifiAdminSimple mWifiAdmin;
  34 +
  35 + @Override
  36 + protected void onCreate(Bundle savedInstanceState) {
  37 + super.onCreate(savedInstanceState);
  38 + setContentView(R.layout.activity_config);
  39 +
  40 + mWifiAdmin = new WifiAdminSimple(this);
  41 +
  42 + mEdtApSsid = (EditText) findViewById(R.id.ssid_et);
  43 + mEdtApPassword = (EditText) findViewById(R.id.pwd_et);
  44 +
  45 + mEdtApSsid.setText("LEMOMOFFICE2.4G");
  46 + mEdtApPassword.setText("88888888");
  47 +
  48 + mBtnConfig = (Button) findViewById(R.id.btn_save);
  49 + mBtnConfig.setOnClickListener(new View.OnClickListener() {
  50 + @Override
  51 + public void onClick(View v) {
  52 + String apSsid = mEdtApSsid.getText().toString();
  53 + String apPassword = mEdtApPassword.getText().toString();
  54 + String apBssid = mWifiAdmin.getWifiConnectedBssid();
  55 +
  56 + int[] tastResultCount = {0, 1, 2, 3, 4, 5};
  57 + String taskResultCountStr = Integer.toString(tastResultCount[1]); //设置任务的数量为1个
  58 +
  59 + new AsyncTask3().execute(apSsid, apBssid, apPassword, "NO", taskResultCountStr);
  60 + }
  61 + });
  62 +
  63 + }
  64 +
  65 +
  66 + @Override
  67 + protected void onResume() {
  68 + super.onResume();
  69 + // display the connected ap's ssid
  70 + String apSsid = mWifiAdmin.getWifiConnectedSsid();
  71 + if (apSsid != null) {
  72 + mEdtApSsid.setText(apSsid);
  73 + } else {
  74 + mEdtApSsid.setText("");
  75 + }
  76 +// check whether the wifi is connected
  77 + boolean isApSsidEmpty = TextUtils.isEmpty(apSsid);
  78 + mBtnConfig.setEnabled(!isApSsidEmpty);
  79 + }
  80 +
  81 + public void matchScreen(View view) {
  82 + Intent intent = new Intent(this, MainActivity.class);
  83 + startActivity(intent);
  84 + }
  85 +
  86 +
  87 + private class AsyncTask2 extends AsyncTask<String, Void, IChResult> {
  88 +
  89 + private ProgressDialog mProgressDialog;
  90 +
  91 + private IChTask mChTask;
  92 + // without the lock, if the user tap confirm and cancel quickly enough,
  93 + // the bug will arise. the reason is follows:
  94 + // 0. task is starting created, but not finished
  95 + // 1. the task is cancel for the task hasn't been created, it do nothing
  96 + // 2. task is created
  97 + // 3. Oops, the task should be cancelled, but it is running
  98 + private final Object mLock = new Object();
  99 +
  100 + @Override
  101 + protected void onPreExecute() {
  102 + mProgressDialog = new ProgressDialog(ConfigActivity.this);
  103 + mProgressDialog.setMessage("正在配置,请稍侯...");
  104 + mProgressDialog.setCanceledOnTouchOutside(false);
  105 + mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
  106 + @Override
  107 + public void onCancel(DialogInterface dialog) {
  108 + synchronized (mLock) {
  109 + if (__IChTask.DEBUG) {
  110 + Log.i(TAG, "progress dialog is canceled");
  111 + }
  112 + if (mChTask != null) {
  113 + mChTask.interrupt();
  114 + }
  115 + }
  116 + }
  117 + });
  118 + mProgressDialog.setButton(DialogInterface.BUTTON_POSITIVE, "确认", new DialogInterface.OnClickListener() {
  119 + @Override
  120 + public void onClick(DialogInterface dialog, int which) {
  121 + }
  122 + });
  123 + mProgressDialog.show();
  124 + mProgressDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(false);
  125 + }
  126 +
  127 + @Override
  128 + protected IChResult doInBackground(String... params) {
  129 + synchronized (mLock) {
  130 + String apSsid = params[0];
  131 + String apBssid = params[1];
  132 + String apPassword = params[2];
  133 + String isSsidHiddenStr = params[3];
  134 + boolean isSsidHidden = false;
  135 + if (isSsidHiddenStr.equals("YES")) {
  136 + isSsidHidden = true;
  137 + }
  138 + mChTask = new ChTask(apSsid, apBssid, apPassword, isSsidHidden, ConfigActivity.this);
  139 + }
  140 + IChResult result = mChTask.executeForResult();
  141 + return result;
  142 + }
  143 +
  144 + @Override
  145 + protected void onPostExecute(IChResult result) {
  146 + mProgressDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(true);
  147 + mProgressDialog.getButton(DialogInterface.BUTTON_POSITIVE).setText("确认");
  148 + // it is unnecessary at the moment, add here just to show how to use isCancelled()
  149 + if (!result.isCancelled()) {
  150 + if (result.isSuc()) {
  151 + mProgressDialog.setMessage("配置成功" + "\n" + "BSSID = " + result.getBssid() + "\n" + "InetAddress = " + result.getInetAddress().getHostAddress());
  152 + } else {
  153 + mProgressDialog.setMessage("配置失败");
  154 + }
  155 + }
  156 + }
  157 + }
  158 +
  159 + private void onChResultAddedPerform(final IChResult result) {
  160 + runOnUiThread(new Runnable() {
  161 +
  162 + @Override
  163 + public void run() {
  164 + String text = result.getBssid() + " 已连接到wifi";
  165 + Toast.makeText(ConfigActivity.this, text, Toast.LENGTH_SHORT).show();
  166 + }
  167 +
  168 + });
  169 + }
  170 +
  171 + private IChListener myListener = new IChListener() {
  172 +
  173 + @Override
  174 + public void onChResultAdded(final IChResult result) {
  175 + onChResultAddedPerform(result);
  176 + }
  177 + };
  178 +
  179 + private class AsyncTask3 extends AsyncTask<String, Void, List<IChResult>> {
  180 +
  181 + private ProgressDialog mProgressDialog;
  182 +
  183 + private IChTask mChTask;
  184 + // without the lock, if the user tap confirm and cancel quickly enough,
  185 + // the bug will arise. the reason is follows:
  186 + // 0. task is starting created, but not finished
  187 + // 1. the task is cancel for the task hasn't been created, it do nothing
  188 + // 2. task is created
  189 + // 3. Oops, the task should be cancelled, but it is running
  190 + private final Object mLock = new Object();
  191 +
  192 + @Override
  193 + protected void onPreExecute() {
  194 + mProgressDialog = new ProgressDialog(ConfigActivity.this);
  195 + mProgressDialog.setMessage("正在配置, 请稍候...");
  196 + mProgressDialog.setCanceledOnTouchOutside(false);
  197 + mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
  198 + @Override
  199 + public void onCancel(DialogInterface dialog) {
  200 + synchronized (mLock) {
  201 + if (__IChTask.DEBUG) {
  202 + Log.i(TAG, "progress dialog is canceled");
  203 + }
  204 + if (mChTask != null) {
  205 + mChTask.interrupt();
  206 + }
  207 + }
  208 + }
  209 + });
  210 + mProgressDialog.setButton(DialogInterface.BUTTON_POSITIVE, "确认", new DialogInterface.OnClickListener() {
  211 + @Override
  212 + public void onClick(DialogInterface dialog, int which) {
  213 + }
  214 + });
  215 + if (!mProgressDialog.isShowing()) {
  216 + mProgressDialog.show();
  217 + mProgressDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(false);
  218 + }
  219 + }
  220 +
  221 + @Override
  222 + protected List<IChResult> doInBackground(String... params) {
  223 + int taskResultCount = -1;
  224 + synchronized (mLock) {
  225 + String apSsid = params[0];
  226 + String apBssid = params[1];
  227 + String apPassword = params[2];
  228 + String isSsidHiddenStr = params[3];
  229 + String taskResultCountStr = params[4];
  230 + boolean isSsidHidden = false;
  231 + if (isSsidHiddenStr.equals("YES")) {
  232 + isSsidHidden = true;
  233 + }
  234 + taskResultCount = Integer.parseInt(taskResultCountStr);
  235 + mChTask = new ChTask(apSsid, apBssid, apPassword, isSsidHidden, ConfigActivity.this);
  236 + mChTask.setChListener(myListener);
  237 + }
  238 + List<IChResult> resultList = mChTask.executeForResults(taskResultCount);
  239 + return resultList;
  240 + }
  241 +
  242 + @Override
  243 + protected void onPostExecute(List<IChResult> result) {
  244 + mProgressDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(true);
  245 + mProgressDialog.getButton(DialogInterface.BUTTON_POSITIVE).setText("确认");
  246 + IChResult firstResult = result.get(0);
  247 + // check whether the task is cancelled and no results received
  248 + if (!firstResult.isCancelled()) {
  249 + int count = 0;
  250 + // max results to be displayed, if it is more than maxDisplayCount,
  251 + // just show the count of redundant ones
  252 + final int maxDisplayCount = 5;
  253 + // the task received some results including cancelled while
  254 + // executing before receiving enough results
  255 + if (firstResult.isSuc()) {
  256 + StringBuilder sb = new StringBuilder();
  257 + for (IChResult resultInList : result) {
  258 + sb.append("配置成功" + "\n" + "BSSID = " + resultInList.getBssid() + "\n" + "InetAddress = " + resultInList.getInetAddress().getHostAddress());
  259 +
  260 + count++;
  261 + if (count >= maxDisplayCount) {
  262 + break;
  263 + }
  264 + }
  265 + if (count < result.size()) {
  266 + sb.append("\n有 " + (result.size() - count) + " 个结果未显示\n");
  267 + }
  268 + mProgressDialog.setMessage(sb.toString());
  269 + } else {
  270 + mProgressDialog.setMessage("配置失败");
  271 + }
  272 + }
  273 + }
  274 +
  275 + }
  276 +}
... ...
  1 +package com.xgimi.smartscreen;
  2 +
  3 +import android.app.Dialog;
  4 +import android.content.Context;
  5 +import android.os.Bundle;
  6 +import android.os.Handler;
  7 +import android.os.Looper;
  8 +import android.os.Message;
  9 +import android.text.method.ScrollingMovementMethod;
  10 +import android.util.Log;
  11 +import android.view.View;
  12 +import android.widget.TextView;
  13 +import android.widget.Toast;
  14 +import com.xgimi.gimicinema.R;
  15 +import org.json.JSONException;
  16 +import org.json.JSONObject;
  17 +
  18 +import java.io.BufferedReader;
  19 +import java.io.IOException;
  20 +import java.io.InputStreamReader;
  21 +import java.io.PrintWriter;
  22 +import java.net.Socket;
  23 +import java.net.SocketTimeoutException;
  24 +
  25 +
  26 +public class ControlDialog extends Dialog implements View.OnClickListener {
  27 + private static final String TAG = "ControlDialog";
  28 +
  29 + private Context mContext;
  30 + private String mDeviceIp;
  31 +
  32 + private TextView tvDeviceInfo;
  33 +
  34 + private MessageThread messageThread;
  35 + private static final int PORT = 8009;
  36 +
  37 + public ControlDialog(Context context, String DeviceIp) {
  38 + super(context);
  39 +
  40 + this.mContext = context;
  41 + this.mDeviceIp = DeviceIp;
  42 + }
  43 +
  44 + @Override
  45 + protected void onCreate(Bundle savedInstanceState) {
  46 + super.onCreate(savedInstanceState);
  47 + setContentView(R.layout.dialog_control);
  48 +
  49 + TextView tvDeviceIp = (TextView) findViewById(R.id.tv_dialog_ip);
  50 + tvDeviceIp.setText("[ " + mDeviceIp + " ]");
  51 +
  52 + tvDeviceInfo = (TextView) findViewById(R.id.tv_device_info);
  53 + tvDeviceInfo.setMovementMethod(ScrollingMovementMethod.getInstance());
  54 + tvDeviceInfo.setText("序列号:\n\n软件版本:\n\n硬件版本:\n\n幕布状态:");
  55 +
  56 + TextView tvUp = (TextView) findViewById(R.id.tv_up);
  57 + tvUp.setOnClickListener(this);
  58 +
  59 + TextView tvDown = (TextView) findViewById(R.id.tv_down);
  60 + tvDown.setOnClickListener(this);
  61 +
  62 +
  63 + messageThread = new MessageThread();
  64 +
  65 + new Thread(messageThread).start();
  66 +
  67 + new Handler().postDelayed(new Runnable() {
  68 + public void run() {
  69 + getDeviceInfo();
  70 + }
  71 + }, 1000);
  72 +
  73 + }
  74 +
  75 + private void getDeviceInfo() {
  76 + JSONObject dataGetInfo = new JSONObject();
  77 +
  78 + try {
  79 + dataGetInfo.put("cmd", 1);
  80 + } catch (JSONException e) {
  81 + e.printStackTrace();
  82 + }
  83 +
  84 + Message msgGetInfo = new Message();
  85 + msgGetInfo.what = 0x345;
  86 + msgGetInfo.obj = dataGetInfo;
  87 + messageThread.sendHandler.sendMessage(msgGetInfo);
  88 + }
  89 +
  90 + @Override
  91 + public void onClick(View v) {
  92 + switch (v.getId()) {
  93 + case R.id.tv_up:/*
  94 +
  95 +
  96 + MessageEvent msgEvent = new MessageEvent();
  97 + msgEvent.setEventId(SmartScreenBean.UPACTION);
  98 + msgEvent.setMessage("192.168.31.164");
  99 + EventBus.getDefault().post(msgEvent);*/
  100 + JSONObject dataUp = new JSONObject();
  101 + getDeviceInfo();
  102 + try {
  103 + dataUp.put("cmd", 2);
  104 + dataUp.put("action", 0);
  105 + } catch (JSONException e) {
  106 + e.printStackTrace();
  107 + }
  108 +
  109 + Message msgUp = new Message();
  110 + msgUp.what = 0x345;
  111 + msgUp.obj = dataUp;
  112 + messageThread.sendHandler.sendMessage(msgUp);
  113 +
  114 + break;
  115 +
  116 + case R.id.tv_down:
  117 +
  118 + /* MessageEvent msgEvent1 = new MessageEvent();
  119 + msgEvent1.setEventId(SmartScreenBean.DOWNACTION);
  120 + msgEvent1.setMessage("192.168.31.164");
  121 + EventBus.getDefault().post(msgEvent1);*/
  122 + JSONObject dataDown = new JSONObject();
  123 +
  124 + try {
  125 + dataDown.put("cmd", 2);
  126 + dataDown.put("action", 1);
  127 + } catch (JSONException e) {
  128 + e.printStackTrace();
  129 + }
  130 +
  131 + Message msgDown = new Message();
  132 + msgDown.what = 0x345;
  133 + msgDown.obj = dataDown;
  134 + messageThread.sendHandler.sendMessage(msgDown);
  135 +
  136 + break;
  137 + }
  138 + }
  139 +
  140 + Handler handler = new Handler() {
  141 + @Override
  142 + public void handleMessage(Message msg) {
  143 + super.handleMessage(msg);
  144 +
  145 + if (msg.what == 0x123) {
  146 + String data = (msg.obj).toString();
  147 +
  148 + try {
  149 + JSONObject jsonObject = new JSONObject(data);
  150 +
  151 + int cmd = jsonObject.getInt("cmd");
  152 +
  153 + if (cmd == 1) {
  154 + int sn = jsonObject.getInt("sn");
  155 + String swver = jsonObject.getString("swver");
  156 + String hdver = jsonObject.getString("hdver");
  157 +
  158 + tvDeviceInfo.setText("序列号:" + sn + "\n\n软件版本:" + swver + "\n\n硬件版本:" + hdver);
  159 +
  160 + } else if (cmd == 2) {
  161 + int result = jsonObject.getInt("result");
  162 + if (result == 1) { //成功
  163 + Toast.makeText(mContext, "操作成功", Toast.LENGTH_SHORT).show();
  164 + } else if (result == 0) { //失败
  165 + Toast.makeText(mContext, "操作失败", Toast.LENGTH_SHORT).show();
  166 + }
  167 + }
  168 +
  169 + } catch (JSONException e) {
  170 + e.printStackTrace();
  171 + }
  172 + }
  173 + }
  174 + };
  175 +
  176 +
  177 + public class MessageThread implements Runnable {
  178 + //接收UI线程消息的Handler对象
  179 + public Handler sendHandler;
  180 +
  181 + private Socket socket;
  182 + BufferedReader br = null;
  183 + PrintWriter pw = null;
  184 +
  185 + @Override
  186 + public void run() {
  187 +
  188 + try {
  189 + socket = new Socket(mDeviceIp, PORT);
  190 + br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  191 + pw = new PrintWriter(socket.getOutputStream());
  192 +
  193 + //启动一个线程来读取数据
  194 + new Thread(new Runnable() {
  195 + @Override
  196 + public void run() {
  197 +
  198 + String data = null;
  199 +
  200 + try {
  201 + while ((data = br.readLine()) != null) {
  202 + Log.i(TAG, "接收到的数据:" + data);
  203 +
  204 + Message msg = new Message();
  205 + msg.what = 0x123;
  206 + msg.obj = data;
  207 + handler.sendMessage(msg);
  208 + }
  209 +
  210 + } catch (IOException e) {
  211 + Log.i(TAG, "接收数据异常:" + e.getMessage());
  212 + e.printStackTrace();
  213 + }
  214 +
  215 + }
  216 + }).start();
  217 +
  218 + Looper.prepare();
  219 + sendHandler = new Handler() {
  220 + @Override
  221 + public void handleMessage(Message msg) {
  222 + super.handleMessage(msg);
  223 +
  224 + if (msg.what == 0x345) {
  225 + Log.i(TAG, "写数据:" + (msg.obj).toString());
  226 +// pw.write((msg.obj).toString());
  227 + pw.write("{\"cmd\":2,\"action\":0}");
  228 + pw.flush();
  229 + }
  230 + }
  231 + };
  232 + //启动Looper
  233 + Looper.loop();
  234 +
  235 + } catch (SocketTimeoutException e) {
  236 + Log.i(TAG, "网络连接超时!");
  237 + } catch (IOException e) {
  238 + e.printStackTrace();
  239 + } finally {
  240 + try {
  241 + if (pw != null) {
  242 + pw.close();
  243 + }
  244 + if (br != null) {
  245 + br.close();
  246 + }
  247 + if (socket != null) {
  248 + socket.close();
  249 + }
  250 + } catch (IOException e) {
  251 + e.printStackTrace();
  252 + }
  253 + }
  254 +
  255 + }
  256 + }
  257 +}
... ...
  1 +package com.xgimi.smartscreen;
  2 +
  3 +import android.app.Activity;
  4 +import android.os.AsyncTask;
  5 +import android.os.Bundle;
  6 +import android.util.Log;
  7 +import android.view.View;
  8 +import android.view.Window;
  9 +import android.widget.AdapterView;
  10 +import android.widget.ArrayAdapter;
  11 +import android.widget.ListView;
  12 +import android.widget.Toast;
  13 +import com.xgimi.gimicinema.R;
  14 +
  15 +import java.io.IOException;
  16 +import java.net.DatagramPacket;
  17 +import java.net.DatagramSocket;
  18 +import java.net.InetAddress;
  19 +import java.net.SocketException;
  20 +import java.net.UnknownHostException;
  21 +import java.util.ArrayList;
  22 +import java.util.List;
  23 +
  24 +public class MainActivity extends Activity {
  25 + private static final String TAG = "MainActivity";
  26 +
  27 + private ListView lvDevice;
  28 + List<String> listData;
  29 + ArrayAdapter<String> adapter;
  30 +
  31 +// private SwipeRefreshLayout swipeRefreshLayout;
  32 +
  33 + private boolean isSearching = false;
  34 +
  35 + @Override
  36 + protected void onCreate(Bundle savedInstanceState) {
  37 + super.onCreate(savedInstanceState);
  38 + setContentView(R.layout.content_main);
  39 +// Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
  40 +// setSupportActionBar(toolbar);
  41 +
  42 +// FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
  43 +// fab.setOnClickListener(new View.OnClickListener() {
  44 +// @Override
  45 +// public void onClick(View view) {
  46 +// startActivity(new Intent(MainActivity.this, ConfigActivity.class));
  47 +// }
  48 +// });
  49 +
  50 +// swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
  51 +//
  52 +// swipeRefreshLayout.setColorSchemeResources(R.color.g);
  53 +// swipeRefreshLayout.setSize(SwipeRefreshLayout.LARGE);
  54 +//
  55 +// swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
  56 +// @Override
  57 +// public void onRefresh() {
  58 +// }
  59 +// });
  60 +
  61 + lvDevice = (ListView) findViewById(R.id.lv_device);
  62 + lvDevice.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  63 + @Override
  64 + public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  65 + ControlDialog dialog = new ControlDialog(MainActivity.this, listData.get(position));
  66 + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); //去除标题栏
  67 + dialog.show();
  68 + }
  69 + });
  70 + new SearchAsyncTask().execute();
  71 +
  72 + }
  73 +
  74 + @Override
  75 + protected void onPause() {
  76 + super.onPause();
  77 +
  78 + isSearching = false;
  79 +
  80 +// swipeRefreshLayout.setRefreshing(false);
  81 + }
  82 +
  83 + private class SearchAsyncTask extends AsyncTask<Void, Integer, String> {
  84 +
  85 + InetAddress deviceAddress = null;
  86 + DatagramSocket socket = null;
  87 +
  88 + @Override
  89 + protected String doInBackground(Void... params) {
  90 + isSearching = true;
  91 +
  92 + try {
  93 + socket = new DatagramSocket();
  94 + } catch (SocketException e) {
  95 + e.printStackTrace();
  96 + }
  97 +
  98 + //接收
  99 + Thread receiveThread = new Thread(new Runnable() {
  100 + @Override
  101 + public void run() {
  102 +
  103 + byte[] dataReceive = new byte[1024];
  104 + DatagramPacket packetReceive = new DatagramPacket(dataReceive, dataReceive.length);
  105 +
  106 + try {
  107 + socket.receive(packetReceive);
  108 +
  109 + String reply = new String(dataReceive, 0, packetReceive.getLength());
  110 + if (reply.contains("I'm a screen Controller")) {
  111 + isSearching = false;
  112 +
  113 + deviceAddress = packetReceive.getAddress();
  114 + }
  115 + } catch (IOException e) {
  116 + e.printStackTrace();
  117 + }
  118 + }
  119 +
  120 + });
  121 +
  122 + receiveThread.start();
  123 +
  124 + int cnt = 3; //搜索次数
  125 +
  126 + while (isSearching) {
  127 + Log.i(TAG, "开始搜索...");
  128 +
  129 + if (--cnt == 0) {
  130 + break;
  131 + }
  132 +
  133 + //发送
  134 + String data = "Are You Screen Controller?";
  135 +
  136 + DatagramPacket packetSend = null;
  137 + try {
  138 + packetSend = new DatagramPacket(data.getBytes(), data.getBytes().length,
  139 + InetAddress.getByName("255.255.255.255"), 12419);
  140 + } catch (UnknownHostException e) {
  141 + e.printStackTrace();
  142 + }
  143 +
  144 + try {
  145 + socket.send(packetSend);
  146 + } catch (IOException e) {
  147 + e.printStackTrace();
  148 + }
  149 +
  150 + try {
  151 + Thread.sleep(5000);
  152 + } catch (InterruptedException e) {
  153 + e.printStackTrace();
  154 + }
  155 + }
  156 +
  157 + receiveThread.interrupt();
  158 +
  159 + if (deviceAddress != null) {
  160 + return deviceAddress.toString().substring(1); //去除ip地址前的斜杠
  161 + } else {
  162 + return null;
  163 + }
  164 + }
  165 +
  166 + @Override
  167 + protected void onPreExecute() {
  168 + super.onPreExecute();
  169 +
  170 +// swipeRefreshLayout.setRefreshing(true);
  171 +
  172 + if (lvDevice.getCount() != 0) {
  173 + adapter.clear();
  174 + adapter.notifyDataSetChanged();
  175 + }
  176 + }
  177 +
  178 + @Override
  179 + protected void onPostExecute(String s) {
  180 + super.onPostExecute(s);
  181 +
  182 +// swipeRefreshLayout.setRefreshing(false);
  183 +
  184 + if (s != null) {
  185 + listData = new ArrayList<String>();
  186 + listData.add(s);
  187 +
  188 + adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, listData);
  189 + lvDevice.setAdapter(adapter);
  190 + } else {
  191 + Toast.makeText(MainActivity.this, "没有搜索到设备,再次下拉搜索", Toast.LENGTH_SHORT).show();
  192 + }
  193 + }
  194 + }
  195 +
  196 +}
... ...
  1 +package com.xgimi.smartscreen;
  2 +
  3 +/**
  4 + * Created by Administrator on 2016/10/15.
  5 + */
  6 +public class SmartScreenBean {
  7 + public static final int UPACTION = 0;
  8 + public static final int DOWNACTION = 1;
  9 + public static final int STOPACTION = 2;
  10 +
  11 + public String ip;
  12 + public String name;
  13 + public int state;
  14 +
  15 +}
... ...
  1 +package com.xgimi.smartscreen;
  2 +
  3 +import android.app.Service;
  4 +import android.content.Context;
  5 +import android.content.Intent;
  6 +import android.os.IBinder;
  7 +import android.util.Log;
  8 +import com.gimi.common.cinema.model.MessageEvent;
  9 +import com.gimi.common.cinema.utils.SystemUtils;
  10 +import com.google.gson.Gson;
  11 +import com.google.gson.JsonSyntaxException;
  12 +import com.qnbar.smc.service.SocketResponse;
  13 +import com.qnbar.smc.service.SocketSendMsg;
  14 +import com.xgimi.gimicinema.BuildConfig;
  15 +import org.greenrobot.eventbus.EventBus;
  16 +
  17 +import java.io.IOException;
  18 +import java.io.InputStream;
  19 +import java.io.OutputStream;
  20 +import java.lang.ref.WeakReference;
  21 +import java.net.Socket;
  22 +import java.util.Arrays;
  23 +
  24 +public class SocketService extends Service {
  25 + private static final String TAG = "BackService";
  26 + private static final long HEART_BEAT_RATE = 10 * 1000;
  27 +
  28 + public static final int OPEN_DOOR_CMD = 1701;
  29 +
  30 + private static final int SUCESS_MESSAGE = 0;
  31 + private static final int ROOM_HAS_REGISTERED = 1001;
  32 + private static final int ROOM_NOT_EXIST_M = 1002;
  33 + private static final int HEAT_BEAT_RTN = 1003;
  34 +
  35 + public static final String HOST = "121.43.189.162";// "192.168.1.21";//
  36 + public static final int PORT = 9501;
  37 +
  38 + public static final String END_SYMBOL = "\\r\\n\\r\\n";//心跳包内容
  39 + public String testRoomSn = "000003";
  40 +
  41 + private ReadThread mReadThread;
  42 + private HeatBeatThread mHeatBeatThread;
  43 + private Gson gson;
  44 +
  45 +// private LocalBroadcastManager mLocalBroadcastManager;
  46 +
  47 + private WeakReference<Socket> mSocket;
  48 +
  49 + // For heart Beat
  50 +// private Handler mHandler = new Handler();
  51 +// private Runnable heartBeatRunnable = new Runnable() {
  52 +//
  53 +// @Override
  54 +// public void run() {
  55 +// if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
  56 +// Log.d(TAG, "heart beat");
  57 +// boolean isSuccess = sendMsg(new Gson().toJson(new SocketSendMsg().contractHeartBeatMsg(testRoomSn)) + END_SYMBOL);//就发送一个HEART_BEAT_STRING过去 如果发送失败,就重新初始化一个socket
  58 +// if (!isSuccess) {
  59 +// Log.d(TAG, "heart beat error restart");
  60 +// mHandler.removeCallbacks(heartBeatRunnable);
  61 +// mReadThread.release();
  62 +// mHeatBeatThread.release();
  63 +// releaseLastSocket(mSocket);
  64 +// new InitSocketThread().start();
  65 +// }
  66 +// } else {
  67 +// Log.d(TAG, "heart beat less than beat rate");
  68 +// }
  69 +// mHandler.postDelayed(this, HEART_BEAT_RATE);
  70 +// }
  71 +// };
  72 +
  73 + private long sendTime = 0L;
  74 + private Context context;
  75 +
  76 + @Override
  77 + public IBinder onBind(Intent arg0) {
  78 + return null;
  79 + }
  80 +
  81 + @Override
  82 + public void onCreate() {
  83 + super.onCreate();
  84 + gson = new Gson();
  85 + context = this;
  86 + //TODO change the room sn
  87 + if (!"LETEST".equals(SystemUtils.getPid(context, BuildConfig.MACHINE_TYPE))) {
  88 + testRoomSn = "000002";
  89 + }
  90 + new InitSocketThread().start();
  91 + Log.d(TAG, "socket service onCreate");
  92 + }
  93 +
  94 + public boolean sendMsg(String msg) {
  95 + if (null == mSocket || null == mSocket.get()) {
  96 + return false;
  97 + }
  98 + Log.d(TAG, "send msg:" + msg);
  99 + Socket soc = mSocket.get();
  100 + try {
  101 + if (!soc.isClosed() && !soc.isOutputShutdown()) {
  102 + OutputStream os = soc.getOutputStream();
  103 + String message = msg;
  104 + os.write(message.getBytes());
  105 + os.flush();
  106 + sendTime = System.currentTimeMillis();//每次发送成数据,就改一下最后成功发送的时间,节省心跳间隔时间
  107 + } else {
  108 + return false;
  109 + }
  110 + } catch (IOException e) {
  111 + e.printStackTrace();
  112 + return false;
  113 + }
  114 + return true;
  115 + }
  116 +
  117 + private void initSocket() throws IOException {//初始化Socket
  118 + Socket so = new Socket(HOST, PORT);
  119 + mSocket = new WeakReference<Socket>(so);
  120 + mReadThread = new ReadThread(so);
  121 + mReadThread.start();
  122 +// new Thread(heartBeatRunnable).start();
  123 +// mHandler.post(heartBeatRunnable);//初始化成功后,就准备发送心跳包
  124 + mHeatBeatThread = new HeatBeatThread(so);
  125 + mHeatBeatThread.start();//上面的 one plus 3t NetworkOnMainThreadException!!!
  126 + }
  127 +
  128 + private void releaseLastSocket(WeakReference<Socket> mSocket) {
  129 + try {
  130 + if (null != mSocket) {
  131 + Socket sk = mSocket.get();
  132 + if (!sk.isClosed()) {
  133 + sk.close();
  134 + }
  135 + sk = null;
  136 + mSocket = null;
  137 + }
  138 + } catch (IOException e) {
  139 + e.printStackTrace();
  140 + }
  141 + }
  142 +
  143 + class InitSocketThread extends Thread {
  144 + @Override
  145 + public void run() {
  146 + super.run();
  147 + try {
  148 + initSocket();
  149 + } catch (IOException e) {
  150 + e.printStackTrace();
  151 + Log.d(TAG, "init socket thread error,restart again after 10's");
  152 + try {
  153 + Thread.sleep(HEART_BEAT_RATE);
  154 + } catch (InterruptedException e1) {
  155 + e1.printStackTrace();
  156 + }
  157 + this.run();
  158 + }
  159 + }
  160 + }
  161 +
  162 + // Thread to read content from Socket
  163 + class ReadThread extends Thread {
  164 + private WeakReference<Socket> mWeakSocket;
  165 + private boolean isStart = true;
  166 +
  167 + public ReadThread(Socket socket) {
  168 + mWeakSocket = new WeakReference<Socket>(socket);
  169 + }
  170 +
  171 + public void release() {
  172 + isStart = false;
  173 + releaseLastSocket(mWeakSocket);
  174 + }
  175 +
  176 + @Override
  177 + public void run() {
  178 + super.run();
  179 + Socket socket = mWeakSocket.get();
  180 + if (null != socket) {
  181 + try {
  182 + if (!sendRegister) {
  183 + Log.d(TAG, "send register mes");
  184 + SocketSendMsg ssm = new SocketSendMsg().contractRegisterMsg(testRoomSn);
  185 + String msg = gson.toJson(ssm) + END_SYMBOL;
  186 + sendMsg(msg);
  187 + Log.d(TAG, "" + msg);
  188 + sendRegister = true;
  189 + }
  190 + Log.d(TAG, "send register mes end");
  191 + InputStream is = socket.getInputStream();
  192 + byte[] buffer = new byte[1024 * 4];
  193 + int length = 0;
  194 + while (!socket.isClosed() && !socket.isInputShutdown()
  195 + && isStart && ((length = is.read(buffer)) != -1)) {
  196 + if (length > 0) {
  197 + String message = new String(Arrays.copyOf(buffer,
  198 + length)).trim();
  199 + Log.d(TAG, "end:" + message.contains(END_SYMBOL) + "");
  200 + Log.d(TAG, "recv msg:" + message);
  201 + try {
  202 + SocketResponse socketResponse = gson.fromJson(message.trim(), SocketResponse.class);
  203 + switch (socketResponse.getCode()) {
  204 + case SUCESS_MESSAGE:
  205 + Log.d(TAG, "success:" + socketResponse.getCmd());
  206 + break;
  207 + case ROOM_HAS_REGISTERED:
  208 + SocketSendMsg ssm = new SocketSendMsg().contractReconnectMsg(testRoomSn);
  209 + String msg = gson.toJson(ssm) + END_SYMBOL;
  210 + sendMsg(msg);
  211 + Log.d(TAG, "send reconnect mes: " + msg);
  212 + break;
  213 + case ROOM_NOT_EXIST_M:
  214 + Log.d(TAG, "re init socket");
  215 + //sendRegister = false;
  216 + releaseLastSocket(mWeakSocket);
  217 + initSocket();
  218 + break;
  219 + case HEAT_BEAT_RTN:
  220 + Log.d(TAG, "HEAT_BEAT_RTN");
  221 + sendTime = System.currentTimeMillis();
  222 + break;
  223 + }
  224 + if (("openDoor").equals(socketResponse.getCmd())) {
  225 + MessageEvent messageEvent = new MessageEvent();
  226 + messageEvent.setEventId(OPEN_DOOR_CMD);
  227 + messageEvent.setMessage("click item");
  228 + EventBus.getDefault().post(messageEvent);
  229 + }
  230 + } catch (JsonSyntaxException e) {
  231 + Log.d(TAG, message);
  232 + e.printStackTrace();
  233 + }
  234 + //收到服务器过来的消息,就通过Broadcast发送出去
  235 +// if (message.equals(END_SYMBOL)) {//处理心跳回复
  236 +// Intent intent = new Intent(HEART_BEAT_ACTION);
  237 +// mLocalBroadcastManager.sendBroadcast(intent);
  238 +// } else {
  239 +// //其他消息回复
  240 +// Intent intent = new Intent(MESSAGE_ACTION);
  241 +// intent.putExtra("message", message);
  242 +// mLocalBroadcastManager.sendBroadcast(intent);
  243 +// }
  244 + }
  245 + }
  246 + } catch (IOException e) {
  247 + e.printStackTrace();
  248 + }
  249 + }
  250 + }
  251 + }
  252 +
  253 + boolean sendRegister = false;
  254 +
  255 +
  256 + // Thread to read content from Socket
  257 + class HeatBeatThread extends Thread {
  258 + private WeakReference<Socket> mWeakSocket;
  259 + private boolean isStart = true;
  260 +
  261 + public HeatBeatThread(Socket socket) {
  262 + mWeakSocket = new WeakReference<Socket>(socket);
  263 + }
  264 +
  265 + public void release() {
  266 + isStart = false;
  267 + releaseLastSocket(mWeakSocket);
  268 + }
  269 +
  270 + @Override
  271 + public void run() {
  272 + super.run();
  273 + Socket socket = mWeakSocket.get();
  274 + if (null != socket) {
  275 + while (isStart) {
  276 + if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
  277 + Log.d(TAG, "heart beat:" + Thread.currentThread().getId());
  278 + boolean isSuccess = sendMsg(new Gson().toJson(new SocketSendMsg().contractHeartBeatMsg(testRoomSn)) + END_SYMBOL);//就发送一个HEART_BEAT_STRING过去 如果发送失败,就重新初始化一个socket
  279 + if (!isSuccess) {
  280 + Log.d(TAG, "heart beat error restart:" + Thread.currentThread().getId());
  281 +// mHandler.removeCallbacks(heartBeatRunnable);
  282 + mReadThread.release();
  283 + mHeatBeatThread.release();
  284 + sendRegister = false;
  285 + releaseLastSocket(mSocket);
  286 + new InitSocketThread().start();
  287 + }
  288 + } else {
  289 + Log.d(TAG, "heart beat less than beat rate:" + Thread.currentThread().getId());
  290 + }
  291 + try {
  292 + Thread.sleep(HEART_BEAT_RATE);
  293 + } catch (InterruptedException e) {
  294 + e.printStackTrace();
  295 + }
  296 + }
  297 + }
  298 + }
  299 + }
  300 +
  301 + @Override
  302 + public void onDestroy() {
  303 + super.onDestroy();
  304 + Log.d(TAG, "socket service destroy");
  305 + }
  306 +}
\ No newline at end of file
... ...
  1 +package com.xgimi.smartscreen.confignetwork;
  2 +
  3 +import java.net.InetAddress;
  4 +import java.util.concurrent.atomic.AtomicBoolean;
  5 +
  6 +public class ChResult implements IChResult {
  7 +
  8 + private final boolean mIsSuc;
  9 + private final String mBssid;
  10 + private final InetAddress mInetAddress;
  11 + private AtomicBoolean mIsCancelled;
  12 +
  13 + /**
  14 + * Constructor of ChResult
  15 + *
  16 + * @param isSuc whether the ch task is executed suc
  17 + * @param bssid the device's bssid
  18 + * @param inetAddress the device's ip address
  19 + */
  20 + public ChResult(boolean isSuc, String bssid, InetAddress inetAddress) {
  21 + this.mIsSuc = isSuc;
  22 + this.mBssid = bssid;
  23 + this.mInetAddress = inetAddress;
  24 + this.mIsCancelled = new AtomicBoolean(false);
  25 + }
  26 +
  27 + @Override
  28 + public boolean isSuc() {
  29 + return this.mIsSuc;
  30 + }
  31 +
  32 + @Override
  33 + public String getBssid() {
  34 + return this.mBssid;
  35 + }
  36 +
  37 + @Override
  38 + public boolean isCancelled() {
  39 + return mIsCancelled.get();
  40 + }
  41 +
  42 + public void setIsCancelled(boolean isCancelled) {
  43 + this.mIsCancelled.set(isCancelled);
  44 + }
  45 +
  46 + @Override
  47 + public InetAddress getInetAddress() {
  48 + return this.mInetAddress;
  49 + }
  50 +
  51 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork;
  2 +
  3 +import android.content.Context;
  4 +
  5 +import com.xgimi.smartscreen.confignetwork.task.ChTaskParameter;
  6 +import com.xgimi.smartscreen.confignetwork.task.IChTaskParameter;
  7 +import com.xgimi.smartscreen.confignetwork.task.__ChTask;
  8 +
  9 +import java.util.List;
  10 +
  11 +
  12 +public class ChTask implements IChTask {
  13 +
  14 + public __ChTask _mChTask;
  15 + private IChTaskParameter _mParameter;
  16 +
  17 + /**
  18 + * Constructor of ChTask
  19 + *
  20 + * @param apSsid the Ap's ssid
  21 + * @param apBssid the Ap's bssid
  22 + * @param apPassword the Ap's password
  23 + * @param isSsidHidden whether the Ap's ssid is hidden
  24 + * @param context the Context of the Application
  25 + */
  26 + public ChTask(String apSsid, String apBssid, String apPassword, boolean isSsidHidden, Context context) {
  27 + _mParameter = new ChTaskParameter();
  28 + _mChTask = new __ChTask(apSsid, apBssid, apPassword, context, _mParameter, isSsidHidden);
  29 + }
  30 +
  31 + /**
  32 + * Constructor of ChTask
  33 + *
  34 + * @param apSsid the Ap's ssid
  35 + * @param apBssid the Ap's bssid
  36 + * @param apPassword the Ap's password
  37 + * @param isSsidHidden whether the Ap's ssid is hidden
  38 + * @param timeoutMillisecond (it should be >= 15000+6000) millisecond of total timeout
  39 + * @param context the Context of the Application
  40 + */
  41 + public ChTask(String apSsid, String apBssid, String apPassword, boolean isSsidHidden, int timeoutMillisecond, Context context) {
  42 + _mParameter = new ChTaskParameter();
  43 + _mParameter.setWaitUdpTotalMillisecond(timeoutMillisecond);
  44 + _mChTask = new __ChTask(apSsid, apBssid, apPassword, context, _mParameter, isSsidHidden);
  45 + }
  46 +
  47 + @Override
  48 + public void interrupt() {
  49 + _mChTask.interrupt();
  50 + }
  51 +
  52 + @Override
  53 + public IChResult executeForResult() throws RuntimeException {
  54 + return _mChTask.executeForResult();
  55 + }
  56 +
  57 + @Override
  58 + public boolean isCancelled() {
  59 + return _mChTask.isCancelled();
  60 + }
  61 +
  62 + @Override
  63 + public List<IChResult> executeForResults(int expectTaskResultCount) throws RuntimeException {
  64 + if (expectTaskResultCount <= 0) {
  65 + expectTaskResultCount = Integer.MAX_VALUE;
  66 + }
  67 + return _mChTask.executeForResults(expectTaskResultCount);
  68 + }
  69 +
  70 + @Override
  71 + public void setChListener(IChListener chListener) {
  72 + _mChTask.setChListener(chListener);
  73 + }
  74 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork;
  2 +
  3 +public interface IChListener {
  4 + /**
  5 + * when new ch result is added, the listener will call
  6 + * onChResultAdded callback
  7 + *
  8 + * @param result the Ch result
  9 + */
  10 + void onChResultAdded(IChResult result);
  11 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork;
  2 +
  3 +import java.net.InetAddress;
  4 +
  5 +public interface IChResult {
  6 +
  7 + /**
  8 + * check whether the ch task is executed suc
  9 + *
  10 + * @return whether the ch task is executed suc
  11 + */
  12 + boolean isSuc();
  13 +
  14 + /**
  15 + * get the device's bssid
  16 + *
  17 + * @return the device's bssid
  18 + */
  19 + String getBssid();
  20 +
  21 + /**
  22 + * check whether the ch task is cancelled by user
  23 + *
  24 + * @return whether the ch task is cancelled by user
  25 + */
  26 + boolean isCancelled();
  27 +
  28 + /**
  29 + * get the ip address of the device
  30 + *
  31 + * @return the ip device of the device
  32 + */
  33 + InetAddress getInetAddress();
  34 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork;
  2 +
  3 +import java.util.List;
  4 +
  5 +public interface IChTask {
  6 +
  7 + /**
  8 + * set the ch listener, when one device is connected to the Ap, it will be called back
  9 + *
  10 + * @param chListener when one device is connected to the Ap, it will be called back
  11 + */
  12 + void setChListener(IChListener chListener);
  13 +
  14 + /**
  15 + * Interrupt the Ch Task when User tap back or close the Application.
  16 + */
  17 + void interrupt();
  18 +
  19 + /**
  20 + * Note: !!!Don't call the task at UI Main Thread or RuntimeException will
  21 + * be thrown Execute the Ch Task and return the result
  22 + * <p/>
  23 + * Smart Config v2.4 support the API
  24 + *
  25 + * @return the IChResult
  26 + * @throws RuntimeException
  27 + */
  28 + IChResult executeForResult() throws RuntimeException;
  29 +
  30 + /**
  31 + * Note: !!!Don't call the task at UI Main Thread or RuntimeException will
  32 + * be thrown Execute the Ch Task and return the result
  33 + * <p/>
  34 + * Smart Config v2.4 support the API
  35 + * <p/>
  36 + * It will be blocked until the client receive result count >= expectTaskResultCount.
  37 + * If it fail, it will return one fail result will be returned in the list.
  38 + * If it is cancelled while executing,
  39 + * if it has received some results, all of them will be returned in the list.
  40 + * if it hasn't received any results, one cancel result will be returned in the list.
  41 + *
  42 + * @param expectTaskResultCount the expect result count(if expectTaskResultCount <= 0,
  43 + * expectTaskResultCount = Integer.MAX_VALUE)
  44 + * @return the list of IChResult
  45 + * @throws RuntimeException
  46 + */
  47 + List<IChResult> executeForResults(int expectTaskResultCount) throws RuntimeException;
  48 +
  49 + /**
  50 + * check whether the task is cancelled by user
  51 + *
  52 + * @return whether the task is cancelled by user
  53 + */
  54 + boolean isCancelled();
  55 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork.protocol;
  2 +
  3 +import com.xgimi.smartscreen.confignetwork.task.IChGenerator;
  4 +import com.xgimi.smartscreen.confignetwork.util.ByteUtil;
  5 +
  6 +import java.net.InetAddress;
  7 +
  8 +
  9 +public class ChGenerator implements IChGenerator {
  10 +
  11 + private final byte[][] mGcBytes2;
  12 + private final byte[][] mDcBytes2;
  13 +
  14 + /**
  15 + * Constructor of ChGenerator, it will cost some time(maybe a bit
  16 + * much)
  17 + *
  18 + * @param apSsid the Ap's ssid
  19 + * @param apBssid the Ap's bssid
  20 + * @param apPassword the Ap's password
  21 + * @param inetAddress the phone's or pad's local ip address allocated by Ap
  22 + * @param isSsidHiden whether the Ap's ssid is hidden
  23 + */
  24 + public ChGenerator(String apSsid, String apBssid, String apPassword, InetAddress inetAddress, boolean isSsidHiden) {
  25 + // generate guide code
  26 + GuideCode gc = new GuideCode();
  27 + char[] gcU81 = gc.getU8s();
  28 + mGcBytes2 = new byte[gcU81.length][];
  29 +
  30 + for (int i = 0; i < mGcBytes2.length; i++) {
  31 + mGcBytes2[i] = ByteUtil.genSpecBytes(gcU81[i]);
  32 + }
  33 +
  34 + // generate data code
  35 + DatumCode dc = new DatumCode(apSsid, apBssid, apPassword, inetAddress,
  36 + isSsidHiden);
  37 + char[] dcU81 = dc.getU8s();
  38 + mDcBytes2 = new byte[dcU81.length][];
  39 +
  40 + for (int i = 0; i < mDcBytes2.length; i++) {
  41 + mDcBytes2[i] = ByteUtil.genSpecBytes(dcU81[i]);
  42 + }
  43 + }
  44 +
  45 + @Override
  46 + public byte[][] getGCBytes2() {
  47 + return mGcBytes2;
  48 + }
  49 +
  50 + @Override
  51 + public byte[][] getDCBytes2() {
  52 + return mDcBytes2;
  53 + }
  54 +
  55 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork.protocol;
  2 +
  3 +
  4 +import com.xgimi.smartscreen.confignetwork.task.ICodeData;
  5 +import com.xgimi.smartscreen.confignetwork.util.ByteUtil;
  6 +import com.xgimi.smartscreen.confignetwork.util.CRC8;
  7 +
  8 +/**
  9 + * one data format:(data code should have 2 to 65 data)
  10 + *
  11 + * control byte high 4 bits low 4 bits
  12 + * 1st 9bits: 0x0 crc(high) data(high)
  13 + * 2nd 9bits: 0x1 sequence header
  14 + * 3rd 9bits: 0x0 crc(low) data(low)
  15 + *
  16 + * sequence header: 0,1,2,...
  17 + *
  18 + * @author afunx
  19 + *
  20 + */
  21 +public class DataCode implements ICodeData {
  22 +
  23 + public static final int DATA_CODE_LEN = 6;
  24 +
  25 + private static final int INDEX_MAX = 127;
  26 +
  27 + private final byte mSeqHeader;
  28 + private final byte mDataHigh;
  29 + private final byte mDataLow;
  30 + // the crc here means the crc of the data and sequence header be transformed
  31 + // it is calculated by index and data to be transformed
  32 + private final byte mCrcHigh;
  33 + private final byte mCrcLow;
  34 +
  35 + /**
  36 + * Constructor of DataCode
  37 + * @param u8 the character to be transformed
  38 + * @param index the index of the char
  39 + */
  40 + public DataCode(char u8, int index) {
  41 + if (index > INDEX_MAX) {
  42 + throw new RuntimeException("index > INDEX_MAX");
  43 + }
  44 + byte[] dataBytes = ByteUtil.splitUint8To2bytes(u8);
  45 + mDataHigh = dataBytes[0];
  46 + mDataLow = dataBytes[1];
  47 + CRC8 crc8 = new CRC8();
  48 + crc8.update(ByteUtil.convertUint8toByte(u8));
  49 + crc8.update(index);
  50 + byte[] crcBytes = ByteUtil.splitUint8To2bytes((char) crc8.getValue());
  51 + mCrcHigh = crcBytes[0];
  52 + mCrcLow = crcBytes[1];
  53 + mSeqHeader = (byte) index;
  54 + }
  55 +
  56 + @Override
  57 + public byte[] getBytes() {
  58 + byte[] dataBytes = new byte[DATA_CODE_LEN];
  59 + dataBytes[0] = 0x00;
  60 + dataBytes[1] = ByteUtil.combine2bytesToOne(mCrcHigh,mDataHigh);
  61 + dataBytes[2] = 0x01;
  62 + dataBytes[3] = mSeqHeader;
  63 + dataBytes[4] = 0x00;
  64 + dataBytes[5] = ByteUtil.combine2bytesToOne(mCrcLow, mDataLow);
  65 + return dataBytes;
  66 + }
  67 +
  68 + @Override
  69 + public String toString() {
  70 + StringBuilder sb = new StringBuilder();
  71 + byte[] dataBytes = getBytes();
  72 + for (int i = 0; i < DATA_CODE_LEN; i++) {
  73 + String hexString = ByteUtil.convertByte2HexString(dataBytes[i]);
  74 + sb.append("0x");
  75 + if (hexString.length() == 1) {
  76 + sb.append("0");
  77 + }
  78 + sb.append(hexString).append(" ");
  79 + }
  80 + return sb.toString();
  81 + }
  82 +
  83 + @Override
  84 + public char[] getU8s() {
  85 + throw new RuntimeException("DataCode don't support getU8s()");
  86 + }
  87 +
  88 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork.protocol;
  2 +
  3 +import com.xgimi.smartscreen.confignetwork.task.ICodeData;
  4 +import com.xgimi.smartscreen.confignetwork.util.ByteUtil;
  5 +import com.xgimi.smartscreen.confignetwork.util.CRC8;
  6 +import com.xgimi.smartscreen.confignetwork.util.NetUtil;
  7 +
  8 +import java.net.InetAddress;
  9 +
  10 +
  11 +public class DatumCode implements ICodeData {
  12 +
  13 + // define by the Ch protocol, all of the datum code should add 1 at last to prevent 0
  14 + private static final int EXTRA_LEN = 40;
  15 + private static final int EXTRA_HEAD_LEN = 5;
  16 +
  17 + private final DataCode[] mDataCodes;
  18 +
  19 + /**
  20 + * Constructor of DatumCode
  21 + * @param apSsid the Ap's ssid
  22 + * @param apBssid the Ap's bssid
  23 + * @param apPassword the Ap's password
  24 + * @param ipAddress the ip address of the phone or pad
  25 + * @param isSsidHiden whether the Ap's ssid is hidden
  26 + */
  27 + public DatumCode(String apSsid, String apBssid, String apPassword, InetAddress ipAddress, boolean isSsidHiden) {
  28 + // Data = total len(1 byte) + apPwd len(1 byte) + SSID CRC(1 byte) +
  29 + // BSSID CRC(1 byte) + TOTAL XOR(1 byte)+ ipAddress(4 byte) + apPwd + apSsid apPwdLen <=
  30 + // 105 at the moment
  31 +
  32 + // total xor
  33 + char totalXor = 0;
  34 +
  35 + char apPwdLen = (char) ByteUtil.getBytesByString(apPassword).length;
  36 + CRC8 crc = new CRC8();
  37 + crc.update(ByteUtil.getBytesByString(apSsid));
  38 + char apSsidCrc = (char) crc.getValue();
  39 +
  40 + crc.reset();
  41 + crc.update(NetUtil.parseBssid2bytes(apBssid));
  42 + char apBssidCrc = (char) crc.getValue();
  43 +
  44 + char apSsidLen = (char) ByteUtil.getBytesByString(apSsid).length;
  45 + // hostname parse
  46 + String ipAddrStrs[] = ipAddress.getHostAddress().split("\\.");
  47 + int ipLen = ipAddrStrs.length;
  48 +
  49 + char ipAddrChars[] = new char[ipLen];
  50 + // only support ipv4 at the moment
  51 + for (int i = 0; i < ipLen; ++i) {
  52 + ipAddrChars[i] = (char) Integer.parseInt(ipAddrStrs[i]);
  53 + }
  54 +
  55 +
  56 + char _totalLen = (char) (EXTRA_HEAD_LEN + ipLen + apPwdLen + apSsidLen);
  57 + char totalLen = isSsidHiden ? (char) (EXTRA_HEAD_LEN + ipLen + apPwdLen + apSsidLen)
  58 + : (char) (EXTRA_HEAD_LEN + ipLen + apPwdLen);
  59 +
  60 + // build data codes
  61 + mDataCodes = new DataCode[totalLen];
  62 + mDataCodes[0] = new DataCode(_totalLen, 0);
  63 + totalXor ^= _totalLen;
  64 + mDataCodes[1] = new DataCode(apPwdLen, 1);
  65 + totalXor ^= apPwdLen;
  66 + mDataCodes[2] = new DataCode(apSsidCrc, 2);
  67 + totalXor ^= apSsidCrc;
  68 + mDataCodes[3] = new DataCode(apBssidCrc, 3);
  69 + totalXor ^= apBssidCrc;
  70 + mDataCodes[4] = null;
  71 + for (int i = 0; i < ipLen; ++i) {
  72 + mDataCodes[i + EXTRA_HEAD_LEN] = new DataCode(ipAddrChars[i], i + EXTRA_HEAD_LEN);
  73 + totalXor ^= ipAddrChars[i];
  74 + }
  75 +
  76 + byte[] apPwdBytes = ByteUtil.getBytesByString(apPassword);
  77 + char[] apPwdChars = new char[apPwdBytes.length];
  78 + for (int i = 0;i < apPwdBytes.length; i++) {
  79 + apPwdChars[i] = ByteUtil.convertByte2Uint8(apPwdBytes[i]);
  80 + }
  81 + for (int i = 0; i < apPwdChars.length; i++) {
  82 + mDataCodes[i + EXTRA_HEAD_LEN + ipLen] = new DataCode(
  83 + apPwdChars[i], i + EXTRA_HEAD_LEN + ipLen);
  84 + totalXor ^= apPwdChars[i];
  85 + }
  86 +
  87 + byte[] apSsidBytes = ByteUtil.getBytesByString(apSsid);
  88 + char[] apSsidChars = new char[apSsidBytes.length];
  89 +
  90 + // totalXor will xor apSsidChars no matter whether the ssid is hidden
  91 + for (int i = 0; i < apSsidBytes.length; i++) {
  92 + apSsidChars[i] = ByteUtil.convertByte2Uint8(apSsidBytes[i]);
  93 + totalXor ^= apSsidChars[i];
  94 + }
  95 +
  96 + if (isSsidHiden) {
  97 + for (int i = 0; i < apSsidChars.length; i++) {
  98 + mDataCodes[i + EXTRA_HEAD_LEN + ipLen + apPwdLen] = new DataCode(
  99 + apSsidChars[i], i + EXTRA_HEAD_LEN + ipLen + apPwdLen);
  100 + }
  101 + }
  102 +
  103 + // set total xor last
  104 + mDataCodes[4] = new DataCode(totalXor, 4);
  105 + }
  106 +
  107 + @Override
  108 + public byte[] getBytes() {
  109 + byte[] datumCode = new byte[mDataCodes.length * DataCode.DATA_CODE_LEN];
  110 + for (int i = 0; i < mDataCodes.length; i++) {
  111 + System.arraycopy(mDataCodes[i].getBytes(), 0, datumCode, i
  112 + * DataCode.DATA_CODE_LEN, DataCode.DATA_CODE_LEN);
  113 + }
  114 + return datumCode;
  115 + }
  116 +
  117 + @Override
  118 + public String toString() {
  119 + StringBuilder sb = new StringBuilder();
  120 + byte[] dataBytes = getBytes();
  121 + for (int i = 0; i < dataBytes.length; i++) {
  122 + String hexString = ByteUtil.convertByte2HexString(dataBytes[i]);
  123 + sb.append("0x");
  124 + if (hexString.length() == 1) {
  125 + sb.append("0");
  126 + }
  127 + sb.append(hexString).append(" ");
  128 + }
  129 + return sb.toString();
  130 + }
  131 +
  132 + @Override
  133 + public char[] getU8s() {
  134 + byte[] dataBytes = getBytes();
  135 + int len = dataBytes.length / 2;
  136 + char[] dataU8s = new char[len];
  137 + byte high, low;
  138 + for (int i = 0; i < len; i++) {
  139 + high = dataBytes[i * 2];
  140 + low = dataBytes[i * 2 + 1];
  141 + dataU8s[i] = (char) (ByteUtil.combine2bytesToU16(high, low) + EXTRA_LEN);
  142 + }
  143 + return dataU8s;
  144 + }
  145 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork.protocol;
  2 +
  3 +
  4 +import com.xgimi.smartscreen.confignetwork.task.ICodeData;
  5 +import com.xgimi.smartscreen.confignetwork.util.ByteUtil;
  6 +
  7 +public class GuideCode implements ICodeData {
  8 +
  9 + public static final int GUIDE_CODE_LEN = 4;
  10 +
  11 + @Override
  12 + public byte[] getBytes() {
  13 + throw new RuntimeException("DataCode don't support getBytes()");
  14 + }
  15 +
  16 + @Override
  17 + public String toString() {
  18 + StringBuilder sb = new StringBuilder();
  19 + char[] dataU8s = getU8s();
  20 + for (int i = 0; i < GUIDE_CODE_LEN; i++) {
  21 + String hexString = ByteUtil.convertU8ToHexString(dataU8s[i]);
  22 + sb.append("0x");
  23 + if (hexString.length() == 1) {
  24 + sb.append("0");
  25 + }
  26 + sb.append(hexString).append(" ");
  27 + }
  28 + return sb.toString();
  29 + }
  30 +
  31 + @Override
  32 + public char[] getU8s() {
  33 + char[] guidesU8s = new char[GUIDE_CODE_LEN];
  34 + guidesU8s[0] = 515;
  35 + guidesU8s[1] = 514;
  36 + guidesU8s[2] = 513;
  37 + guidesU8s[3] = 512;
  38 + return guidesU8s;
  39 + }
  40 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork.task;
  2 +
  3 +public class ChTaskParameter implements IChTaskParameter {
  4 +
  5 + private long mIntervalGuideCodeMillisecond;
  6 + private long mIntervalDataCodeMillisecond;
  7 + private long mTimeoutGuideCodeMillisecond;
  8 + private long mTimeoutDataCodeMillisecond;
  9 + private int mTotalRepeatTime;
  10 + private int mChResultOneLen;
  11 + private int mChResultMacLen;
  12 + private int mChResultIpLen;
  13 + private int mChResultTotalLen;
  14 + private int mPortListening;
  15 + private int mTargetPort;
  16 + private int mWaitUdpReceivingMilliseond;
  17 + private int mWaitUdpSendingMillisecond;
  18 + private int mThresholdSucBroadcastCount;
  19 + private int mExpectTaskResultCount;
  20 + private static int _datagramCount = 0;
  21 +
  22 + public ChTaskParameter() {
  23 + mIntervalGuideCodeMillisecond = 10;
  24 + mIntervalDataCodeMillisecond = 10;
  25 + mTimeoutGuideCodeMillisecond = 2000;
  26 + mTimeoutDataCodeMillisecond = 4000;
  27 + mTotalRepeatTime = 1;
  28 + mChResultOneLen = 1;
  29 + mChResultMacLen = 6;
  30 + mChResultIpLen = 4;
  31 + mChResultTotalLen = 1 + 6 + 4;
  32 + mPortListening = 18266;
  33 + mTargetPort = 7001;
  34 + mWaitUdpReceivingMilliseond = 15000;
  35 + mWaitUdpSendingMillisecond = 45000;
  36 + mThresholdSucBroadcastCount = 1;
  37 + mExpectTaskResultCount = 1;
  38 + }
  39 +
  40 + // the range of the result should be 1-100
  41 + private static int __getNextDatagramCount() {
  42 + return 1 + (_datagramCount++) % 100;
  43 + }
  44 +
  45 + @Override
  46 + public long getIntervalGuideCodeMillisecond() {
  47 + return mIntervalGuideCodeMillisecond;
  48 + }
  49 +
  50 + @Override
  51 + public long getIntervalDataCodeMillisecond() {
  52 + return mIntervalDataCodeMillisecond;
  53 + }
  54 +
  55 + @Override
  56 + public long getTimeoutGuideCodeMillisecond() {
  57 + return mTimeoutGuideCodeMillisecond;
  58 + }
  59 +
  60 + @Override
  61 + public long getTimeoutDataCodeMillisecond() {
  62 + return mTimeoutDataCodeMillisecond;
  63 + }
  64 +
  65 + @Override
  66 + public long getTimeoutTotalCodeMillisecond() {
  67 + return mTimeoutGuideCodeMillisecond + mTimeoutDataCodeMillisecond;
  68 + }
  69 +
  70 + @Override
  71 + public int getTotalRepeatTime() {
  72 + return mTotalRepeatTime;
  73 + }
  74 +
  75 + @Override
  76 + public int getChResultOneLen() {
  77 + return mChResultOneLen;
  78 + }
  79 +
  80 + @Override
  81 + public int getChResultMacLen() {
  82 + return mChResultMacLen;
  83 + }
  84 +
  85 + @Override
  86 + public int getChResultIpLen() {
  87 + return mChResultIpLen;
  88 + }
  89 +
  90 + @Override
  91 + public int getChResultTotalLen() {
  92 + return mChResultTotalLen;
  93 + }
  94 +
  95 + @Override
  96 + public int getPortListening() {
  97 + return mPortListening;
  98 + }
  99 +
  100 + // target hostname is : 234.1.1.1, 234.2.2.2, 234.3.3.3 to 234.100.100.100
  101 + @Override
  102 + public String getTargetHostname() {
  103 + int count = __getNextDatagramCount();
  104 + return "234." + count + "." + count + "." + count;
  105 + }
  106 +
  107 + @Override
  108 + public int getTargetPort() {
  109 + return mTargetPort;
  110 + }
  111 +
  112 + @Override
  113 + public int getWaitUdpReceivingMillisecond() {
  114 + return mWaitUdpReceivingMilliseond;
  115 + }
  116 +
  117 + @Override
  118 + public int getWaitUdpSendingMillisecond() {
  119 + return mWaitUdpSendingMillisecond;
  120 + }
  121 +
  122 + @Override
  123 + public int getWaitUdpTotalMillisecond() {
  124 + return mWaitUdpReceivingMilliseond + mWaitUdpSendingMillisecond;
  125 + }
  126 +
  127 + @Override
  128 + public int getThresholdSucBroadcastCount() {
  129 + return mThresholdSucBroadcastCount;
  130 + }
  131 +
  132 + @Override
  133 + public void setWaitUdpTotalMillisecond(int waitUdpTotalMillisecond) {
  134 + if (waitUdpTotalMillisecond < mWaitUdpReceivingMilliseond
  135 + + getTimeoutTotalCodeMillisecond()) {
  136 + // if it happen, even one turn about sending udp broadcast can't be
  137 + // completed
  138 + throw new IllegalArgumentException(
  139 + "waitUdpTotalMillisecod is invalid, "
  140 + + "it is less than mWaitUdpReceivingMilliseond + getTimeoutTotalCodeMillisecond()");
  141 + }
  142 + mWaitUdpSendingMillisecond = waitUdpTotalMillisecond
  143 + - mWaitUdpReceivingMilliseond;
  144 + }
  145 +
  146 + @Override
  147 + public int getExpectTaskResultCount() {
  148 + return this.mExpectTaskResultCount;
  149 + }
  150 +
  151 + @Override
  152 + public void setExpectTaskResultCount(int expectTaskResultCount) {
  153 + this.mExpectTaskResultCount = expectTaskResultCount;
  154 + }
  155 +
  156 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork.task;
  2 +
  3 +public interface IChGenerator {
  4 + /**
  5 + * Get guide code by the format of byte[][]
  6 + *
  7 + * @return guide code by the format of byte[][]
  8 + */
  9 + byte[][] getGCBytes2();
  10 +
  11 + /**
  12 + * Get data code by the format of byte[][]
  13 + *
  14 + * @return data code by the format of byte[][]
  15 + */
  16 + byte[][] getDCBytes2();
  17 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork.task;
  2 +
  3 +public interface IChTaskParameter {
  4 +
  5 + /**
  6 + * get interval millisecond for guide code(the time between each guide code sending)
  7 + * @return interval millisecond for guide code(the time between each guide code sending)
  8 + */
  9 + long getIntervalGuideCodeMillisecond();
  10 +
  11 + /**
  12 + * get interval millisecond for data code(the time between each data code sending)
  13 + * @return interval millisecond for data code(the time between each data code sending)
  14 + */
  15 + long getIntervalDataCodeMillisecond();
  16 +
  17 + /**
  18 + * get timeout millisecond for guide code(the time how much the guide code sending)
  19 + * @return timeout millisecond for guide code(the time how much the guide code sending)
  20 + */
  21 + long getTimeoutGuideCodeMillisecond();
  22 +
  23 + /**
  24 + * get timeout millisecond for data code(the time how much the data code sending)
  25 + * @return timeout millisecond for data code(the time how much the data code sending)
  26 + */
  27 + long getTimeoutDataCodeMillisecond();
  28 +
  29 + /**
  30 + * get timeout millisecond for total code(guide code and data code altogether)
  31 + * @return timeout millisecond for total code(guide code and data code altogether)
  32 + */
  33 + long getTimeoutTotalCodeMillisecond();
  34 +
  35 + /**
  36 + * get total repeat time for executing ch task
  37 + * @return total repeat time for executing ch task
  38 + */
  39 + int getTotalRepeatTime();
  40 +
  41 + /**
  42 + * the length of the Ch result 1st byte is the total length of ssid and
  43 + * password, the other 6 bytes are the device's bssid
  44 + */
  45 +
  46 + /**
  47 + * get chResult length of one
  48 + * @return length of one
  49 + */
  50 + int getChResultOneLen();
  51 +
  52 + /**
  53 + * get chResult length of mac
  54 + * @return length of mac
  55 + */
  56 + int getChResultMacLen();
  57 +
  58 + /**
  59 + * get chResult length of ip
  60 + * @return length of ip
  61 + */
  62 + int getChResultIpLen();
  63 +
  64 + /**
  65 + * get chResult total length
  66 + * @return total length
  67 + */
  68 + int getChResultTotalLen();
  69 +
  70 + /**
  71 + * get port for listening(used by server)
  72 + * @return port for listening(used by server)
  73 + */
  74 + int getPortListening();
  75 +
  76 + /**
  77 + * get target hostname
  78 + * @return target hostame(used by client)
  79 + */
  80 + String getTargetHostname();
  81 +
  82 + /**
  83 + * get target port
  84 + * @return target port(used by client)
  85 + */
  86 + int getTargetPort();
  87 +
  88 + /**
  89 + * get millisecond for waiting udp receiving(receiving without sending)
  90 + * @return millisecond for waiting udp receiving(receiving without sending)
  91 + */
  92 + int getWaitUdpReceivingMillisecond();
  93 +
  94 + /**
  95 + * get millisecond for waiting udp sending(sending including receiving)
  96 + * @return millisecond for waiting udep sending(sending including receiving)
  97 + */
  98 + int getWaitUdpSendingMillisecond();
  99 +
  100 + /**
  101 + * get millisecond for waiting udp sending and receiving
  102 + * @return millisecond for waiting udp sending and receiving
  103 + */
  104 + int getWaitUdpTotalMillisecond();
  105 +
  106 + /**
  107 + * get the threshold for how many correct broadcast should be received
  108 + * @return the threshold for how many correct broadcast should be received
  109 + */
  110 + int getThresholdSucBroadcastCount();
  111 +
  112 + /**
  113 + * set the millisecond for waiting udp sending and receiving
  114 + * @param waitUdpTotalMillisecond the millisecond for waiting udp sending and receiving
  115 + */
  116 + void setWaitUdpTotalMillisecond(int waitUdpTotalMillisecond);
  117 +
  118 + /**
  119 + * get the count of expect task results
  120 + * @return the count of expect task results
  121 + */
  122 + int getExpectTaskResultCount();
  123 +
  124 + /**
  125 + * set the count of expect task results
  126 + * @param expectTaskResultCount the count of expect task results
  127 + */
  128 + void setExpectTaskResultCount(int expectTaskResultCount);
  129 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork.task;
  2 +
  3 +/**
  4 + * the class used to represent some code to be transformed by UDP socket should implement the interface
  5 + * @author afunx
  6 + *
  7 + */
  8 +public interface ICodeData {
  9 + /**
  10 + * Get the byte[] to be transformed.
  11 + *
  12 + *
  13 + * @return the byte[] to be transfromed
  14 + */
  15 + byte[] getBytes();
  16 +
  17 + /**
  18 + * Get the char[](u8[]) to be transfromed.
  19 + *
  20 + * @return the char[](u8) to be transformed
  21 + */
  22 + char[] getU8s();
  23 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork.task;
  2 +
  3 +import android.content.Context;
  4 +import android.os.Looper;
  5 +import android.text.TextUtils;
  6 +import android.util.Log;
  7 +
  8 +import com.xgimi.smartscreen.confignetwork.ChResult;
  9 +import com.xgimi.smartscreen.confignetwork.IChListener;
  10 +import com.xgimi.smartscreen.confignetwork.IChResult;
  11 +import com.xgimi.smartscreen.confignetwork.protocol.ChGenerator;
  12 +import com.xgimi.smartscreen.confignetwork.udp.UDPSocketClient;
  13 +import com.xgimi.smartscreen.confignetwork.udp.UDPSocketServer;
  14 +import com.xgimi.smartscreen.confignetwork.util.ByteUtil;
  15 +import com.xgimi.smartscreen.confignetwork.util.NetUtil;
  16 +
  17 +import java.net.InetAddress;
  18 +import java.util.ArrayList;
  19 +import java.util.HashMap;
  20 +import java.util.List;
  21 +import java.util.Map;
  22 +import java.util.concurrent.atomic.AtomicBoolean;
  23 +
  24 +public class __ChTask implements __IChTask {
  25 +
  26 + /**
  27 + * one indivisible data contain 3 9bits info
  28 + */
  29 + private static final int ONE_DATA_LEN = 3;
  30 +
  31 + private static final String TAG = "ChTask";
  32 +
  33 + private volatile List<IChResult> mChResultList;
  34 + private volatile boolean mIsSuc = false;
  35 + private volatile boolean mIsInterrupt = false;
  36 + private volatile boolean mIsExecuted = false;
  37 + private final UDPSocketClient mSocketClient;
  38 + private final UDPSocketServer mSocketServer;
  39 + private final String mApSsid;
  40 + private final String mApBssid;
  41 + private final boolean mIsSsidHidden;
  42 + private final String mApPassword;
  43 + private final Context mContext;
  44 + private AtomicBoolean mIsCancelled;
  45 + private IChTaskParameter mParameter;
  46 + private volatile Map<String, Integer> mBssidTaskSucCountMap;
  47 + private IChListener mChListener;
  48 +
  49 + public __ChTask(String apSsid, String apBssid, String apPassword,
  50 + Context context, IChTaskParameter parameter,
  51 + boolean isSsidHidden) {
  52 + if (TextUtils.isEmpty(apSsid)) {
  53 + throw new IllegalArgumentException("the apSsid should be null or empty");
  54 + }
  55 + if (apPassword == null) {
  56 + apPassword = "";
  57 + }
  58 + mContext = context;
  59 + mApSsid = apSsid;
  60 + mApBssid = apBssid;
  61 + mApPassword = apPassword;
  62 + mIsCancelled = new AtomicBoolean(false);
  63 + mSocketClient = new UDPSocketClient();
  64 + mParameter = parameter;
  65 + mSocketServer = new UDPSocketServer(mParameter.getPortListening(),
  66 + mParameter.getWaitUdpTotalMillisecond(), context);
  67 + mIsSsidHidden = isSsidHidden;
  68 + mChResultList = new ArrayList<IChResult>();
  69 + mBssidTaskSucCountMap = new HashMap<String, Integer>();
  70 + }
  71 +
  72 + private void __putChResult(boolean isSuc, String bssid, InetAddress inetAddress) {
  73 + synchronized (mChResultList) {
  74 + // check whether the result receive enough UDP response
  75 + boolean isTaskSucCountEnough = false;
  76 + Integer count = mBssidTaskSucCountMap.get(bssid);
  77 + if (count == null) {
  78 + count = 0;
  79 + }
  80 + ++count;
  81 + if (__IChTask.DEBUG) {
  82 + Log.d(TAG, "__putChResult(): count = " + count);
  83 + }
  84 + mBssidTaskSucCountMap.put(bssid, count);
  85 + isTaskSucCountEnough = count >= mParameter
  86 + .getThresholdSucBroadcastCount();
  87 + if (!isTaskSucCountEnough) {
  88 + if (__IChTask.DEBUG) {
  89 + Log.d(TAG, "__putChResult(): count = " + count + ", isn't enough");
  90 + }
  91 + return;
  92 + }
  93 + // check whether the result is in the mChResultList already
  94 + boolean isExist = false;
  95 + for (IChResult chResultInList : mChResultList) {
  96 + if (chResultInList.getBssid().equals(bssid)) {
  97 + isExist = true;
  98 + break;
  99 + }
  100 + }
  101 + // only add the result who isn't in the mChResultList
  102 + if (!isExist) {
  103 + if (__IChTask.DEBUG) {
  104 + Log.d(TAG, "__putChResult(): put one more result");
  105 + }
  106 + final IChResult chResult = new ChResult(isSuc, bssid, inetAddress);
  107 + mChResultList.add(chResult);
  108 + if (mChListener != null) {
  109 + mChListener.onChResultAdded(chResult);
  110 + }
  111 + }
  112 + }
  113 + }
  114 +
  115 + private List<IChResult> __getChResultList() {
  116 + synchronized (mChResultList) {
  117 + if (mChResultList.isEmpty()) {
  118 + ChResult chResultFail = new ChResult(false, null, null);
  119 + chResultFail.setIsCancelled(mIsCancelled.get());
  120 + mChResultList.add(chResultFail);
  121 + }
  122 +
  123 + return mChResultList;
  124 + }
  125 + }
  126 +
  127 + private synchronized void __interrupt() {
  128 + if (!mIsInterrupt) {
  129 + mIsInterrupt = true;
  130 + mSocketClient.interrupt();
  131 + mSocketServer.interrupt();
  132 + // interrupt the current Thread which is used to wait for udp response
  133 + Thread.currentThread().interrupt();
  134 + }
  135 + }
  136 +
  137 + @Override
  138 + public void interrupt() {
  139 + if (__IChTask.DEBUG) {
  140 + Log.d(TAG, "interrupt()");
  141 + }
  142 + mIsCancelled.set(true);
  143 + __interrupt();
  144 + }
  145 +
  146 + private void __listenAsyn(final int expectDataLen) {
  147 + new Thread() {
  148 + public void run() {
  149 + if (__IChTask.DEBUG) {
  150 + Log.d(TAG, "__listenAsyn() start");
  151 + }
  152 + long startTimestamp = System.currentTimeMillis();
  153 + byte[] apSsidAndPassword = ByteUtil.getBytesByString(mApSsid + mApPassword);
  154 + byte expectOneByte = (byte) (apSsidAndPassword.length + 9);
  155 + if (__IChTask.DEBUG) {
  156 + Log.i(TAG, "expectOneByte: " + (0 + expectOneByte));
  157 + }
  158 + byte receiveOneByte = -1;
  159 + byte[] receiveBytes = null;
  160 + while (mChResultList.size() < mParameter.getExpectTaskResultCount() && !mIsInterrupt) {
  161 + receiveBytes = mSocketServer.receiveSpecLenBytes(expectDataLen);
  162 + if (receiveBytes != null) {
  163 + receiveOneByte = receiveBytes[0];
  164 + } else {
  165 + receiveOneByte = -1;
  166 + }
  167 + if (receiveOneByte == expectOneByte) {
  168 + if (__IChTask.DEBUG) {
  169 + Log.i(TAG, "receive correct broadcast");
  170 + }
  171 + // change the socket's timeout
  172 + long consume = System.currentTimeMillis() - startTimestamp;
  173 + int timeout = (int) (mParameter.getWaitUdpTotalMillisecond() - consume);
  174 + if (timeout < 0) {
  175 + if (__IChTask.DEBUG) {
  176 + Log.i(TAG, "ch timeout");
  177 + }
  178 + break;
  179 + } else {
  180 + if (__IChTask.DEBUG) {
  181 + Log.i(TAG, "mSocketServer's new timeout is " + timeout + " milliseconds");
  182 + }
  183 + mSocketServer.setSoTimeout(timeout);
  184 + if (__IChTask.DEBUG) {
  185 + Log.i(TAG, "receive correct broadcast");
  186 + }
  187 + if (receiveBytes != null) {
  188 + String bssid = ByteUtil.parseBssid(
  189 + receiveBytes,
  190 + mParameter.getChResultOneLen(),
  191 + mParameter.getChResultMacLen());
  192 + InetAddress inetAddress = NetUtil.parseInetAddr(
  193 + receiveBytes,
  194 + mParameter.getChResultOneLen() + mParameter.getChResultMacLen(),
  195 + mParameter.getChResultIpLen());
  196 + __putChResult(true, bssid, inetAddress);
  197 + }
  198 + }
  199 + } else {
  200 + if (__IChTask.DEBUG) {
  201 + Log.i(TAG, "receive rubbish message, just ignore");
  202 + }
  203 + }
  204 + }
  205 + mIsSuc = mChResultList.size() >= mParameter.getExpectTaskResultCount();
  206 + __ChTask.this.__interrupt();
  207 + if (__IChTask.DEBUG) {
  208 + Log.d(TAG, "__listenAsyn() finish");
  209 + }
  210 + }
  211 + }.start();
  212 + }
  213 +
  214 + private boolean __execute(IChGenerator generator) {
  215 +
  216 + long startTime = System.currentTimeMillis();
  217 + long currentTime = startTime;
  218 + long lastTime = currentTime - mParameter.getTimeoutTotalCodeMillisecond();
  219 +
  220 + byte[][] gcBytes2 = generator.getGCBytes2();
  221 + byte[][] dcBytes2 = generator.getDCBytes2();
  222 +
  223 + int index = 0;
  224 + while (!mIsInterrupt) {
  225 + if (currentTime - lastTime >= mParameter.getTimeoutTotalCodeMillisecond()) {
  226 + if (__IChTask.DEBUG) {
  227 + Log.d(TAG, "send gc code ");
  228 + }
  229 + // send guide code
  230 + while (!mIsInterrupt && System.currentTimeMillis() - currentTime < mParameter.getTimeoutGuideCodeMillisecond()) {
  231 + mSocketClient.sendData(gcBytes2,
  232 + mParameter.getTargetHostname(),
  233 + mParameter.getTargetPort(),
  234 + mParameter.getIntervalGuideCodeMillisecond());
  235 + // check whether the udp is send enough time
  236 + if (System.currentTimeMillis() - startTime > mParameter.getWaitUdpSendingMillisecond()) {
  237 + break;
  238 + }
  239 + }
  240 + lastTime = currentTime;
  241 + } else {
  242 + mSocketClient.sendData(dcBytes2, index, ONE_DATA_LEN,
  243 + mParameter.getTargetHostname(),
  244 + mParameter.getTargetPort(),
  245 + mParameter.getIntervalDataCodeMillisecond());
  246 + index = (index + ONE_DATA_LEN) % dcBytes2.length;
  247 + }
  248 + currentTime = System.currentTimeMillis();
  249 + // check whether the udp is send enough time
  250 + if (currentTime - startTime > mParameter.getWaitUdpSendingMillisecond()) {
  251 + break;
  252 + }
  253 + }
  254 +
  255 + return mIsSuc;
  256 + }
  257 +
  258 + private void __checkTaskValid() {
  259 + // !!!NOTE: the ch task could be executed only once
  260 + if (this.mIsExecuted) {
  261 + throw new IllegalStateException("the Ch task could be executed only once");
  262 + }
  263 + this.mIsExecuted = true;
  264 + }
  265 +
  266 + @Override
  267 + public IChResult executeForResult() throws RuntimeException {
  268 + return executeForResults(1).get(0);
  269 + }
  270 +
  271 + @Override
  272 + public boolean isCancelled() {
  273 + return this.mIsCancelled.get();
  274 + }
  275 +
  276 + @Override
  277 + public List<IChResult> executeForResults(int expectTaskResultCount)
  278 + throws RuntimeException {
  279 + __checkTaskValid();
  280 +
  281 + mParameter.setExpectTaskResultCount(expectTaskResultCount);
  282 +
  283 + if (__IChTask.DEBUG) {
  284 + Log.d(TAG, "execute()");
  285 + }
  286 + if (Looper.myLooper() == Looper.getMainLooper()) {
  287 + throw new RuntimeException(
  288 + "Don't call the ch Task at Main(UI) thread directly.");
  289 + }
  290 + InetAddress localInetAddress = NetUtil.getLocalInetAddress(mContext);
  291 + if (__IChTask.DEBUG) {
  292 + Log.i(TAG, "localInetAddress: " + localInetAddress);
  293 + }
  294 + // generator the ch byte[][] to be transformed, which will cost
  295 + // some time(maybe a bit much)
  296 + IChGenerator generator = new ChGenerator(mApSsid, mApBssid,
  297 + mApPassword, localInetAddress, mIsSsidHidden);
  298 + // listen the ch result asyn
  299 + __listenAsyn(mParameter.getChResultTotalLen());
  300 + boolean isSuc = false;
  301 + for (int i = 0; i < mParameter.getTotalRepeatTime(); i++) {
  302 + isSuc = __execute(generator);
  303 + if (isSuc) {
  304 + return __getChResultList();
  305 + }
  306 + }
  307 +
  308 + if (!mIsInterrupt) {
  309 + // wait the udp response without sending udp broadcast
  310 + try {
  311 + Thread.sleep(mParameter.getWaitUdpReceivingMillisecond());
  312 + } catch (InterruptedException e) {
  313 + // receive the udp broadcast or the user interrupt the task
  314 + if (this.mIsSuc) {
  315 + return __getChResultList();
  316 + } else {
  317 + this.__interrupt();
  318 + return __getChResultList();
  319 + }
  320 + }
  321 + this.__interrupt();
  322 + }
  323 +
  324 + return __getChResultList();
  325 + }
  326 +
  327 + @Override
  328 + public void setChListener(IChListener chListener) {
  329 + mChListener = chListener;
  330 + }
  331 +
  332 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork.task;
  2 +
  3 +import com.xgimi.smartscreen.confignetwork.IChListener;
  4 +import com.xgimi.smartscreen.confignetwork.IChResult;
  5 +
  6 +import java.util.List;
  7 +
  8 +
  9 +/**
  10 + * IChTask defined the task of ch should offer. INTERVAL here means
  11 + * the milliseconds of interval of the step. REPEAT here means the repeat times
  12 + * of the step.
  13 + *
  14 + * @author afunx
  15 + *
  16 + */
  17 +public interface __IChTask {
  18 +
  19 + /**
  20 + * set the ch listener, when one device is connected to the Ap, it will be called back
  21 + * @param chListener when one device is connected to the Ap, it will be called back
  22 + */
  23 + void setChListener(IChListener chListener);
  24 +
  25 + /**
  26 + * Interrupt the Ch Task when User tap back or close the Application.
  27 + */
  28 + void interrupt();
  29 +
  30 + /**
  31 + * Note: !!!Don't call the task at UI Main Thread or RuntimeException will
  32 + * be thrown Execute the Ch Task and return the result
  33 + *
  34 + * @return the IChResult
  35 + * @throws RuntimeException
  36 + */
  37 + IChResult executeForResult() throws RuntimeException;
  38 +
  39 + /**
  40 + * Note: !!!Don't call the task at UI Main Thread or RuntimeException will
  41 + * be thrown Execute the Ch Task and return the result
  42 + *
  43 + * @param expectTaskResultCount
  44 + * the expect result count(if expectTaskResultCount <= 0,
  45 + * expectTaskResultCount = Integer.MAX_VALUE)
  46 + * @return the list of IChResult
  47 + * @throws RuntimeException
  48 + */
  49 + List<IChResult> executeForResults(int expectTaskResultCount) throws RuntimeException;
  50 +
  51 + /**
  52 + * Turn on or off the log.
  53 + */
  54 + static final boolean DEBUG = true;
  55 +
  56 + boolean isCancelled();
  57 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork.udp;
  2 +
  3 +import android.util.Log;
  4 +
  5 +import com.xgimi.smartscreen.confignetwork.task.__IChTask;
  6 +
  7 +import java.io.IOException;
  8 +import java.net.DatagramPacket;
  9 +import java.net.DatagramSocket;
  10 +import java.net.InetAddress;
  11 +import java.net.SocketException;
  12 +import java.net.UnknownHostException;
  13 +
  14 +/**
  15 + * this class is used to help send UDP data according to length
  16 + *
  17 + * @author afunx
  18 + */
  19 +public class UDPSocketClient {
  20 +
  21 + private static final String TAG = "UDPSocketClient";
  22 + private DatagramSocket mSocket;
  23 + private volatile boolean mIsStop;
  24 + private volatile boolean mIsClosed;
  25 +
  26 + public UDPSocketClient() {
  27 + try {
  28 + this.mSocket = new DatagramSocket();
  29 + this.mIsStop = false;
  30 + this.mIsClosed = false;
  31 + } catch (SocketException e) {
  32 + if (__IChTask.DEBUG) {
  33 + Log.e(TAG, "SocketException");
  34 + }
  35 + e.printStackTrace();
  36 + }
  37 + }
  38 +
  39 + @Override
  40 + protected void finalize() throws Throwable {
  41 + close();
  42 + super.finalize();
  43 + }
  44 +
  45 + public void interrupt() {
  46 + if (__IChTask.DEBUG) {
  47 + Log.i(TAG, "USPSocketClient is interrupt");
  48 + }
  49 + this.mIsStop = true;
  50 + }
  51 +
  52 + /**
  53 + * close the UDP socket
  54 + */
  55 + public synchronized void close() {
  56 + if (!this.mIsClosed) {
  57 + this.mSocket.close();
  58 + this.mIsClosed = true;
  59 + }
  60 + }
  61 +
  62 + /**
  63 + * send the data by UDP
  64 + *
  65 + * @param data the data to be sent
  66 + * @param targetHostName the host name of target, e.g. 192.168.1.101
  67 + * @param targetPort the port of target
  68 + * @param interval the milliseconds to between each UDP sent
  69 + */
  70 + public void sendData(byte[][] data, String targetHostName, int targetPort, long interval) {
  71 + sendData(data, 0, data.length, targetHostName, targetPort, interval);
  72 + }
  73 +
  74 +
  75 + /**
  76 + * send the data by UDP
  77 + *
  78 + * @param data the data to be sent
  79 + * @param offset the offset which data to be sent
  80 + * @param count the count of the data
  81 + * @param targetHostName the host name of target, e.g. 192.168.1.101
  82 + * @param targetPort the port of target
  83 + * @param interval the milliseconds to between each UDP sent
  84 + */
  85 + public void sendData(byte[][] data, int offset, int count, String targetHostName, int targetPort, long interval) {
  86 + if ((data == null) || (data.length <= 0)) {
  87 + if (__IChTask.DEBUG) {
  88 + Log.e(TAG, "sendData(): data == null or length <= 0");
  89 + }
  90 + return;
  91 + }
  92 + for (int i = offset; !mIsStop && i < offset + count; i++) {
  93 + if (data[i].length == 0) {
  94 + continue;
  95 + }
  96 + try {
  97 + // Log.i(TAG, "data[" + i + " +].length = " + data[i].length);
  98 + DatagramPacket localDatagramPacket = new DatagramPacket(
  99 + data[i], data[i].length,
  100 + InetAddress.getByName(targetHostName), targetPort);
  101 + this.mSocket.send(localDatagramPacket);
  102 + } catch (UnknownHostException e) {
  103 + if (__IChTask.DEBUG) {
  104 + Log.e(TAG, "sendData(): UnknownHostException");
  105 + }
  106 + e.printStackTrace();
  107 + mIsStop = true;
  108 + break;
  109 + } catch (IOException e) {
  110 + if (__IChTask.DEBUG) {
  111 + Log.e(TAG, "sendData(): IOException, but just ignore it");
  112 + }
  113 + // for the Ap will make some troubles when the phone send too many UDP packets,
  114 + // but we don't expect the UDP packet received by others, so just ignore it
  115 + }
  116 + try {
  117 + Thread.sleep(interval);
  118 + } catch (InterruptedException e) {
  119 + e.printStackTrace();
  120 + if (__IChTask.DEBUG) {
  121 + Log.e(TAG, "sendData is Interrupted");
  122 + }
  123 + mIsStop = true;
  124 + break;
  125 + }
  126 + }
  127 + if (mIsStop) {
  128 + close();
  129 + }
  130 + }
  131 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork.udp;
  2 +
  3 +import android.content.Context;
  4 +import android.net.wifi.WifiManager;
  5 +import android.util.Log;
  6 +
  7 +import java.io.IOException;
  8 +import java.net.DatagramPacket;
  9 +import java.net.DatagramSocket;
  10 +import java.net.SocketException;
  11 +import java.util.Arrays;
  12 +
  13 +public class UDPSocketServer {
  14 +
  15 + private static final String TAG = "UDPSocketServer";
  16 + private DatagramPacket mReceivePacket;
  17 + private DatagramSocket mServerSocket;
  18 + private Context mContext;
  19 + private WifiManager.MulticastLock mLock;
  20 + private final byte[] buffer;
  21 + private volatile boolean mIsClosed;
  22 +
  23 + private synchronized void acquireLock() {
  24 + if (mLock != null && !mLock.isHeld()) {
  25 + mLock.acquire();
  26 + }
  27 + }
  28 +
  29 + private synchronized void releaseLock() {
  30 + if (mLock != null && mLock.isHeld()) {
  31 + try {
  32 + mLock.release();
  33 + } catch (Throwable th) {
  34 + // ignoring this exception, probably wakeLock was already released
  35 + }
  36 + }
  37 + }
  38 +
  39 + /**
  40 + * Constructor of UDP Socket Server
  41 + *
  42 + * @param port the Socket Server port
  43 + * @param socketTimeout the socket read timeout
  44 + * @param context the context of the Application
  45 + */
  46 + public UDPSocketServer(int port, int socketTimeout, Context context) {
  47 + this.mContext = context;
  48 + this.buffer = new byte[64];
  49 + this.mReceivePacket = new DatagramPacket(buffer, 64);
  50 + try {
  51 + this.mServerSocket = new DatagramSocket(port);
  52 + this.mServerSocket.setSoTimeout(socketTimeout);
  53 + this.mIsClosed = false;
  54 + WifiManager manager = (WifiManager) mContext
  55 + .getSystemService(Context.WIFI_SERVICE);
  56 + mLock = manager.createMulticastLock("test wifi");
  57 + Log.d(TAG, "mServerSocket is created, socket read timeout: "
  58 + + socketTimeout + ", port: " + port);
  59 + } catch (IOException e) {
  60 + Log.e(TAG, "IOException");
  61 + e.printStackTrace();
  62 + }
  63 + }
  64 +
  65 + /**
  66 + * Set the socket timeout in milliseconds
  67 + *
  68 + * @param timeout the timeout in milliseconds or 0 for no timeout.
  69 + * @return true whether the timeout is set suc
  70 + */
  71 + public boolean setSoTimeout(int timeout) {
  72 + try {
  73 + this.mServerSocket.setSoTimeout(timeout);
  74 + return true;
  75 + } catch (SocketException e) {
  76 + e.printStackTrace();
  77 + }
  78 + return false;
  79 + }
  80 +
  81 + /**
  82 + * Receive one byte from the port and convert it into String
  83 + *
  84 + * @return
  85 + */
  86 + public byte receiveOneByte() {
  87 + Log.d(TAG, "receiveOneByte() entrance");
  88 + try {
  89 + acquireLock();
  90 + mServerSocket.receive(mReceivePacket);
  91 + Log.d(TAG, "receive: " + (0 + mReceivePacket.getData()[0]));
  92 + return mReceivePacket.getData()[0];
  93 + } catch (IOException e) {
  94 + e.printStackTrace();
  95 + }
  96 + return Byte.MIN_VALUE;
  97 + }
  98 +
  99 + /**
  100 + * Receive specific length bytes from the port and convert it into String
  101 + * 21,24,-2,52,-102,-93,-60
  102 + * 15,18,fe,34,9a,a3,c4
  103 + *
  104 + * @return
  105 + */
  106 + public byte[] receiveSpecLenBytes(int len) {
  107 + Log.d(TAG, "receiveSpecLenBytes() entrance: len = " + len);
  108 + try {
  109 + acquireLock();
  110 + mServerSocket.receive(mReceivePacket);
  111 + byte[] recDatas = Arrays.copyOf(mReceivePacket.getData(), mReceivePacket.getLength());
  112 + Log.d(TAG, "received len : " + recDatas.length);
  113 + for (int i = 0; i < recDatas.length; i++) {
  114 + Log.e(TAG, "recDatas[" + i + "]:" + recDatas[i]);
  115 + }
  116 + Log.e(TAG, "receiveSpecLenBytes: " + new String(recDatas));
  117 + if (recDatas.length != len) {
  118 + Log.w(TAG,
  119 + "received len is different from specific len, return null");
  120 + return null;
  121 + }
  122 + return recDatas;
  123 + } catch (IOException e) {
  124 + e.printStackTrace();
  125 + }
  126 + return null;
  127 + }
  128 +
  129 + public void interrupt() {
  130 + Log.i(TAG, "USPSocketServer is interrupt");
  131 + close();
  132 + }
  133 +
  134 + public synchronized void close() {
  135 + if (!this.mIsClosed) {
  136 + Log.e(TAG, "mServerSocket is closed");
  137 + mServerSocket.close();
  138 + releaseLock();
  139 + this.mIsClosed = true;
  140 + }
  141 + }
  142 +
  143 + @Override
  144 + protected void finalize() throws Throwable {
  145 + close();
  146 + super.finalize();
  147 + }
  148 +
  149 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork.util;
  2 +
  3 +import java.io.UnsupportedEncodingException;
  4 +import java.util.Random;
  5 +
  6 +/**
  7 + * In Java, it don't support unsigned int, so we use char to replace uint8.
  8 + * The range of byte is [-128,127], and the range of char is [0,65535].
  9 + * So the byte could used to store the uint8.
  10 + * (We assume that the String could be mapped to assic)
  11 + *
  12 + * @author afunx
  13 + */
  14 +public class ByteUtil {
  15 +
  16 + public static final String ESPTOUCH_ENCODING_CHARSET = "UTF-8";
  17 +
  18 + /**
  19 + * Put String to byte[]
  20 + *
  21 + * @param destbytes the byte[] of dest
  22 + * @param srcString the String of src
  23 + * @param destOffset the offset of byte[]
  24 + * @param srcOffset the offset of String
  25 + * @param count the count of dest, and the count of src as well
  26 + */
  27 + public static void putString2bytes(byte[] destbytes, String srcString,
  28 + int destOffset, int srcOffset, int count) {
  29 + for (int i = 0; i < count; i++) {
  30 + destbytes[count + i] = srcString.getBytes()[i];
  31 + }
  32 + }
  33 +
  34 + /**
  35 + * Convert uint8 into char( we treat char as uint8)
  36 + *
  37 + * @param uint8 the unit8 to be converted
  38 + * @return the byte of the unint8
  39 + */
  40 + public static byte convertUint8toByte(char uint8) {
  41 + if (uint8 > Byte.MAX_VALUE - Byte.MIN_VALUE) {
  42 + throw new RuntimeException("Out of Boundary");
  43 + }
  44 + return (byte) uint8;
  45 + }
  46 +
  47 + /**
  48 + * Convert char into uint8( we treat char as uint8 )
  49 + *
  50 + * @param b the byte to be converted
  51 + * @return the char(uint8)
  52 + */
  53 + public static char convertByte2Uint8(byte b) {
  54 + // char will be promoted to int for char don't support & operator
  55 + // & 0xff could make negatvie value to positive
  56 + return (char) (b & 0xff);
  57 + }
  58 +
  59 + /**
  60 + * Convert byte[] into char[]( we treat char[] as uint8[])
  61 + *
  62 + * @param bytes the byte[] to be converted
  63 + * @return the char[](uint8[])
  64 + */
  65 + public static char[] convertBytes2Uint8s(byte[] bytes) {
  66 + int len = bytes.length;
  67 + char[] uint8s = new char[len];
  68 + for (int i = 0; i < len; i++) {
  69 + uint8s[i] = convertByte2Uint8(bytes[i]);
  70 + }
  71 + return uint8s;
  72 + }
  73 +
  74 + /**
  75 + * Put byte[] into char[]( we treat char[] as uint8[])
  76 + *
  77 + * @param destUint8s the char[](uint8[]) array
  78 + * @param srcBytes the byte[]
  79 + * @param destOffset the offset of char[](uint8[])
  80 + * @param srcOffset the offset of byte[]
  81 + * @param count the count of dest, and the count of src as well
  82 + */
  83 + public static void putbytes2Uint8s(char[] destUint8s, byte[] srcBytes, int destOffset, int srcOffset, int count) {
  84 + for (int i = 0; i < count; i++) {
  85 + destUint8s[destOffset + i] = convertByte2Uint8(srcBytes[srcOffset + i]);
  86 + }
  87 + }
  88 +
  89 + /**
  90 + * Convert byte to Hex String
  91 + *
  92 + * @param b the byte to be converted
  93 + * @return the Hex String
  94 + */
  95 + public static String convertByte2HexString(byte b) {
  96 + char u8 = convertByte2Uint8(b);
  97 + return Integer.toHexString(u8);
  98 + }
  99 +
  100 + /**
  101 + * Convert char(uint8) to Hex String
  102 + *
  103 + * @param u8 the char(uint8) to be converted
  104 + * @return the Hex String
  105 + */
  106 + public static String convertU8ToHexString(char u8) {
  107 + return Integer.toHexString(u8);
  108 + }
  109 +
  110 + /**
  111 + * Split uint8 to 2 bytes of high byte and low byte. e.g. 20 = 0x14 should
  112 + * be split to [0x01,0x04] 0x01 is high byte and 0x04 is low byte
  113 + *
  114 + * @param uint8 the char(uint8)
  115 + * @return the high and low bytes be split, byte[0] is high and byte[1] is
  116 + * low
  117 + */
  118 + public static byte[] splitUint8To2bytes(char uint8) {
  119 + if (uint8 < 0 || uint8 > 0xff) {
  120 + throw new RuntimeException("Out of Boundary");
  121 + }
  122 + String hexString = Integer.toHexString(uint8);
  123 + byte low;
  124 + byte high;
  125 + if (hexString.length() > 1) {
  126 + high = (byte) Integer.parseInt(hexString.substring(0, 1), 16);
  127 + low = (byte) Integer.parseInt(hexString.substring(1, 2), 16);
  128 + } else {
  129 + high = 0;
  130 + low = (byte) Integer.parseInt(hexString.substring(0, 1), 16);
  131 + }
  132 + byte[] result = new byte[]{high, low};
  133 + return result;
  134 + }
  135 +
  136 + /**
  137 + * Combine 2 bytes (high byte and low byte) to one whole byte
  138 + *
  139 + * @param high the high byte
  140 + * @param low the low byte
  141 + * @return the whole byte
  142 + */
  143 + public static byte combine2bytesToOne(byte high, byte low) {
  144 + if (high < 0 || high > 0xf || low < 0 || low > 0xf) {
  145 + throw new RuntimeException("Out of Boundary");
  146 + }
  147 + return (byte) (high << 4 | low);
  148 + }
  149 +
  150 + /**
  151 + * Combine 2 bytes (high byte and low byte) to
  152 + *
  153 + * @param high the high byte
  154 + * @param low the low byte
  155 + * @return the char(u8)
  156 + */
  157 + public static char combine2bytesToU16(byte high, byte low) {
  158 + char highU8 = convertByte2Uint8(high);
  159 + char lowU8 = convertByte2Uint8(low);
  160 + return (char) (highU8 << 8 | lowU8);
  161 + }
  162 +
  163 + /**
  164 + * Generate the random byte to be sent
  165 + *
  166 + * @return the random byte
  167 + */
  168 + private static byte randomByte() {
  169 + return (byte) (127 - new Random().nextInt(256));
  170 + }
  171 +
  172 + /**
  173 + * Generate the random byte to be sent
  174 + *
  175 + * @param len the len presented by u8
  176 + * @return the byte[] to be sent
  177 + */
  178 + public static byte[] randomBytes(char len) {
  179 + byte[] data = new byte[len];
  180 + for (int i = 0; i < len; i++) {
  181 + data[i] = randomByte();
  182 + }
  183 + return data;
  184 + }
  185 +
  186 + public static byte[] genSpecBytes(char len) {
  187 + byte[] data = new byte[len];
  188 + for (int i = 0; i < len; i++) {
  189 + data[i] = '1';
  190 + }
  191 + return data;
  192 + }
  193 +
  194 + /**
  195 + * Generate the random byte to be sent
  196 + *
  197 + * @param len the len presented by byte
  198 + * @return the byte[] to be sent
  199 + */
  200 + public static byte[] randomBytes(byte len) {
  201 + char u8 = convertByte2Uint8(len);
  202 + return randomBytes(u8);
  203 + }
  204 +
  205 + /**
  206 + * Generate the specific byte to be sent
  207 + *
  208 + * @param len the len presented by byte
  209 + * @return the byte[]
  210 + */
  211 + public static byte[] genSpecBytes(byte len) {
  212 + char u8 = convertByte2Uint8(len);
  213 + return genSpecBytes(u8);
  214 + }
  215 +
  216 + public static String parseBssid(byte[] bssidBytes, int offset, int count) {
  217 + byte[] bytes = new byte[count];
  218 + for (int i = 0; i < count; i++) {
  219 + bytes[i] = bssidBytes[i + offset];
  220 + }
  221 + return parseBssid(bytes);
  222 + }
  223 +
  224 + /**
  225 + * parse "24,-2,52,-102,-93,-60" to "18,fe,34,9a,a3,c4"
  226 + * parse the bssid from hex to String
  227 + *
  228 + * @param bssidBytes the hex bytes bssid, e.g. {24,-2,52,-102,-93,-60}
  229 + * @return the String of bssid, e.g. 18fe349aa3c4
  230 + */
  231 + public static String parseBssid(byte[] bssidBytes) {
  232 + StringBuilder sb = new StringBuilder();
  233 + int k;
  234 + String hexK;
  235 + String str;
  236 + for (int i = 0; i < bssidBytes.length; i++) {
  237 + k = 0xff & bssidBytes[i];
  238 + hexK = Integer.toHexString(k);
  239 + str = ((k < 16) ? ("0" + hexK) : (hexK));
  240 + System.out.println(str);
  241 + sb.append(str);
  242 + }
  243 + return sb.toString();
  244 + }
  245 +
  246 + /**
  247 + * @param string the string to be used
  248 + * @return the byte[] of String according to {@link #ESPTOUCH_ENCODING_CHARSET}
  249 + */
  250 + public static byte[] getBytesByString(String string) {
  251 + try {
  252 + return string.getBytes(ESPTOUCH_ENCODING_CHARSET);
  253 + } catch (UnsupportedEncodingException e) {
  254 + throw new IllegalArgumentException("the charset is invalid");
  255 + }
  256 + }
  257 +
  258 + private static void test_splitUint8To2bytes() {
  259 + // 20 = 0x14
  260 + byte[] result = splitUint8To2bytes((char) 20);
  261 + if (result[0] == 1 && result[1] == 4) {
  262 + System.out.println("test_splitUint8To2bytes(): pass");
  263 + } else {
  264 + System.out.println("test_splitUint8To2bytes(): fail");
  265 + }
  266 + }
  267 +
  268 + private static void test_combine2bytesToOne() {
  269 + byte high = 0x01;
  270 + byte low = 0x04;
  271 + if (combine2bytesToOne(high, low) == 20) {
  272 + System.out.println("test_combine2bytesToOne(): pass");
  273 + } else {
  274 + System.out.println("test_combine2bytesToOne(): fail");
  275 + }
  276 + }
  277 +
  278 + private static void test_convertChar2Uint8() {
  279 + byte b1 = 'a';
  280 + // -128: 1000 0000 should be 128 in unsigned char
  281 + // -1: 1111 1111 should be 255 in unsigned char
  282 + byte b2 = (byte) -128;
  283 + byte b3 = (byte) -1;
  284 + if (convertByte2Uint8(b1) == 97 && convertByte2Uint8(b2) == 128 && convertByte2Uint8(b3) == 255) {
  285 + System.out.println("test_convertChar2Uint8(): pass");
  286 + } else {
  287 + System.out.println("test_convertChar2Uint8(): fail");
  288 + }
  289 + }
  290 +
  291 + private static void test_convertUint8toByte() {
  292 + char c1 = 'a';
  293 + // 128: 1000 0000 should be -128 in byte
  294 + // 255: 1111 1111 should be -1 in byte
  295 + char c2 = 128;
  296 + char c3 = 255;
  297 + if (convertUint8toByte(c1) == 97 && convertUint8toByte(c2) == -128 && convertUint8toByte(c3) == -1) {
  298 + System.out.println("test_convertUint8toByte(): pass");
  299 + } else {
  300 + System.out.println("test_convertUint8toByte(): fail");
  301 + }
  302 + }
  303 +
  304 + private static void test_parseBssid() {
  305 + byte b[] = {15, -2, 52, -102, -93, -60};
  306 + if (parseBssid(b).equals("0ffe349aa3c4")) {
  307 + System.out.println("test_parseBssid(): pass");
  308 + } else {
  309 + System.out.println("test_parseBssid(): fail");
  310 + }
  311 + }
  312 +
  313 + public static void main(String args[]) {
  314 + test_convertUint8toByte();
  315 + test_convertChar2Uint8();
  316 + test_splitUint8To2bytes();
  317 + test_combine2bytesToOne();
  318 + test_parseBssid();
  319 + }
  320 +
  321 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork.util;
  2 +
  3 +import java.util.zip.Checksum;
  4 +
  5 +public class CRC8 implements Checksum {
  6 +
  7 + private final short init;
  8 +
  9 + private static final short[] crcTable = new short[256];
  10 +
  11 + private short value;
  12 +
  13 + private static final short CRC_POLYNOM = 0x8c;
  14 +
  15 + private static final short CRC_INITIAL = 0x00;
  16 +
  17 + static {
  18 + for (int dividend = 0; dividend < 256; dividend++) {
  19 + int remainder = dividend;// << 8;
  20 + for (int bit = 0; bit < 8; ++bit)
  21 + if ((remainder & 0x01) != 0)
  22 + remainder = (remainder >>> 1) ^ CRC_POLYNOM;
  23 + else
  24 + remainder >>>= 1;
  25 + crcTable[dividend] = (short) remainder;
  26 + }
  27 + }
  28 +
  29 + public CRC8() {
  30 + this.value = this.init = CRC_INITIAL;
  31 + }
  32 +
  33 + @Override
  34 + public void update(byte[] buffer, int offset, int len) {
  35 + for (int i = 0; i < len; i++) {
  36 + int data = buffer[offset + i] ^ value;
  37 + value = (short) (crcTable[data & 0xff] ^ (value << 8));
  38 + }
  39 + }
  40 +
  41 + /**
  42 + * Updates the current checksum with the specified array of bytes.
  43 + * Equivalent to calling <code>update(buffer, 0, buffer.length)</code>.
  44 + *
  45 + * @param buffer the byte array to update the checksum with
  46 + */
  47 + public void update(byte[] buffer) {
  48 + update(buffer, 0, buffer.length);
  49 + }
  50 +
  51 + @Override
  52 + public void update(int b) {
  53 + update(new byte[]{(byte) b}, 0, 1);
  54 + }
  55 +
  56 + @Override
  57 + public long getValue() {
  58 + return value & 0xff;
  59 + }
  60 +
  61 + @Override
  62 + public void reset() {
  63 + value = init;
  64 + }
  65 +
  66 +}
... ...
  1 +package com.xgimi.smartscreen.confignetwork.util;
  2 +
  3 +import android.content.Context;
  4 +import android.net.ConnectivityManager;
  5 +import android.net.NetworkInfo;
  6 +import android.net.wifi.WifiInfo;
  7 +import android.net.wifi.WifiManager;
  8 +
  9 +import java.net.InetAddress;
  10 +import java.net.UnknownHostException;
  11 +
  12 +public class NetUtil {
  13 +
  14 + /**
  15 + * 判断网络是否连接
  16 + *
  17 + * @param context
  18 + * @return
  19 + */
  20 + public static boolean isConnected(Context context) {
  21 +
  22 + ConnectivityManager connectivity = (ConnectivityManager) context
  23 + .getSystemService(Context.CONNECTIVITY_SERVICE);
  24 +
  25 + if (null != connectivity) {
  26 +
  27 + NetworkInfo info = connectivity.getActiveNetworkInfo();
  28 + if (null != info && info.isConnected()) {
  29 + if (info.getState() == NetworkInfo.State.CONNECTED) {
  30 + return true;
  31 + }
  32 + }
  33 + }
  34 + return false;
  35 + }
  36 +
  37 + /**
  38 + * 判断是否是wifi连接
  39 + */
  40 + public static boolean isWifi(Context context) {
  41 + ConnectivityManager cm = (ConnectivityManager) context
  42 + .getSystemService(Context.CONNECTIVITY_SERVICE);
  43 +
  44 + if (cm == null)
  45 + return false;
  46 + return cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI;
  47 + }
  48 +
  49 + /**
  50 + * get the local ip address by Android System
  51 + *
  52 + * @param context the context
  53 + * @return the local ip addr allocated by Ap
  54 + */
  55 + public static InetAddress getLocalInetAddress(Context context) {
  56 + WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
  57 + WifiInfo wifiInfo = wm.getConnectionInfo();
  58 + int localAddrInt = wifiInfo.getIpAddress();
  59 + String localAddrStr = __formatString(localAddrInt);
  60 + InetAddress localInetAddr = null;
  61 + try {
  62 + localInetAddr = InetAddress.getByName(localAddrStr);
  63 + } catch (UnknownHostException e) {
  64 + e.printStackTrace();
  65 + }
  66 + return localInetAddr;
  67 + }
  68 +
  69 + private static String __formatString(int value) {
  70 + String strValue = "";
  71 + byte[] ary = __intToByteArray(value);
  72 + for (int i = ary.length - 1; i >= 0; i--) {
  73 + strValue += (ary[i] & 0xFF);
  74 + if (i > 0) {
  75 + strValue += ".";
  76 + }
  77 + }
  78 + return strValue;
  79 + }
  80 +
  81 + private static byte[] __intToByteArray(int value) {
  82 + byte[] b = new byte[4];
  83 + for (int i = 0; i < 4; i++) {
  84 + int offset = (b.length - 1 - i) * 8;
  85 + b[i] = (byte) ((value >>> offset) & 0xFF);
  86 + }
  87 + return b;
  88 + }
  89 +
  90 + /**
  91 + * parse InetAddress
  92 + *
  93 + * @param inetAddrBytes
  94 + * @return
  95 + */
  96 + public static InetAddress parseInetAddr(byte[] inetAddrBytes, int offset, int count) {
  97 + InetAddress inetAddress = null;
  98 + StringBuilder sb = new StringBuilder();
  99 + for (int i = 0; i < count; i++) {
  100 + sb.append(Integer.toString(inetAddrBytes[offset + i] & 0xff));
  101 + if (i != count - 1) {
  102 + sb.append('.');
  103 + }
  104 + }
  105 + try {
  106 + inetAddress = InetAddress.getByName(sb.toString());
  107 + } catch (UnknownHostException e) {
  108 + e.printStackTrace();
  109 + }
  110 + return inetAddress;
  111 + }
  112 +
  113 + /**
  114 + * parse bssid
  115 + *
  116 + * @param bssid the bssid
  117 + * @return byte converted from bssid
  118 + */
  119 + public static byte[] parseBssid2bytes(String bssid) {
  120 + String bssidSplits[] = bssid.split(":");
  121 + byte[] result = new byte[bssidSplits.length];
  122 + for (int i = 0; i < bssidSplits.length; i++) {
  123 + result[i] = (byte) Integer.parseInt(bssidSplits[i], 16);
  124 + }
  125 + return result;
  126 + }
  127 +}
... ...
  1 +package com.xgimi.smartscreen.service;
  2 +
  3 +import android.app.Service;
  4 +import android.content.BroadcastReceiver;
  5 +import android.content.Context;
  6 +import android.content.Intent;
  7 +import android.content.IntentFilter;
  8 +import android.net.ConnectivityManager;
  9 +import android.os.AsyncTask;
  10 +import android.os.Handler;
  11 +import android.os.IBinder;
  12 +import android.os.Message;
  13 +import android.text.TextUtils;
  14 +import android.util.Log;
  15 +import android.widget.Toast;
  16 +import com.gimi.common.cinema.model.MessageEvent;
  17 +import com.google.gson.Gson;
  18 +import com.xgimi.smartscreen.SmartScreenBean;
  19 +import com.xgimi.smartscreen.confignetwork.ChTask;
  20 +import com.xgimi.smartscreen.confignetwork.IChListener;
  21 +import com.xgimi.smartscreen.confignetwork.IChResult;
  22 +import com.xgimi.smartscreen.confignetwork.IChTask;
  23 +import com.xgimi.smartscreen.confignetwork.task.__IChTask;
  24 +import com.xgimi.smartscreen.confignetwork.util.NetUtil;
  25 +import org.greenrobot.eventbus.EventBus;
  26 +import org.greenrobot.eventbus.Subscribe;
  27 +import org.greenrobot.eventbus.ThreadMode;
  28 +import org.json.JSONException;
  29 +import org.json.JSONObject;
  30 +
  31 +import java.io.BufferedReader;
  32 +import java.io.IOException;
  33 +import java.io.InputStreamReader;
  34 +import java.io.PrintWriter;
  35 +import java.net.DatagramPacket;
  36 +import java.net.DatagramSocket;
  37 +import java.net.InetAddress;
  38 +import java.net.Socket;
  39 +import java.net.SocketException;
  40 +import java.net.SocketTimeoutException;
  41 +import java.net.UnknownHostException;
  42 +import java.util.List;
  43 +import java.util.Timer;
  44 +import java.util.TimerTask;
  45 +
  46 +/**
  47 + * Created by Administrator on 2016/7/26.
  48 + */
  49 +public class ConfigService extends Service {
  50 +
  51 + private String TAG = "ConfigService";
  52 + private WifiAdminSimple mWifiAdmin;
  53 + private String mDeviceIp;
  54 + private int configStat = 0;
  55 + private Timer firstTimer;
  56 + private long waitTime;
  57 + private int findWifiInfoCount = 0;
  58 + private boolean hasTask = false;
  59 + SmartScreenBean smartScreen;
  60 +
  61 + private int state;
  62 + MessageThread messageThread;
  63 +
  64 + @Override
  65 + public IBinder onBind(Intent intent) {
  66 + return null;
  67 + }
  68 +
  69 + @Override
  70 + public void onCreate() {
  71 + super.onCreate();
  72 + Log.d(TAG, "onCreate");
  73 + EventBus.getDefault().register(this);
  74 +
  75 + configStat = 0;
  76 + IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
  77 + registerReceiver(netStateChange, filter);
  78 + }
  79 +
  80 + @Override
  81 + public int onStartCommand(Intent intent, int flags, int startId) {
  82 + Log.d(TAG, "onStartCommand");
  83 + if (intent == null)
  84 + return super.onStartCommand(intent, flags, startId);
  85 + if (intent.getIntExtra("boot", 0) == 1) {
  86 + waitTime = System.currentTimeMillis();
  87 + firstTimer = new Timer();
  88 + firstTimer.scheduleAtFixedRate(new TimerTask() {
  89 + @Override
  90 + public void run() {
  91 + Log.e(TAG, "count time....");
  92 + if (System.currentTimeMillis() - waitTime > 2 * 60 * 1000) {
  93 + hasTask = false;
  94 + firstTimer.cancel();
  95 + firstTimer = null;
  96 + }
  97 + }
  98 + }, 0, 1000);
  99 + state = SmartScreenBean.DOWNACTION;
  100 + hasTask = true;
  101 + getNetStat();
  102 + }
  103 +
  104 + String action = intent.getAction();
  105 + if ("com.xgimi.smartscreen.ACTION.CONTROL".equals(action)) {
  106 + state = intent.getIntExtra("CONTROL", -1);
  107 + String ip = intent.getStringExtra("CONTROLIP");
  108 + if (state >= 0) {
  109 + Control(ip, state);
  110 + }
  111 + } else if ("com.xgimi.smartscreen.ACTION.SEARCH".equals(action)) {
  112 + new SearchAsyncTask().execute();
  113 + } else if ("com.xgimi.smartscreen.ACTION.BIND".equals(action)) {
  114 + String bindInfo = intent.getStringExtra("BINDINFO");
  115 + XgimiSettingsSP.putString(ConfigService.this, "BINDINFO", bindInfo);
  116 + Intent notifyIntent = new Intent("com.xgimi.smartscreen.ACTION.DEVICEBIND");
  117 + sendBroadcast(notifyIntent);
  118 + }/*else if("com.xgimi.smartscreen.ACTION.POWEROFF".equals(action)){
  119 + state = SmartScreenBean.UPACTION;
  120 + hasTask = true;
  121 + String bindInfo = XgimiSettingsSP.getString(ConfigService.this,"BINDINFO");
  122 + if(!StringUtils.isEmpty(bindInfo)){
  123 + Gson gson = new Gson();
  124 + try {
  125 + smartScreen = gson.fromJson(bindInfo,SmartScreenBean.class);
  126 + if(smartScreen!=null&&!StringUtils.isEmpty(smartScreen.ip)){
  127 + handler.sendEmptyMessage(999);
  128 + handler.sendEmptyMessageDelayed(999,300);
  129 + handler.sendEmptyMessageDelayed(999,600);
  130 + handler.sendEmptyMessageDelayed(999,900);
  131 + }
  132 + }catch (Exception e){
  133 + e.printStackTrace();
  134 + }
  135 + }
  136 + }*/
  137 + return super.onStartCommand(intent, flags, startId);
  138 + }
  139 +
  140 + private void Control(String ip, int stat) {
  141 + if (messageThread == null)
  142 + messageThread = new MessageThread();
  143 + messageThread.setIp(ip);
  144 + messageThread.setMode(stat);
  145 + new Thread(messageThread).start();
  146 + }
  147 +
  148 + public class MessageThread implements Runnable {
  149 + final int PORT = 8009;
  150 + String cmd, ip;
  151 +
  152 + public void setIp(String ip) {
  153 + this.ip = ip;
  154 + }
  155 +
  156 + public void setMode(int mode) {
  157 + JSONObject dataUp = new JSONObject();
  158 + try {
  159 + dataUp.put("cmd", 2);
  160 + dataUp.put("action", mode);
  161 + cmd = dataUp.toString();
  162 + } catch (JSONException e) {
  163 + e.printStackTrace();
  164 + cmd = null;
  165 + }
  166 + }
  167 +
  168 + @Override
  169 + public void run() {
  170 + if (TextUtils.isEmpty(cmd)) {
  171 + return;
  172 + }
  173 + BufferedReader br = null;
  174 + PrintWriter pw = null;
  175 + Socket socket = null;
  176 + try {
  177 + socket = new Socket(ip, PORT);
  178 + socket.setSoTimeout(1000);
  179 + br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  180 + pw = new PrintWriter(socket.getOutputStream());
  181 + pw.write(cmd);
  182 + pw.flush();
  183 + String data = null;
  184 + while ((data = br.readLine()) != null) {
  185 + Log.i(TAG, "接收到的数据:" + data);
  186 + Message msg = new Message();
  187 + msg.what = 0x123;
  188 + msg.obj = data;
  189 + handler.sendMessage(msg);
  190 + }
  191 + } catch (SocketTimeoutException e) {
  192 + Log.i(TAG, "网络连接超时!");
  193 + } catch (IOException e) {
  194 + e.printStackTrace();
  195 + } finally {
  196 + try {
  197 + if (pw != null) {
  198 + pw.close();
  199 + }
  200 + if (br != null) {
  201 + br.close();
  202 + }
  203 + if (socket != null) {
  204 + socket.close();
  205 + }
  206 + } catch (IOException e) {
  207 + e.printStackTrace();
  208 + }
  209 + }
  210 + }
  211 + }
  212 +
  213 + Handler handler = new Handler() {
  214 + @Override
  215 + public void handleMessage(Message msg) {
  216 + super.handleMessage(msg);
  217 + if (msg.what == 998) {
  218 + Toast.makeText(ConfigService.this, "recv ", Toast.LENGTH_SHORT).show();
  219 + } else if (msg.what == 999) {
  220 + Log.e(TAG, "shut down !!!");
  221 + Control(smartScreen.ip, state);
  222 + } else if (msg.what == 1000) {
  223 + WifiInfo wifiInfo = (WifiInfo) msg.obj;
  224 + startConfig(wifiInfo.Ssid, wifiInfo.Password);
  225 + } else if (msg.what == 0x123) {
  226 + String data = (msg.obj).toString();
  227 + try {
  228 + JSONObject jsonObject = new JSONObject(data);
  229 + int cmd = jsonObject.getInt("cmd");
  230 + if (cmd == 2) {
  231 + int result = jsonObject.getInt("result");
  232 + if (result == 1) { //成功
  233 + Log.e(TAG, "操作成功");
  234 + } else if (result == 0) { //失败
  235 + Log.e(TAG, "操作失败");
  236 + }
  237 + }
  238 + } catch (JSONException e) {
  239 + e.printStackTrace();
  240 + }
  241 + }
  242 + }
  243 + };
  244 +
  245 + private void getNetStat() {
  246 + Log.d(TAG, "getNetStat");
  247 + int stat = XgimiSettingsSP.getInt(ConfigService.this, "AUTOSCREEN");
  248 + if (stat == 0) {
  249 + return;
  250 + }
  251 + if (NetUtil.isConnected(ConfigService.this)) {
  252 + Log.e(TAG, "SearchAsyncTask");
  253 + new SearchAsyncTask().execute();
  254 + }
  255 + }
  256 +
  257 + private BroadcastReceiver netStateChange = new BroadcastReceiver() {
  258 + @Override
  259 + public void onReceive(Context context, Intent intent) {
  260 + if (intent == null) {
  261 + return;
  262 + }
  263 + String action = intent.getAction();
  264 + if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
  265 + Log.d(TAG, "网络状态已经改变");
  266 + if (NetUtil.isConnected(ConfigService.this)) {
  267 + new SearchAsyncTask().execute();
  268 + }
  269 + }
  270 + }
  271 + };
  272 +
  273 + private void findWifiInfo() {
  274 + findWifiInfoCount++;
  275 + Log.d(TAG, "findWifiInfo" + findWifiInfoCount);
  276 + if (mWifiAdmin == null) {
  277 + mWifiAdmin = new WifiAdminSimple(this);
  278 + }
  279 + String apSsid = mWifiAdmin.getWifiConnectedSsid();
  280 + if (TextUtils.isEmpty(apSsid)) {
  281 + return;
  282 + }
  283 + }
  284 +
  285 + private void startConfig(String apSsid, String apPassword) {
  286 + Log.d(TAG, "startConfig");
  287 + String apBssid = mWifiAdmin.getWifiConnectedBssid();
  288 + String isSsidHiddenStr = "YES";
  289 + int[] tastResultCount = {0, 1, 2, 3, 4, 5};
  290 + String taskResultCountStr = Integer.toString(tastResultCount[1]); //设置任务的数量为1个
  291 + if (__IChTask.DEBUG) {
  292 + Log.d(TAG, "mBtnConfig is clicked, mEdtApSsid = " + apSsid + ", " + " mEdtApPassword = " + apPassword);
  293 + }
  294 + new AsyncTask3().execute(apSsid, apBssid, apPassword, isSsidHiddenStr, taskResultCountStr);
  295 + }
  296 +
  297 + private void onChResultAddedPerform(final IChResult result) {
  298 + String text = result.getBssid() + " 已连接到wifi";
  299 + Log.e(TAG, "onChResultAddedPerform:" + text);
  300 + }
  301 +
  302 + private IChListener myListener = new IChListener() {
  303 +
  304 + @Override
  305 + public void onChResultAdded(final IChResult result) {
  306 + onChResultAddedPerform(result);
  307 + }
  308 + };
  309 +
  310 + private class AsyncTask3 extends AsyncTask<String, Void, List<IChResult>> {
  311 +
  312 + private IChTask mChTask;
  313 + // without the lock, if the user tap confirm and cancel quickly enough,
  314 + // the bug will arise. the reason is follows:
  315 + // 0. task is starting created, but not finished
  316 + // 1. the task is cancel for the task hasn't been created, it do nothing
  317 + // 2. task is created
  318 + // 3. Oops, the task should be cancelled, but it is running
  319 + private final Object mLock = new Object();
  320 +
  321 + @Override
  322 + protected List<IChResult> doInBackground(String... params) {
  323 + int taskResultCount = -1;
  324 + synchronized (mLock) {
  325 + String apSsid = params[0];
  326 + String apBssid = params[1];
  327 + String apPassword = params[2];
  328 + String isSsidHiddenStr = params[3];
  329 + String taskResultCountStr = params[4];
  330 + boolean isSsidHidden = false;
  331 + if (isSsidHiddenStr.equals("YES")) {
  332 + isSsidHidden = true;
  333 + }
  334 + taskResultCount = Integer.parseInt(taskResultCountStr);
  335 + mChTask = new ChTask(apSsid, apBssid, apPassword, isSsidHidden, ConfigService.this);
  336 + mChTask.setChListener(myListener);
  337 + }
  338 + List<IChResult> resultList = mChTask.executeForResults(taskResultCount);
  339 + return resultList;
  340 + }
  341 +
  342 + @Override
  343 + protected void onPostExecute(List<IChResult> result) {
  344 + IChResult firstResult = result.get(0);
  345 + // check whether the task is cancelled and no results received
  346 + Log.e(TAG, "onPostExecute IChResult");
  347 + if (!firstResult.isCancelled()) {
  348 + int count = 0;
  349 + // max results to be displayed, if it is more than maxDisplayCount,
  350 + // just show the count of redundant ones
  351 + final int maxDisplayCount = 5;
  352 + // the task received some results including cancelled while
  353 + // executing before receiving enough results
  354 + String ip = "";
  355 + if (firstResult.isSuc()) {
  356 + StringBuilder sb = new StringBuilder();
  357 + for (IChResult resultInList : result) {
  358 + sb.append("配置成功" + "\n" + "BSSID = " + resultInList.getBssid() + "\n" + "InetAddress = " + resultInList.getInetAddress().getHostAddress());
  359 + ip = resultInList.getInetAddress().getHostAddress();
  360 + count++;
  361 + if (count >= maxDisplayCount) {
  362 + break;
  363 + }
  364 + }
  365 + if (count < result.size()) {
  366 + sb.append("\n有 " + (result.size() - count) + " 个结果未显示\n");
  367 + }
  368 + Log.e(TAG, "test:start SearchAsyncTask;" + sb.toString());
  369 + if (hasTask)
  370 + Control(ip, state);
  371 + } else {
  372 + Log.e(TAG, "onPostExecute isSuc = false");
  373 + }
  374 + } else {
  375 + Log.e(TAG, "onPostExecute isCancelled");
  376 + }
  377 + }
  378 + }
  379 +
  380 + private class SearchAsyncTask extends AsyncTask<Void, Integer, String> {
  381 + InetAddress deviceAddress = null;
  382 + DatagramSocket socket = null;
  383 + boolean isSearching = false;
  384 +
  385 + @Override
  386 + protected String doInBackground(Void... params) {
  387 + isSearching = true;
  388 + try {
  389 + socket = new DatagramSocket();
  390 + } catch (SocketException e) {
  391 + e.printStackTrace();
  392 + }
  393 + //接收
  394 + Thread receiveThread = new Thread(new Runnable() {
  395 + @Override
  396 + public void run() {
  397 +
  398 + byte[] dataReceive = new byte[1024];
  399 + DatagramPacket packetReceive = new DatagramPacket(dataReceive, dataReceive.length);
  400 +
  401 + try {
  402 + socket.receive(packetReceive);
  403 + String reply = new String(dataReceive, 0, packetReceive.getLength());
  404 + if (reply.contains("I'm a screen Controller")) {
  405 + isSearching = false;
  406 + deviceAddress = packetReceive.getAddress();
  407 + }
  408 + } catch (IOException e) {
  409 + e.printStackTrace();
  410 + Log.i(TAG, "receive...cnt" + e.toString());
  411 + }
  412 + }
  413 +
  414 + });
  415 + receiveThread.start();
  416 + int cnt = 3; //搜索次数
  417 +
  418 + while (isSearching) {
  419 + Log.i(TAG, "开始搜索...cnt" + cnt);
  420 + if (--cnt == 0) {
  421 + break;
  422 + }
  423 + //发送
  424 + String data = "Are You Screen Controller?";
  425 + DatagramPacket packetSend = null;
  426 + try {
  427 + packetSend = new DatagramPacket(data.getBytes(), data.getBytes().length,
  428 + InetAddress.getByName("255.255.255.255"), 12419);
  429 + } catch (UnknownHostException e) {
  430 + e.printStackTrace();
  431 + }
  432 +
  433 + try {
  434 + socket.send(packetSend);
  435 + } catch (IOException e) {
  436 + e.printStackTrace();
  437 + Log.e(TAG, "send IOException" + e.toString());
  438 + }
  439 +
  440 + try {
  441 + Thread.sleep(500);
  442 + } catch (InterruptedException e) {
  443 + e.printStackTrace();
  444 + Log.e(TAG, "sleep InterruptedException" + e.toString());
  445 + }
  446 + }
  447 + receiveThread.interrupt();
  448 + if (deviceAddress != null) {
  449 + return deviceAddress.toString().substring(1); //去除ip地址前的斜杠
  450 + } else {
  451 + return null;
  452 + }
  453 + }
  454 +
  455 + @Override
  456 + protected void onPostExecute(String s) {
  457 + super.onPostExecute(s);
  458 + Log.e(TAG, "ip:" + s);
  459 + if (!TextUtils.isEmpty(s)) {
  460 + SmartScreenBean smartScreenBean = new SmartScreenBean();
  461 + smartScreenBean.ip = s;
  462 + smartScreenBean.name = "极米智能幕布";
  463 + smartScreenBean.state = 0;
  464 + String bindInfo = new Gson().toJson(smartScreenBean, SmartScreenBean.class);
  465 + XgimiSettingsSP.putString(ConfigService.this, "BINDINFO", bindInfo);
  466 + Intent notifyIntent = new Intent("com.xgimi.smartscreen.ACTION.DEVICEBIND");
  467 + sendBroadcast(notifyIntent);
  468 + if (hasTask) {
  469 + Control(s, state);
  470 + hasTask = false;
  471 + }
  472 + } else {
  473 + Log.e(TAG, "没有发现设备!");
  474 + XgimiSettingsSP.putString(ConfigService.this, "BINDINFO", "");
  475 + Intent notifyIntent = new Intent("com.xgimi.smartscreen.ACTION.NODEVICE");
  476 + sendBroadcast(notifyIntent);
  477 + }
  478 + }
  479 + }
  480 +
  481 +
  482 + @Override
  483 + public void onDestroy() {
  484 + Log.e(TAG, "onDestroy");
  485 + EventBus.getDefault().unregister(this);
  486 + if (firstTimer != null) {
  487 + firstTimer.cancel();
  488 + firstTimer = null;
  489 + }
  490 + unregisterReceiver(netStateChange);
  491 + handler.removeCallbacksAndMessages(null);
  492 + super.onDestroy();
  493 + }
  494 +
  495 +
  496 + @Subscribe(threadMode = ThreadMode.MAIN)
  497 + public void onMoonEvent(MessageEvent messageEvent) {
  498 + switch (messageEvent.getEventId()) {
  499 + case SmartScreenBean.UPACTION:
  500 + Log.d(TAG, "SmartScreenBean.UPACTION");
  501 + Control(messageEvent.getMessage(), messageEvent.getEventId());
  502 + break;
  503 + case SmartScreenBean.DOWNACTION:
  504 + Log.d(TAG, "SmartScreenBean.DOWNACTION");
  505 + Control(messageEvent.getMessage(), messageEvent.getEventId());
  506 + break;
  507 + case SmartScreenBean.STOPACTION:
  508 + Log.d(TAG, "SmartScreenBean.STOPACTION");
  509 + Control(messageEvent.getMessage(), messageEvent.getEventId());
  510 + break;
  511 + }
  512 + }
  513 +}
... ...
  1 +package com.xgimi.smartscreen.service;
  2 +
  3 +import android.content.Context;
  4 +import android.net.ConnectivityManager;
  5 +import android.net.NetworkInfo;
  6 +import android.net.wifi.WifiInfo;
  7 +import android.net.wifi.WifiManager;
  8 +
  9 +public class WifiAdminSimple {
  10 +
  11 + private final Context mContext;
  12 +
  13 + public WifiAdminSimple(Context context) {
  14 + mContext = context;
  15 + }
  16 +
  17 + public String getWifiConnectedSsid() {
  18 + WifiInfo mWifiInfo = getConnectionInfo();
  19 + String ssid = null;
  20 + if (mWifiInfo != null && isWifiConnected()) {
  21 + int len = mWifiInfo.getSSID().length();
  22 + if (mWifiInfo.getSSID().startsWith("\"") && mWifiInfo.getSSID().endsWith("\"")) {
  23 + ssid = mWifiInfo.getSSID().substring(1, len - 1);
  24 + } else {
  25 + ssid = mWifiInfo.getSSID();
  26 + }
  27 +
  28 + }
  29 + return ssid;
  30 + }
  31 +
  32 + public String getWifiConnectedBssid() {
  33 + WifiInfo mWifiInfo = getConnectionInfo();
  34 + String bssid = null;
  35 + if (mWifiInfo != null && isWifiConnected()) {
  36 + bssid = mWifiInfo.getBSSID();
  37 + }
  38 + return bssid;
  39 + }
  40 +
  41 + // get the wifi info which is "connected" in wifi-setting
  42 + private WifiInfo getConnectionInfo() {
  43 + WifiManager mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
  44 + WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
  45 + return wifiInfo;
  46 + }
  47 +
  48 + private boolean isWifiConnected() {
  49 + NetworkInfo mWiFiNetworkInfo = getWifiNetworkInfo();
  50 + boolean isWifiConnected = false;
  51 + if (mWiFiNetworkInfo != null) {
  52 + isWifiConnected = mWiFiNetworkInfo.isConnected();
  53 + }
  54 + return isWifiConnected;
  55 + }
  56 +
  57 + private NetworkInfo getWifiNetworkInfo() {
  58 + ConnectivityManager mConnectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
  59 + NetworkInfo mWiFiNetworkInfo = mConnectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
  60 + return mWiFiNetworkInfo;
  61 + }
  62 +}
... ...
  1 +package com.xgimi.smartscreen.service;
  2 +
  3 +/**
  4 + * Created by Administrator on 2016/7/26.
  5 + */
  6 +public class WifiInfo {
  7 + public String Ssid="";
  8 + public String Password="";
  9 +}
... ...
  1 +package com.xgimi.smartscreen.service;
  2 +
  3 +/**
  4 + * Created by Administrator on 2016/7/26.
  5 + */
  6 +
  7 +import android.util.Log;
  8 +
  9 +import java.io.BufferedReader;
  10 +import java.io.DataInputStream;
  11 +import java.io.DataOutputStream;
  12 +import java.io.InputStreamReader;
  13 +import java.util.ArrayList;
  14 +import java.util.List;
  15 +import java.util.regex.Matcher;
  16 +import java.util.regex.Pattern;
  17 +
  18 +public class WifiManage {
  19 +
  20 + public List<WifiInfo> Read() throws Exception {
  21 + List<WifiInfo> wifiInfos=new ArrayList<WifiInfo>();
  22 +
  23 + Process process = null;
  24 + DataOutputStream dataOutputStream = null;
  25 + DataInputStream dataInputStream = null;
  26 + StringBuffer wifiConf = new StringBuffer();
  27 + try {
  28 + process = Runtime.getRuntime().exec("sh");
  29 + dataOutputStream = new DataOutputStream(process.getOutputStream());
  30 + dataInputStream = new DataInputStream(process.getInputStream());
  31 + dataOutputStream
  32 + .writeBytes("cat /system/etc/wifiinfo/wpa_supplicant.conf\n");
  33 + dataOutputStream.writeBytes("exit\n");
  34 + dataOutputStream.flush();
  35 + InputStreamReader inputStreamReader = new InputStreamReader(
  36 + dataInputStream, "UTF-8");
  37 + BufferedReader bufferedReader = new BufferedReader(
  38 + inputStreamReader);
  39 + String line = null;
  40 + while ((line = bufferedReader.readLine()) != null) {
  41 + wifiConf.append(line);
  42 + Log.e("TAG","line"+line);
  43 + }
  44 + bufferedReader.close();
  45 + inputStreamReader.close();
  46 + process.waitFor();
  47 + } catch (Exception e) {
  48 + throw e;
  49 + } finally {
  50 + try {
  51 + if (dataOutputStream != null) {
  52 + dataOutputStream.close();
  53 + }
  54 + if (dataInputStream != null) {
  55 + dataInputStream.close();
  56 + }
  57 + if(process!=null)
  58 + process.destroy();
  59 + } catch (Exception e) {
  60 + throw e;
  61 + }
  62 + }
  63 +
  64 +
  65 + Pattern network = Pattern.compile("network=\\{([^\\}]+)\\}", Pattern.DOTALL);
  66 + Matcher networkMatcher = network.matcher(wifiConf.toString() );
  67 + while (networkMatcher.find() ) {
  68 + String networkBlock = networkMatcher.group();
  69 + Pattern ssid = Pattern.compile("ssid=\"([^\"]+)\"");
  70 + Matcher ssidMatcher = ssid.matcher(networkBlock);
  71 +
  72 + if (ssidMatcher.find() ) {
  73 + WifiInfo wifiInfo=new WifiInfo();
  74 + wifiInfo.Ssid=ssidMatcher.group(1);
  75 + Pattern psk = Pattern.compile("psk=\"([^\"]+)\"");
  76 + Matcher pskMatcher = psk.matcher(networkBlock);
  77 + if (pskMatcher.find() ) {
  78 + wifiInfo.Password=pskMatcher.group(1);
  79 + } else {
  80 + wifiInfo.Password="无密码";
  81 + }
  82 + wifiInfos.add(wifiInfo);
  83 + }
  84 +
  85 + }
  86 +
  87 + return wifiInfos;
  88 + }
  89 +
  90 +}
... ...
  1 +package com.xgimi.smartscreen.service;
  2 +
  3 +import android.content.Context;
  4 +import android.content.SharedPreferences;
  5 +
  6 +public class XgimiSettingsSP {
  7 +
  8 + private static final String PREFERENCE_NAME = "local_settings"; //sp名字
  9 +
  10 + private static final String PKG_NAME = "com.android.settings"; //设置包名
  11 +
  12 + public static final String ID_USER_NAME = "xgimi_out_username";
  13 +
  14 +
  15 + /**
  16 + * put string preferences
  17 + *
  18 + * @param context
  19 + * @param key The name of the preference to modify
  20 + * @param value The new value for the preference
  21 + * @return True if the new values were successfully written to persistent
  22 + * storage.
  23 + */
  24 + public static boolean putString(Context context, String key, String value) {
  25 + try {
  26 + Context otherAppsContext = context.createPackageContext(PKG_NAME, Context.CONTEXT_IGNORE_SECURITY);
  27 + SharedPreferences settings = otherAppsContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_WORLD_WRITEABLE | Context.MODE_MULTI_PROCESS);
  28 + SharedPreferences.Editor editor = settings.edit();
  29 + editor.putString(key, value);
  30 + return editor.commit();
  31 + } catch (Exception e) {
  32 +
  33 + }
  34 + return false;
  35 + }
  36 +
  37 + /**
  38 + * get string preferences
  39 + *
  40 + * @param context
  41 + * @param key The name of the preference to retrieve
  42 + * @return The preference value if it exists, or null. Throws
  43 + * ClassCastException if there is a preference with this name that
  44 + * is not a string
  45 + * @see #getString(Context, String, String)
  46 + */
  47 + public static String getString(Context context, String key) {
  48 + return getString(context, key, "");
  49 + }
  50 +
  51 + /**
  52 + * get string preferences
  53 + *
  54 + * @param context
  55 + * @param key The name of the preference to retrieve
  56 + * @param defaultValue Value to return if this preference does not exist
  57 + * @return The preference value if it exists, or defValue. Throws
  58 + * ClassCastException if there is a preference with this name that
  59 + * is not a string
  60 + */
  61 + public static String getString(Context context, String key, String defaultValue) {
  62 + try {
  63 + Context otherAppsContext = context.createPackageContext(PKG_NAME, Context.CONTEXT_IGNORE_SECURITY);
  64 + SharedPreferences share = otherAppsContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_WORLD_READABLE | Context.MODE_MULTI_PROCESS);
  65 + return share.getString(key, defaultValue);
  66 + } catch (Exception e) {
  67 +
  68 + }
  69 + return defaultValue;
  70 + }
  71 +
  72 + /**
  73 + * put int preferences
  74 + *
  75 + * @param context
  76 + * @param key The name of the preference to modify
  77 + * @param value The new value for the preference
  78 + * @return True if the new values were successfully written to persistent
  79 + * storage.
  80 + */
  81 + public static boolean putInt(Context context, String key, int value) {
  82 + try {
  83 + Context otherAppsContext = context.createPackageContext(PKG_NAME, Context.CONTEXT_IGNORE_SECURITY);
  84 + SharedPreferences settings = otherAppsContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_WORLD_WRITEABLE | Context.MODE_MULTI_PROCESS);
  85 + SharedPreferences.Editor editor = settings.edit();
  86 + editor.putInt(key, value);
  87 + return editor.commit();
  88 + } catch (Exception e) {
  89 +
  90 + }
  91 + return false;
  92 + }
  93 +
  94 + /**
  95 + * get int preferences
  96 + *
  97 + * @param context
  98 + * @param key The name of the preference to retrieve
  99 + * @return The preference value if it exists, or -1. Throws
  100 + * ClassCastException if there is a preference with this name that
  101 + * is not a int
  102 + * @see #getInt(Context, String, int)
  103 + */
  104 + public static int getInt(Context context, String key) {
  105 + return getInt(context, key, -1);
  106 + }
  107 +
  108 + /**
  109 + * get int preferences
  110 + *
  111 + * @param context
  112 + * @param key The name of the preference to retrieve
  113 + * @param defaultValue Value to return if this preference does not exist
  114 + * @return The preference value if it exists, or defValue. Throws
  115 + * ClassCastException if there is a preference with this name that
  116 + * is not a int
  117 + */
  118 + public static int getInt(Context context, String key, int defaultValue) {
  119 + try {
  120 + Context otherAppsContext = context.createPackageContext(PKG_NAME, Context.CONTEXT_IGNORE_SECURITY);
  121 + SharedPreferences share = otherAppsContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_WORLD_READABLE | Context.MODE_MULTI_PROCESS);
  122 + return share.getInt(key, defaultValue);
  123 + } catch (Exception e) {
  124 +
  125 + }
  126 + return defaultValue;
  127 + }
  128 +
  129 + /**
  130 + * put long preferences
  131 + *
  132 + * @param context
  133 + * @param key The name of the preference to modify
  134 + * @param value The new value for the preference
  135 + * @return True if the new values were successfully written to persistent
  136 + * storage.
  137 + */
  138 + public static boolean putLong(Context context, String key, long value) {
  139 + try {
  140 + Context otherAppsContext = context.createPackageContext(PKG_NAME, Context.CONTEXT_IGNORE_SECURITY);
  141 + SharedPreferences settings = otherAppsContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_WORLD_WRITEABLE | Context.MODE_MULTI_PROCESS);
  142 + SharedPreferences.Editor editor = settings.edit();
  143 + editor.putLong(key, value);
  144 + return editor.commit();
  145 + } catch (Exception e) {
  146 +
  147 + }
  148 + return false;
  149 + }
  150 +
  151 + /**
  152 + * get long preferences
  153 + *
  154 + * @param context
  155 + * @param key The name of the preference to retrieve
  156 + * @return The preference value if it exists, or -1. Throws
  157 + * ClassCastException if there is a preference with this name that
  158 + * is not a long
  159 + * @see #getLong(Context, String, long)
  160 + */
  161 + public static long getLong(Context context, String key) {
  162 + return getLong(context, key, -1);
  163 + }
  164 +
  165 + /**
  166 + * get long preferences
  167 + *
  168 + * @param context
  169 + * @param key The name of the preference to retrieve
  170 + * @param defaultValue Value to return if this preference does not exist
  171 + * @return The preference value if it exists, or defValue. Throws
  172 + * ClassCastException if there is a preference with this name that
  173 + * is not a long
  174 + */
  175 + public static long getLong(Context context, String key, long defaultValue) {
  176 + try {
  177 + Context otherAppsContext = context.createPackageContext(PKG_NAME, Context.CONTEXT_IGNORE_SECURITY);
  178 + SharedPreferences share = otherAppsContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_WORLD_READABLE | Context.MODE_MULTI_PROCESS);
  179 + return share.getLong(key, defaultValue);
  180 + } catch (Exception e) {
  181 +
  182 + }
  183 + return defaultValue;
  184 + }
  185 +
  186 + /**
  187 + * put float preferences
  188 + *
  189 + * @param context
  190 + * @param key The name of the preference to modify
  191 + * @param value The new value for the preference
  192 + * @return True if the new values were successfully written to persistent
  193 + * storage.
  194 + */
  195 + public static boolean putFloat(Context context, String key, float value) {
  196 + try {
  197 + Context otherAppsContext = context.createPackageContext(PKG_NAME, Context.CONTEXT_IGNORE_SECURITY);
  198 + SharedPreferences settings = otherAppsContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_WORLD_WRITEABLE | Context.MODE_MULTI_PROCESS);
  199 + SharedPreferences.Editor editor = settings.edit();
  200 + editor.putFloat(key, value);
  201 + return editor.commit();
  202 + } catch (Exception e) {
  203 +
  204 + }
  205 + return false;
  206 + }
  207 +
  208 + /**
  209 + * get float preferences
  210 + *
  211 + * @param context
  212 + * @param key The name of the preference to retrieve
  213 + * @return The preference value if it exists, or -1. Throws
  214 + * ClassCastException if there is a preference with this name that
  215 + * is not a float
  216 + * @see #getFloat(Context, String, float)
  217 + */
  218 + public static float getFloat(Context context, String key) {
  219 + return getFloat(context, key, -1);
  220 + }
  221 +
  222 + /**
  223 + * get float preferences
  224 + *
  225 + * @param context
  226 + * @param key The name of the preference to retrieve
  227 + * @param defaultValue Value to return if this preference does not exist
  228 + * @return The preference value if it exists, or defValue. Throws
  229 + * ClassCastException if there is a preference with this name that
  230 + * is not a float
  231 + */
  232 + public static float getFloat(Context context, String key, float defaultValue) {
  233 + try {
  234 + Context otherAppsContext = context.createPackageContext(PKG_NAME, Context.CONTEXT_IGNORE_SECURITY);
  235 + SharedPreferences share = otherAppsContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_WORLD_READABLE | Context.MODE_MULTI_PROCESS);
  236 + return share.getFloat(key, defaultValue);
  237 + } catch (Exception e) {
  238 +
  239 + }
  240 + return defaultValue;
  241 + }
  242 +
  243 + /**
  244 + * put boolean preferences
  245 + *
  246 + * @param context
  247 + * @param key The name of the preference to modify
  248 + * @param value The new value for the preference
  249 + * @return True if the new values were successfully written to persistent
  250 + * storage.
  251 + */
  252 + public static boolean putBoolean(Context context, String key, boolean value) {
  253 + try {
  254 + Context otherAppsContext = context.createPackageContext(PKG_NAME, Context.CONTEXT_IGNORE_SECURITY);
  255 + SharedPreferences settings = otherAppsContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_WORLD_WRITEABLE | Context.MODE_MULTI_PROCESS);
  256 + SharedPreferences.Editor editor = settings.edit();
  257 + editor.putBoolean(key, value);
  258 + return editor.commit();
  259 + } catch (Exception e) {
  260 +
  261 + }
  262 + return false;
  263 + }
  264 +
  265 + /**
  266 + * get boolean preferences, default is false
  267 + *
  268 + * @param context
  269 + * @param key The name of the preference to retrieve
  270 + * @return The preference value if it exists, or false. Throws
  271 + * ClassCastException if there is a preference with this name that
  272 + * is not a boolean
  273 + * @see #getBoolean(Context, String, boolean)
  274 + */
  275 + public static boolean getBoolean(Context context, String key) {
  276 + return getBoolean(context, key, false);
  277 + }
  278 +
  279 + /**
  280 + * get boolean preferences
  281 + *
  282 + * @param context
  283 + * @param key The name of the preference to retrieve
  284 + * @param defaultValue Value to return if this preference does not exist
  285 + * @return The preference value if it exists, or defValue. Throws
  286 + * ClassCastException if there is a preference with this name that
  287 + * is not a boolean
  288 + */
  289 + public static boolean getBoolean(Context context, String key, boolean defaultValue) {
  290 + try {
  291 + Context otherAppsContext = context.createPackageContext(PKG_NAME, Context.CONTEXT_IGNORE_SECURITY);
  292 + SharedPreferences share = otherAppsContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_WORLD_READABLE | Context.MODE_MULTI_PROCESS);
  293 + return share.getBoolean(key, defaultValue);
  294 + } catch (Exception e) {
  295 +
  296 + }
  297 + return defaultValue;
  298 + }
  299 +}
... ...
... ... @@ -201,6 +201,28 @@
201 201 </TableRow>
202 202 <TableRow android:layout_width="match_parent"
203 203 android:layout_marginLeft="40dp"
  204 + android:layout_height="wrap_content">
  205 +
  206 + <Button style="@style/GeneralTextViewTheme"
  207 + android:onClick="setLights"
  208 + android:visibility="visible"
  209 + android:textColor="@color/black"
  210 + android:text="@string/set_sm_light"/>
  211 +
  212 + <Button style="@style/GeneralTextViewTheme"
  213 + android:onClick="setSmartScreen"
  214 + android:visibility="visible"
  215 + android:textColor="@color/black"
  216 + android:text="设置智能幕布"/>
  217 +
  218 + <Button style="@style/GeneralTextViewTheme"
  219 + android:onClick="update1905Movies"
  220 + android:visibility="invisible"
  221 + android:textColor="@color/black"
  222 + android:text="@string/update_1905_source"/>
  223 + </TableRow>
  224 + <TableRow android:layout_width="match_parent"
  225 + android:layout_marginLeft="40dp"
204 226 android:visibility="gone"
205 227 android:layout_height="wrap_content">
206 228
... ...
  1 +<!--
  2 + ~ Copyright 2017 wugian
  3 + ~
  4 + ~ Licensed under the Apache License, Version 2.0 (the "License");
  5 + ~ you may not use this file except in compliance with the License.
  6 + ~ You may obtain a copy of the License at
  7 + ~
  8 + ~ http://www.apache.org/licenses/LICENSE-2.0
  9 + ~
  10 + ~ Unless required by applicable law or agreed to in writing, software
  11 + ~ distributed under the License is distributed on an "AS IS" BASIS,
  12 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + ~ See the License for the specific language governing permissions and
  14 + ~ limitations under the License.
  15 + -->
  16 +
  17 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  18 + android:layout_width="match_parent"
  19 + android:layout_height="match_parent"
  20 + android:background="@android:color/white"
  21 + android:orientation="vertical">
  22 +
  23 + <RelativeLayout
  24 + android:layout_width="match_parent"
  25 + android:layout_height="wrap_content"
  26 + >
  27 +
  28 + <ImageView
  29 + android:id="@+id/img_header_menu_left"
  30 + android:layout_width="wrap_content"
  31 + android:layout_height="wrap_content"
  32 + android:layout_alignParentStart="true"
  33 + android:layout_centerVertical="true"
  34 + android:layout_marginStart="10dp"
  35 + android:contentDescription="@null"/>
  36 +
  37 + <TextView
  38 + android:id="@+id/txt_header_title"
  39 + android:layout_width="wrap_content"
  40 + android:layout_height="wrap_content"
  41 + android:layout_alignWithParentIfMissing="false"
  42 + android:layout_centerHorizontal="true"
  43 + android:layout_centerInParent="true"
  44 + android:layout_centerVertical="true"
  45 + android:layout_marginEnd="30dp"
  46 + android:layout_marginStart="30dp"
  47 + android:gravity="center_vertical"
  48 + android:singleLine="true"
  49 + android:text="配置智能幕布"
  50 + android:textAlignment="center"
  51 + android:textColor="@android:color/black"
  52 + android:textSize="18sp"/>
  53 + </RelativeLayout>
  54 +
  55 + <LinearLayout
  56 + android:layout_width="match_parent"
  57 + android:layout_height="wrap_content"
  58 + android:layout_marginLeft="5dp"
  59 + android:layout_marginRight="5dp"
  60 + android:layout_marginTop="15dp"
  61 + android:orientation="vertical">
  62 +
  63 +
  64 + <EditText
  65 + android:id="@+id/ssid_et"
  66 + android:layout_width="match_parent"
  67 + android:layout_height="wrap_content"
  68 + android:editable="false"
  69 + android:ems="10"
  70 + android:inputType="text"
  71 + android:labelFor="@+id/txt_mesh_name"
  72 + android:hint="ssid"/>
  73 +
  74 + <EditText
  75 + android:id="@+id/pwd_et"
  76 + android:layout_width="match_parent"
  77 + android:layout_height="wrap_content"
  78 + android:ems="10"
  79 + android:layout_marginTop="10dp"
  80 + android:inputType="textPassword"
  81 + android:labelFor="@+id/txt_mesh_password"
  82 + android:hint="password"/>
  83 +
  84 +
  85 + <Button
  86 + android:id="@+id/btn_save"
  87 + android:layout_width="match_parent"
  88 + android:layout_height="46dp"
  89 + android:layout_marginTop="15dp"
  90 + android:text="开始配置"
  91 + android:textColor="@android:color/black"
  92 + android:textSize="18sp"/>
  93 +
  94 + <Button
  95 + android:layout_width="match_parent"
  96 + android:layout_height="46dp"
  97 + android:layout_marginTop="15dp"
  98 + android:onClick="matchScreen"
  99 + android:text="配对幕布"
  100 + android:textColor="@android:color/black"
  101 + android:textSize="18sp"/>
  102 + </LinearLayout>
  103 + <TextView android:layout_width="match_parent"
  104 + android:layout_height="wrap_content"
  105 + android:padding="10dp"
  106 + android:textColor="@color/red"
  107 + android:text="请将本机连接到wifi进行配置,或者使用极米助手进行配置!!"
  108 + />
  109 +
  110 +</LinearLayout>
\ No newline at end of file
... ...
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + xmlns:app="http://schemas.android.com/apk/res-auto"
  4 + xmlns:tools="http://schemas.android.com/tools"
  5 + android:layout_width="match_parent"
  6 + android:layout_height="match_parent"
  7 + android:paddingBottom="@dimen/activity_vertical_margin"
  8 + android:paddingLeft="@dimen/activity_horizontal_margin"
  9 + android:paddingRight="@dimen/activity_horizontal_margin"
  10 + android:paddingTop="@dimen/activity_vertical_margin"
  11 + tools:showIn="@layout/activity_main">
  12 +
  13 +
  14 + <ListView
  15 + android:id="@+id/lv_device"
  16 + android:layout_width="match_parent"
  17 + android:layout_height="match_parent"/>
  18 +
  19 +</RelativeLayout>
... ...
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="400dp"
  4 + android:layout_height="wrap_content"
  5 + android:gravity="center_horizontal"
  6 + android:orientation="vertical">
  7 +
  8 + <LinearLayout
  9 + android:layout_width="match_parent"
  10 + android:layout_height="32dp"
  11 + android:background="@color/white"
  12 + android:gravity="center"
  13 + android:orientation="vertical">
  14 +
  15 + <TextView
  16 + android:layout_width="wrap_content"
  17 + android:layout_height="wrap_content"
  18 + android:text="幕布控制"
  19 + android:textColor="@color/black"
  20 + android:textSize="16sp" />
  21 +
  22 + <TextView
  23 + android:id="@+id/tv_dialog_ip"
  24 + android:layout_width="wrap_content"
  25 + android:layout_height="wrap_content"
  26 + android:textColor="@color/black"
  27 + android:textSize="16sp" />
  28 +
  29 + </LinearLayout>
  30 +
  31 + <TextView
  32 + android:layout_width="match_parent"
  33 + android:layout_height="1dp"
  34 + android:background="@color/gray" />
  35 +
  36 + <LinearLayout
  37 + android:layout_width="match_parent"
  38 + android:layout_height="90dp">
  39 +
  40 + <TextView
  41 + android:id="@+id/tv_device_info"
  42 + android:layout_width="match_parent"
  43 + android:layout_height="match_parent"
  44 + android:padding="5dp"
  45 + android:textColor="@color/black"
  46 + android:textSize="14sp" />
  47 +
  48 + </LinearLayout>
  49 +
  50 +
  51 + <TextView
  52 + android:layout_width="match_parent"
  53 + android:layout_height="1dp"
  54 + android:background="@color/gray" />
  55 +
  56 +
  57 + <LinearLayout
  58 + android:layout_width="match_parent"
  59 + android:layout_height="48sp">
  60 +
  61 + <Button
  62 + android:id="@+id/tv_up"
  63 + android:layout_width="0dp"
  64 + android:layout_height="match_parent"
  65 + android:layout_weight="1"
  66 + android:gravity="center"
  67 + android:text="上"
  68 + android:textColor="@color/g"
  69 + android:textSize="16sp" />
  70 +
  71 + <TextView
  72 + android:layout_width="1dp"
  73 + android:layout_height="match_parent"
  74 + android:background="@color/gray" />
  75 +
  76 + <Button
  77 + android:id="@+id/tv_down"
  78 + android:layout_width="0dp"
  79 + android:layout_height="match_parent"
  80 + android:layout_weight="1"
  81 + android:gravity="center"
  82 + android:text="下"
  83 + android:textColor="@color/g"
  84 + android:textSize="16sp" />
  85 +
  86 + </LinearLayout>
  87 +
  88 +
  89 +</LinearLayout>
\ No newline at end of file
... ...
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + xmlns:app="http://schemas.android.com/apk/res-auto"
  4 + xmlns:tools="http://schemas.android.com/tools"
  5 + android:layout_width="match_parent"
  6 + android:layout_height="match_parent"
  7 + android:fitsSystemWindows="true">
  8 +
  9 + <android.support.design.widget.AppBarLayout
  10 + android:layout_width="match_parent"
  11 + android:layout_height="wrap_content"
  12 + android:theme="@style/AppTheme.AppBarOverlay">
  13 +
  14 + <android.support.v7.widget.Toolbar
  15 + android:id="@+id/toolbar"
  16 + android:layout_width="match_parent"
  17 + android:layout_height="?attr/actionBarSize"
  18 + android:background="@color/g"
  19 + app:popupTheme="@style/AppTheme.PopupOverlay" />
  20 +
  21 + </android.support.design.widget.AppBarLayout>
  22 +
  23 + <include layout="@layout/content_main" />
  24 +
  25 +</android.support.design.widget.CoordinatorLayout>
... ...
Please register or login to post a comment