Created
March 29, 2019 13:36
-
-
Save Ayyagaries/09a8b752d614795b8d1b10403cff6457 to your computer and use it in GitHub Desktop.
MainActivity.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.ix.ebadgesdk.sample; | |
import androidx.annotation.NonNull; | |
import androidx.appcompat.app.AppCompatActivity; | |
import androidx.core.app.ActivityCompat; | |
import androidx.recyclerview.widget.DefaultItemAnimator; | |
import androidx.recyclerview.widget.LinearLayoutManager; | |
import androidx.recyclerview.widget.RecyclerView; | |
import no.nordicsemi.android.ble.data.Data; | |
import android.Manifest; | |
import android.app.Dialog; | |
import android.bluetooth.BluetoothAdapter; | |
import android.bluetooth.BluetoothDevice; | |
import android.bluetooth.BluetoothGatt; | |
import android.bluetooth.BluetoothGattService; | |
import android.bluetooth.BluetoothManager; | |
import android.bluetooth.BluetoothProfile; | |
import android.content.Context; | |
import android.graphics.Bitmap; | |
import android.graphics.BitmapFactory; | |
import android.graphics.Color; | |
import android.os.Bundle; | |
import android.text.InputType; | |
import android.util.Log; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.widget.Button; | |
import android.widget.EditText; | |
import android.widget.LinearLayout; | |
import android.widget.ToggleButton; | |
import com.afollestad.materialdialogs.MaterialDialog; | |
import com.afollestad.materialdialogs.folderselector.FileChooserDialog; | |
import com.afollestad.materialdialogs.simplelist.MaterialSimpleListAdapter; | |
import com.afollestad.materialdialogs.simplelist.MaterialSimpleListItem; | |
import com.github.rtoshiro.util.format.SimpleMaskFormatter; | |
import com.github.rtoshiro.util.format.text.MaskTextWatcher; | |
import com.ix.ebadgesdk.CmdController; | |
import com.ix.ebadgesdk.EBadgeBleManager; | |
import com.ix.ebadgesdk.EBadgeBleManagerCallback; | |
import com.ix.ebadgesdk.Utils; | |
import com.ix.ebadgesdk.bean.ImageConfig; | |
import com.ix.ebadgesdk.bean.ImageData; | |
import org.apache.commons.io.IOUtils; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.IOException; | |
import java.nio.ByteBuffer; | |
import java.nio.charset.Charset; | |
import java.text.ParseException; | |
import java.text.SimpleDateFormat; | |
import java.util.ArrayList; | |
import java.util.Date; | |
import java.util.HashSet; | |
import java.util.List; | |
import java.util.Locale; | |
import java.util.UUID; | |
import static com.ix.ebadgesdk.EBadgeBleManager.bytesToHex; | |
public class MainActivity extends AppCompatActivity implements FileChooserDialog.FileCallback { | |
private static final String TAG = "BLESample"; | |
private final static String DEFAULT_IMG_DATA = "000000b6ffdbffb6000000000000b6ffffffb60000006db7b6dbffffffdbb6b749ffffffffffffffffffffffffdbb7b7b7b7b7b7b7dbffffdb00000000000000dbffffdb00000000000000dbffffdb92929292929292dbffffffdbdbdbdbdbdbdbffffffdb00000000000000dbffffdb00000000000000dbffffdb92929292929292dbffffffdbdbdbdbdbdbdbffffffdb00000000000000dbffffdb00000000000000dbffffdb92929292929292dbffffffdbdbdbdbdbdbdbffffffdb00000000000000dbffffdb00000000000000dbffffdb6e6e6e6e6e6e6edbffffffffffffffffffffffff6edbdbdbdbdbdbdbdbdb6e"; | |
private BluetoothManager mBluetoothManager; | |
private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); | |
private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() { | |
@Override | |
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { | |
if (device.getName() != null && device.getName().startsWith("R5") && !(mBLEDeviceAddressSet.contains(device.getAddress()))) { | |
mBLEDeviceAddressSet.add(device.getAddress()); | |
mMaterialSimpleListAdapter.add(new MaterialSimpleListItem.Builder(MainActivity.this) | |
.id(device.getAddress().hashCode()) | |
.tag(device) | |
.content("Name: " + device.getName() + " Mac: " + device.getAddress()) | |
.build()); | |
} | |
} | |
}; | |
private BluetoothGatt mBluetoothGatt; | |
private EBadgeBleManager mBleManager; | |
private MaterialSimpleListAdapter mMaterialSimpleListAdapter; | |
private HashSet<String> mBLEDeviceAddressSet = new HashSet<>(); | |
private RecyclerView mRecyclerView; | |
private LogAdapter mLogAdapter; | |
private String mImgDataHexString = DEFAULT_IMG_DATA; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
mRecyclerView = findViewById(R.id.rv_ble_log); | |
mLogAdapter = new LogAdapter(); | |
mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); | |
mRecyclerView.setItemAnimator(new DefaultItemAnimator()); | |
mRecyclerView.setAdapter(mLogAdapter); | |
mBleManager = new EBadgeBleManager(getApplicationContext()); | |
ActivityCompat.requestPermissions(this, | |
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.READ_EXTERNAL_STORAGE}, | |
0); | |
mMaterialSimpleListAdapter = new MaterialSimpleListAdapter(new MaterialSimpleListAdapter.Callback() { | |
@Override | |
public void onMaterialListItemSelected(MaterialDialog dialog, int index, MaterialSimpleListItem item) { | |
dialog.cancel(); | |
connectToDevice(((BluetoothDevice) item.getTag())); | |
} | |
}); | |
mBluetoothManager = (BluetoothManager) | |
getSystemService(Context.BLUETOOTH_SERVICE); | |
showNearByBLEDevice(); | |
getPairedDevices(); | |
byte[] result = CmdController.addFlashImageTest(); | |
byte[] addPageTestResult = CmdController.addPageTest(); | |
byte[] refreshResult = CmdController.refreshTest(); | |
Log.d(TAG, "onCreate: " + bytesToHex(result)); | |
Log.d(TAG, "addPageTestResult: " + bytesToHex(addPageTestResult)); | |
Log.d(TAG, "refreshResult: " + bytesToHex(refreshResult)); | |
} | |
private void showNearByBLEDevice() { | |
new MaterialDialog.Builder(this).adapter(mMaterialSimpleListAdapter, null).cancelable(false).show(); | |
} | |
private void connectToDevice(BluetoothDevice device) { | |
mBleManager.setGattCallbacks(new EBadgeBleManagerCallback() { | |
@Override | |
public void onError(@NonNull BluetoothDevice device, @NonNull String message, int errorCode) { | |
Log.d(TAG, "onError: " + message + ", code:" + errorCode); | |
} | |
@Override | |
public void onNotificationDataReceive(@NonNull BluetoothDevice device, @NonNull Data data) { | |
super.onNotificationDataReceive(device, data); | |
mLogAdapter.addLog("Notify: " + bytesToHex(data.getValue())); | |
mRecyclerView.smoothScrollToPosition(mLogAdapter.getItemCount() - 1); | |
} | |
@Override | |
public void log(int priority, @NonNull String message) { | |
super.log(priority, message); | |
mLogAdapter.addLog(message); | |
mRecyclerView.smoothScrollToPosition(mLogAdapter.getItemCount() - 1); | |
} | |
}); | |
mBleManager.connect(device).useAutoConnect(false).enqueue(); | |
} | |
public void customCmd(View view) { | |
new MaterialDialog.Builder(this) | |
.title("cmd") | |
.inputType(InputType.TYPE_CLASS_TEXT) | |
.input("", "", (dialog, input) -> mBleManager.customCmd(input.toString()));//.show(); | |
new FileChooserDialog.Builder(this) | |
.tag("customCmd") | |
.extensionsFilter(".txt") // Optional extension filter, will override mimeType() | |
.show(this); // an AppCompatActivity which implements FileCallback | |
} | |
@Override | |
public void onFileSelection(@NonNull FileChooserDialog dialog, @NonNull File file) { | |
dialog.dismiss(); | |
String tag = ""; | |
if (dialog.getTag() != null) { | |
tag = dialog.getTag(); | |
} | |
switch (tag) { | |
case "customCmd": | |
new Thread(() -> { | |
try { | |
FileInputStream fin = new FileInputStream(file); | |
String result = IOUtils.toString(fin, Charset.defaultCharset()); | |
mBleManager.customCmd(result); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
}).run(); | |
break; | |
case "imageData": | |
final Dialog loadingDialog = new MaterialDialog.Builder(this).title("Decoding...") | |
.progress(true, 0) | |
.show(); | |
new Thread(() -> { | |
try { | |
BitmapFactory.Options options = new BitmapFactory.Options(); | |
options.inPreferredConfig = Bitmap.Config.ARGB_8888; | |
Bitmap bitmap = BitmapFactory.decodeFile(file.getPath(), options); | |
mImgDataHexString = Utils.byteArrayToHexString(bitmapTo8BitImage(bitmap)); | |
loadingDialog.dismiss(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
}).run(); | |
break; | |
} | |
} | |
private byte[] bitmapTo8BitImage(Bitmap bitmap) { | |
int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()]; | |
bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, | |
bitmap.getWidth(), bitmap.getHeight()); | |
ByteBuffer eightByteBuffer = ByteBuffer.allocate(pixels.length); | |
for (int i = 0; i < pixels.length; i++) { | |
int p = pixels[i]; | |
int red = Color.red(p); | |
int green = Color.green(p); | |
int blue = Color.blue(p); | |
byte p1Rgb = (byte) (((int) Math.round(red / 255.0 * 7.0) << 5) | | |
((int) Math.round(green / 255.0 * 7.0) << 2) | | |
((int) Math.round(blue / 255.0 * 3.0))); | |
eightByteBuffer.put(p1Rgb); | |
} | |
return eightByteBuffer.array(); | |
} | |
@Override | |
public void onFileChooserDismissed(@NonNull FileChooserDialog dialog) { | |
} | |
public void sendImage(View view) { | |
//mBleManager.sendImageBuffer(); | |
showSendImageDialog(); | |
} | |
private void showSendImageDialog() { | |
LinearLayout linearLayout = new LinearLayout(this); | |
linearLayout.setOrientation(LinearLayout.VERTICAL); | |
ViewGroup.LayoutParams editTextLayoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); | |
final EditText imageIdEdit = new EditText(this); | |
imageIdEdit.setHint("ImageId"); | |
imageIdEdit.setInputType(InputType.TYPE_CLASS_NUMBER); | |
imageIdEdit.setText("1"); | |
final EditText widthEdit = new EditText(this); | |
widthEdit.setHint("Width"); | |
widthEdit.setInputType(InputType.TYPE_CLASS_NUMBER); | |
widthEdit.setText("11"); | |
final EditText heightEdit = new EditText(this); | |
heightEdit.setHint("Height"); | |
heightEdit.setInputType(InputType.TYPE_CLASS_NUMBER); | |
heightEdit.setText("22"); | |
final Button imageDataBtn = new Button(this); | |
imageDataBtn.setAllCaps(false); | |
imageDataBtn.setText("ImageFile"); | |
imageDataBtn.setOnClickListener(v -> { | |
new FileChooserDialog.Builder(this) | |
.tag("imageData") | |
.mimeType("image/*") | |
//.extensionsFilter(".txt") // Optional extension filter, will override mimeType() | |
.show(this); // an AppCompatActivity which implements FileCallback | |
}); | |
linearLayout.addView(imageIdEdit, editTextLayoutParams); | |
linearLayout.addView(widthEdit, editTextLayoutParams); | |
linearLayout.addView(heightEdit, editTextLayoutParams); | |
linearLayout.addView(imageDataBtn); | |
new MaterialDialog.Builder(this) | |
.title("Send Image") | |
.customView(linearLayout, true) | |
.positiveText(android.R.string.ok) | |
.negativeText(android.R.string.cancel) | |
.onPositive((dialog, which) -> { | |
int imageId = Integer.parseInt(imageIdEdit.getText().toString()); | |
int width = Integer.parseInt(widthEdit.getText().toString()); | |
int height = Integer.parseInt(heightEdit.getText().toString()); | |
sendImg(imageId, width, height); | |
}) | |
.show(); | |
} | |
private void sendImg(int imageId, int width, int height) { | |
ImageData imageData = new ImageData(); | |
imageData.id = imageId; | |
imageData.width = width; | |
imageData.height = height; | |
imageData.data = Utils.hexStringToByteArray(mImgDataHexString); | |
mBleManager.sendImageBuffer(imageData); | |
mImgDataHexString = DEFAULT_IMG_DATA; | |
} | |
private void showSetImageDialog() { | |
LinearLayout linearLayout = new LinearLayout(this); | |
linearLayout.setOrientation(LinearLayout.VERTICAL); | |
ViewGroup.LayoutParams editTextLayoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); | |
final EditText pageIdEdit = new EditText(this); | |
pageIdEdit.setHint("PageId"); | |
pageIdEdit.setInputType(InputType.TYPE_CLASS_NUMBER); | |
pageIdEdit.setText("1"); | |
final ToggleButton backgroundToggle = new ToggleButton(this); | |
backgroundToggle.setTextOn("White"); | |
backgroundToggle.setTextOff("Black"); | |
backgroundToggle.setChecked(false); | |
final EditText expiredEdit = new EditText(this); | |
expiredEdit.setHint("ExpiredTime: 2019/10/10 11:12:13"); | |
expiredEdit.setInputType(InputType.TYPE_CLASS_NUMBER); | |
expiredEdit.setText("2019/10/10 11:12:13"); | |
SimpleMaskFormatter smf = new SimpleMaskFormatter("NNNN/NN/NN NN:NN:NN"); | |
MaskTextWatcher mtw = new MaskTextWatcher(expiredEdit, smf); | |
expiredEdit.addTextChangedListener(mtw); | |
final EditText imageIdEdit = new EditText(this); | |
imageIdEdit.setHint("ImageId"); | |
imageIdEdit.setInputType(InputType.TYPE_CLASS_NUMBER); | |
imageIdEdit.setText("1"); | |
final EditText xEdit = new EditText(this); | |
xEdit.setHint("X"); | |
xEdit.setInputType(InputType.TYPE_CLASS_NUMBER); | |
xEdit.setText("100"); | |
final EditText yEdit = new EditText(this); | |
yEdit.setHint("Y"); | |
yEdit.setInputType(InputType.TYPE_CLASS_NUMBER); | |
yEdit.setText("200"); | |
final ToggleButton invertToggle = new ToggleButton(this); | |
invertToggle.setTextOn("Invert"); | |
invertToggle.setTextOff("Normal"); | |
invertToggle.setChecked(false); | |
linearLayout.addView(pageIdEdit, editTextLayoutParams); | |
linearLayout.addView(backgroundToggle); | |
linearLayout.addView(expiredEdit, editTextLayoutParams); | |
linearLayout.addView(imageIdEdit, editTextLayoutParams); | |
linearLayout.addView(xEdit, editTextLayoutParams); | |
linearLayout.addView(yEdit, editTextLayoutParams); | |
linearLayout.addView(invertToggle); | |
new MaterialDialog.Builder(this) | |
.title("Send Image") | |
.customView(linearLayout, true) | |
.positiveText(android.R.string.ok) | |
.negativeText(android.R.string.cancel) | |
.onPositive((dialog, which) -> { | |
int pageId = Integer.parseInt(pageIdEdit.getText().toString()); | |
boolean background = backgroundToggle.isChecked(); | |
Date date = parseDate(expiredEdit.getText().toString()); | |
int imageId = Integer.parseInt(imageIdEdit.getText().toString()); | |
int x = Integer.parseInt(xEdit.getText().toString()); | |
int y = Integer.parseInt(yEdit.getText().toString()); | |
boolean invert = invertToggle.isChecked(); | |
ImageConfig imageConfig = new ImageConfig(); | |
imageConfig.imageId = imageId; | |
imageConfig.x = x; | |
imageConfig.y = y; | |
imageConfig.invert = invert; | |
List<ImageConfig> configList = new ArrayList<>(); | |
configList.add(imageConfig); | |
mBleManager.setImageConfig(pageId, background ? 1 : 0, date, configList); | |
}) | |
.show(); | |
} | |
private Date parseDate(String dataString) { | |
Date date = new Date(); | |
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US); | |
try { | |
date = format.parse(dataString); | |
System.out.println(date); | |
} catch (ParseException e) { | |
e.printStackTrace(); | |
} | |
return date; | |
} | |
public void setPage(View view) { | |
showSetImageDialog(); | |
} | |
private void showRefreshDialog() { | |
LinearLayout linearLayout = new LinearLayout(this); | |
linearLayout.setOrientation(LinearLayout.VERTICAL); | |
ViewGroup.LayoutParams editTextLayoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); | |
final EditText pageIdEdit = new EditText(this); | |
pageIdEdit.setHint("ImageId"); | |
pageIdEdit.setInputType(InputType.TYPE_CLASS_NUMBER); | |
pageIdEdit.setText("1"); | |
linearLayout.addView(pageIdEdit, editTextLayoutParams); | |
new MaterialDialog.Builder(this) | |
.title("Send Image") | |
.customView(linearLayout, true) | |
.positiveText(android.R.string.ok) | |
.negativeText(android.R.string.cancel) | |
.onPositive((dialog, which) -> { | |
int pageId = Integer.parseInt(pageIdEdit.getText().toString()); | |
mBleManager.refresh(pageId); | |
}) | |
.show(); | |
} | |
public void refresh(View view) { | |
showRefreshDialog(); | |
} | |
public void clean(View view) { | |
mBleManager.clean(); | |
} | |
private void getPairedDevices() { | |
for (BluetoothDevice device : mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT)) { | |
if (device.getName() != null && device.getName().startsWith("R5") && !(mBLEDeviceAddressSet.contains(device.getAddress()))) { | |
mBLEDeviceAddressSet.add(device.getAddress()); | |
mMaterialSimpleListAdapter.add(new MaterialSimpleListItem.Builder(MainActivity.this) | |
.id(device.getAddress().hashCode()) | |
.tag(device) | |
.content("Name(Paired): " + device.getName() + " Mac: " + device.getAddress()) | |
.build()); | |
} | |
} | |
} | |
public static byte[] hexStringToByteArray(String s) { | |
int len = s.length(); | |
byte[] data = new byte[len / 2]; | |
for (int i = 0; i < len; i += 2) { | |
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) | |
+ Character.digit(s.charAt(i + 1), 16)); | |
} | |
return data; | |
} | |
private void getBatteryLevel(BluetoothGatt gatt) { | |
for (BluetoothGattService service : gatt.getServices()) { | |
Log.d(TAG, "service list: " + service.getUuid()); | |
} | |
BluetoothGattService service = gatt.getService(UUID.fromString("0000180f-0000-1000-8000-00805f9b34fb")); | |
Log.d(TAG, "battery service == null: " + String.valueOf(service == null)); | |
if (service != null) { | |
gatt.readCharacteristic(service.getCharacteristic(UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb"))); | |
} | |
} | |
@Override | |
protected void onStart() { | |
super.onStart(); | |
mBluetoothAdapter.startLeScan(leScanCallback); | |
} | |
@Override | |
protected void onStop() { | |
super.onStop(); | |
mBluetoothAdapter.stopLeScan(leScanCallback); | |
} | |
@Override | |
protected void onDestroy() { | |
super.onDestroy(); | |
if (mBleManager != null) { | |
mBleManager.disconnect(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment