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 | +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 | + | |
| 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