<activity android:name=".modules.blood_glucose.BloodGlucoseActivity" /> | <activity android:name=".modules.blood_glucose.BloodGlucoseActivity" /> | ||||
<activity android:name=".modules.blood_glucose.BloodGlucoseTestActivity" /> | <activity android:name=".modules.blood_glucose.BloodGlucoseTestActivity" /> | ||||
<activity android:name=".BLDWeightScaleBleActivity" /> | <activity android:name=".BLDWeightScaleBleActivity" /> | ||||
<activity android:name=".ToothBrushBleActivity"/> | |||||
<service android:name="com.pingwang.bluetoothlib.server.ELinkBleServer"/> | <service android:name="com.pingwang.bluetoothlib.server.ELinkBleServer"/> | ||||
</application> | </application> |
import android.content.Intent; | import android.content.Intent; | ||||
import android.os.Message; | import android.os.Message; | ||||
import android.util.Log; | |||||
import android.view.View; | import android.view.View; | ||||
import android.widget.TextView; | import android.widget.TextView; | ||||
import com.besthealth.bhBodyComposition120.BhBodyComposition; | |||||
import com.pingwang.bluetoothlib.AILinkSDK; | import com.pingwang.bluetoothlib.AILinkSDK; | ||||
import com.pingwang.bluetoothlib.utils.BleLog; | import com.pingwang.bluetoothlib.utils.BleLog; | ||||
mList.add(findViewById(R.id.btn_rope_skip)); | mList.add(findViewById(R.id.btn_rope_skip)); | ||||
mList.add(findViewById(R.id.btn_broadcast_nutrition)); | mList.add(findViewById(R.id.btn_broadcast_nutrition)); | ||||
mList.add(findViewById(R.id.btn_ble_nutrition)); | mList.add(findViewById(R.id.btn_ble_nutrition)); | ||||
mList.add(findViewById(R.id.btn_toothbrush_ble)); | |||||
for (View view : mList) { | for (View view : mList) { | ||||
view.setOnClickListener(listener); | view.setOnClickListener(listener); | ||||
} | } | ||||
case R.id.btn_wifi_ble_tooth: | case R.id.btn_wifi_ble_tooth: | ||||
type = BleDeviceConfig.TOOTHBRUSH_WIFI_BLE; | type = BleDeviceConfig.TOOTHBRUSH_WIFI_BLE; | ||||
break; | break; | ||||
case R.id.btn_toothbrush_ble: | |||||
type = BleDeviceConfig.TOOTHBRUSH_BLE; | |||||
break; | |||||
case R.id.btn_ble_weight: | case R.id.btn_ble_weight: | ||||
type = BleDeviceConfig.WEIGHT_BODY_FAT_SCALE; | type = BleDeviceConfig.WEIGHT_BODY_FAT_SCALE; | ||||
break; | break; |
import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.share_charger.ShareChargerActivity; | import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.share_charger.ShareChargerActivity; | ||||
import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.share_condom.ShareCondomActivity; | import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.share_condom.ShareCondomActivity; | ||||
import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.share_socket.ShareSocketActivity; | import aicare.net.cn.sdk.ailinksdkdemoandroid.modules.share_socket.ShareSocketActivity; | ||||
import androidx.annotation.NonNull; | import androidx.annotation.NonNull; | ||||
import androidx.annotation.Nullable; | import androidx.annotation.Nullable; | ||||
import androidx.appcompat.app.AppCompatActivity; | import androidx.appcompat.app.AppCompatActivity; | ||||
showLoading(); | showLoading(); | ||||
} | } | ||||
} else if (BleDeviceConfig.TOOTHBRUSH_WIFI_BLE == mType) { | } else if (BleDeviceConfig.TOOTHBRUSH_WIFI_BLE == mType) { | ||||
mBluetoothService.stopScan(); | |||||
Intent intent = new Intent(); | Intent intent = new Intent(); | ||||
intent.setClass(ShowBleActivity.this, ToothBrushWifiBleActivity.class); | intent.setClass(ShowBleActivity.this, ToothBrushWifiBleActivity.class); | ||||
intent.putExtra("type", mType); | |||||
intent.putExtra("type", mCid); | |||||
intent.putExtra("mac", mac); | intent.putExtra("mac", mac); | ||||
startActivity(intent); | startActivity(intent); | ||||
finish(); | finish(); | ||||
} else { | |||||
} else if (BleDeviceConfig.TOOTHBRUSH_BLE==mType){ | |||||
mBluetoothService.stopScan(); | |||||
Intent intent = new Intent(); | |||||
intent.setClass(ShowBleActivity.this, ToothBrushBleActivity.class); | |||||
intent.putExtra("type", mCid); | |||||
intent.putExtra("mac", mac); | |||||
startActivity(intent); | |||||
finish(); | |||||
}else { | |||||
if (mCid == BleDeviceConfig.BLE_BOOLD_OXYGEN && mVid == 0x0012) { | if (mCid == BleDeviceConfig.BLE_BOOLD_OXYGEN && mVid == 0x0012) { | ||||
//vid=12的不用握手校验,不加密 | //vid=12的不用握手校验,不加密 | ||||
mNoEncryptionMac = mac; | mNoEncryptionMac = mac; | ||||
intent.setClass(ShowBleActivity.this, WeightScaleWifiBleActivity.class); | intent.setClass(ShowBleActivity.this, WeightScaleWifiBleActivity.class); | ||||
break; | break; | ||||
case BleDeviceConfig.TOOTHBRUSH_WIFI_BLE: | case BleDeviceConfig.TOOTHBRUSH_WIFI_BLE: | ||||
intent.setClass(ShowBleActivity.this, ToothBrushWifiBleActivity.class); | intent.setClass(ShowBleActivity.this, ToothBrushWifiBleActivity.class); | ||||
break; | break; | ||||
case BleDeviceConfig.TOOTHBRUSH_BLE: | |||||
intent.setClass(ShowBleActivity.this, ToothBrushBleActivity.class); | |||||
break; | |||||
case BleDeviceConfig.EIGHT_BODY_FAT_SCALE: | case BleDeviceConfig.EIGHT_BODY_FAT_SCALE: | ||||
intent.setClass(ShowBleActivity.this, EightBodyfatActivity.class); | intent.setClass(ShowBleActivity.this, EightBodyfatActivity.class); | ||||
break; | break; | ||||
case BleDeviceConfig.ROPE_SKIPPING: | case BleDeviceConfig.ROPE_SKIPPING: | ||||
intent.setClass(ShowBleActivity.this, RopeSkippingActivity.class); | intent.setClass(ShowBleActivity.this, RopeSkippingActivity.class); | ||||
break; | break; | ||||
// case BleDeviceConfig.TOOTHBRUSH_TEST: | |||||
// // 牙刷测试 | |||||
// intent.setClass(ShowBleActivity.this, ToothbrushTestActivity.class); | |||||
// break; | |||||
case BleDeviceConfig.BLE_NUTRITION_SCALE: | case BleDeviceConfig.BLE_NUTRITION_SCALE: | ||||
// 蓝牙营养秤 | // 蓝牙营养秤 | ||||
// intent.setClass(ShowBleActivity.this, BleNutritionActivity.class); | // intent.setClass(ShowBleActivity.this, BleNutritionActivity.class); | ||||
} | } | ||||
return false; | return false; | ||||
} else { | } else { | ||||
return mType == cid; | return mType == cid; | ||||
} | } | ||||
package aicare.net.cn.sdk.ailinksdkdemoandroid; | |||||
import android.content.Intent; | |||||
import android.content.pm.ActivityInfo; | |||||
import android.os.Bundle; | |||||
import android.os.Handler; | |||||
import android.os.Message; | |||||
import android.util.Log; | |||||
import android.view.View; | |||||
import android.widget.ArrayAdapter; | |||||
import android.widget.EditText; | |||||
import android.widget.ListView; | |||||
import android.widget.Toast; | |||||
import androidx.annotation.Nullable; | |||||
import com.pingwang.bluetoothlib.bean.BleValueBean; | |||||
import com.pingwang.bluetoothlib.device.BleDevice; | |||||
import com.pingwang.bluetoothlib.listener.OnCallbackBle; | |||||
import com.pingwang.bluetoothlib.utils.BleLog; | |||||
import com.pingwang.bluetoothlib.utils.BleStrUtils; | |||||
import java.lang.ref.WeakReference; | |||||
import java.util.ArrayList; | |||||
import java.util.Arrays; | |||||
import java.util.List; | |||||
import aicare.net.cn.sdk.ailinksdkdemoandroid.base.BleBaseActivity; | |||||
import aicare.net.cn.sdk.ailinksdkdemoandroid.config.BleDeviceConfig; | |||||
import cn.net.aicare.modulelibrary.module.ToothBrush.ToothBrushBleCmd; | |||||
/** | |||||
* ble 牙刷 | |||||
*/ | |||||
public class ToothBrushBleActivity extends BleBaseActivity implements View.OnClickListener, OnCallbackBle,ToothBrushBleUtilsData.BleToothBrushCallback { | |||||
private String TAG = ToothBrushBleActivity.class.getName(); | |||||
private String mAddress; | |||||
private int type; | |||||
private List<String> mList; | |||||
private ArrayAdapter listAdapter; | |||||
private MHandler mMHandler; | |||||
private EditText select_gears_et; | |||||
private ToothBrushBleUtilsData mToothBrushBleUtilsData; | |||||
@Override | |||||
protected void onCreate(@Nullable Bundle savedInstanceState) { | |||||
super.onCreate(savedInstanceState); | |||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//禁止横屏 | |||||
setContentView(R.layout.activity_tooth_brush_ble); | |||||
findViewById(R.id.support_unit).setOnClickListener(this); | |||||
findViewById(R.id.default_try_out).setOnClickListener(this); | |||||
findViewById(R.id.default_time_mode).setOnClickListener(this); | |||||
findViewById(R.id.default_mode).setOnClickListener(this); | |||||
select_gears_et = findViewById(R.id.select_gears_et); | |||||
mAddress = getIntent().getStringExtra("mac"); | |||||
type = getIntent().getIntExtra("type", BleDeviceConfig.TOOTHBRUSH_BLE); | |||||
mList = new ArrayList<>(); | |||||
ListView listView = findViewById(R.id.log_list); | |||||
listAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mList); | |||||
listView.setAdapter(listAdapter); | |||||
WeakReference weakReference = new WeakReference(new MHandler()); | |||||
mMHandler = (MHandler) weakReference.get(); | |||||
} | |||||
@Override | |||||
protected void onNewIntent(Intent intent) { | |||||
super.onNewIntent(intent); | |||||
setIntent(intent); | |||||
} | |||||
@Override | |||||
public void onServiceSuccess() { | |||||
//与服务建立连接 | |||||
mList.add(0, "服务与界面建立连接成功"); | |||||
// mList.add(0, "搜索设备"); | |||||
mMHandler.sendEmptyMessage(ToRefreUi); | |||||
mBluetoothService.setOnCallback(this); | |||||
mBluetoothService.scanLeDevice(30 * 1000); | |||||
} | |||||
@Override | |||||
public void onServiceErr() { | |||||
} | |||||
@Override | |||||
public void unbindServices() { | |||||
} | |||||
@Override | |||||
public void onStartScan() { | |||||
} | |||||
@Override | |||||
public void onScanning(BleValueBean data) { | |||||
BleLog.i(TAG, "MAC=" + mAddress + "||CID=" + data.getCid() + "||VID=" + data.getVid() + "||PID=" + data.getPid()); | |||||
if (data.getMac().equalsIgnoreCase(mAddress)) { | |||||
mBluetoothService.stopScan(); | |||||
mBluetoothService.connectDevice(data.getMac()); | |||||
} | |||||
} | |||||
@Override | |||||
public void onScanTimeOut() { | |||||
} | |||||
@Override | |||||
public void onConnecting(String mac) { | |||||
} | |||||
@Override | |||||
public void onDisConnected(String mac, int code) { | |||||
mList.add(0, "蓝牙已断开"); | |||||
mMHandler.sendEmptyMessage(ToRefreUi); | |||||
} | |||||
@Override | |||||
public void onServicesDiscovered(String mac) { | |||||
mList.add(0, "蓝牙已连接"); | |||||
mMHandler.sendEmptyMessage(ToRefreUi); | |||||
stopScanBle(); | |||||
BleDevice bleDevice = mBluetoothService.getBleDevice(mAddress); | |||||
if (bleDevice != null) { | |||||
ToothBrushBleUtilsData.init(bleDevice,this); | |||||
mToothBrushBleUtilsData =ToothBrushBleUtilsData.getInstance(); | |||||
mMHandler.sendEmptyMessageDelayed(ToRequestToken, 600); | |||||
mMHandler.sendEmptyMessageDelayed(GETBATTERY, 800); | |||||
} | |||||
} | |||||
@Override | |||||
public void bleOpen() { | |||||
} | |||||
@Override | |||||
public void bleClose() { | |||||
} | |||||
@Override | |||||
public void onClick(View v) { | |||||
int id = v.getId(); | |||||
if (mToothBrushBleUtilsData != null) | |||||
switch (id) { | |||||
case R.id.support_unit: | |||||
mToothBrushBleUtilsData.getSupportGears(); | |||||
break; | |||||
case R.id.default_mode: | |||||
String gear = select_gears_et.getText().toString().trim(); | |||||
if (!gear.isEmpty()) { | |||||
String[] gears = null; | |||||
if (gear.contains(",")) { | |||||
gears = gear.split(","); | |||||
} else if (gear.contains(",")) { | |||||
gears = gear.split(","); | |||||
} else { | |||||
Toast.makeText(this, "请输入时长,档位,档位级别(数字加符号)", Toast.LENGTH_SHORT).show(); | |||||
} | |||||
if (gears != null) { | |||||
try { | |||||
mToothBrushBleUtilsData.setDefault(Integer.parseInt(gears[0]), Integer.parseInt(gears[1]), Integer.parseInt(gears[2])); | |||||
} catch (Exception e) { | |||||
e.printStackTrace(); | |||||
Toast.makeText(this, "请输入时长,档位,档位级别(数字加符号)", Toast.LENGTH_SHORT).show(); | |||||
} | |||||
} | |||||
} | |||||
break; | |||||
case R.id.default_try_out: | |||||
String gear1 = select_gears_et.getText().toString().trim(); | |||||
if (!gear1.isEmpty()) { | |||||
String[] gears = null; | |||||
if (gear1.contains(",")) { | |||||
gears = gear1.split(","); | |||||
} else if (gear1.contains(",")) { | |||||
gears = gear1.split(","); | |||||
} else { | |||||
Toast.makeText(this, "请输入时长,档位,档位级别(数字加符号)", Toast.LENGTH_SHORT).show(); | |||||
} | |||||
if (gears != null) { | |||||
try { | |||||
mToothBrushBleUtilsData.setTryOut(Integer.parseInt(gears[1]), Integer.parseInt(gears[2]), 0, 0); | |||||
} catch (Exception e) { | |||||
e.printStackTrace(); | |||||
Toast.makeText(this, "请输入时长,档位,档位级别(数字加符号)", Toast.LENGTH_SHORT).show(); | |||||
} | |||||
} | |||||
} | |||||
break; | |||||
case R.id.default_time_mode: | |||||
mToothBrushBleUtilsData.getdefaultGearAndDuration(); | |||||
break; | |||||
} | |||||
} | |||||
private final int ToRefreUi = 300; | |||||
private final int ConnectWifi = 400; | |||||
private final int ToRequestToken = 500; | |||||
private final int GETBATTERY = 600; | |||||
@Override | |||||
public void onVersion(String version) { | |||||
mList.add(0, "版本号:" + version); | |||||
mMHandler.sendEmptyMessage(ToRefreUi); | |||||
} | |||||
@Override | |||||
public void onGetSupportGears(List<Integer> staif, List<Integer> secondLevel) { | |||||
mList.add(0, "牙刷支持的一级档位:" + Arrays.toString(staif.toArray()) + " 二级档位:" + Arrays.toString(secondLevel.toArray())); | |||||
mMHandler.sendEmptyMessage(ToRefreUi); | |||||
} | |||||
@Override | |||||
public void onGetBattery(int batteryStatus, int batteryQuantity) { | |||||
mList.add(0, "电池状态:" + batteryStatus + " 电量:" + batteryQuantity); | |||||
mMHandler.sendEmptyMessage(ToRefreUi); | |||||
} | |||||
@Override | |||||
public void onGetDefaultGearAndDuration(int time, int gear, int gearFrom) { | |||||
mList.add(0, "获得到默认的刷牙档位和时长:" + time + " 档位:" + gear + " 档位级别" + gearFrom); | |||||
mMHandler.sendEmptyMessage(ToRefreUi); | |||||
} | |||||
@Override | |||||
public void onGetTokenResult(int result) { | |||||
String s = ""; | |||||
if (result == ToothBrushBleCmd.NO_TOKEN) { | |||||
s = "没有"; | |||||
} else if (result == ToothBrushBleCmd.HAS_TOKEN) { | |||||
s = "已经授权"; | |||||
} else if (result == ToothBrushBleCmd.WITHOUT_TOKEN) { | |||||
s = "不需要授权"; | |||||
} else if (result == ToothBrushBleCmd.SUCCESSTOKEN) { | |||||
s = "授权成功"; | |||||
} | |||||
mList.add(0, "请求授权结果" + result + " " + s); | |||||
mMHandler.sendEmptyMessage(ToRefreUi); | |||||
} | |||||
@Override | |||||
public void onGetManualParameter(int time, int hz, int duty) { | |||||
mList.add(0, " 获取手动档位的参数: 时长" + time + " 频率" + hz + " 占空比" + duty); | |||||
mMHandler.sendEmptyMessage(ToRefreUi); | |||||
} | |||||
@Override | |||||
public void onSetDefaultModeAndManualModeResult(byte type, int result) { | |||||
String s = ""; | |||||
if (result == 0) { | |||||
s = "设置成功"; | |||||
} else if (result == 1) { | |||||
s = "设置失败"; | |||||
} else if (result == 2) { | |||||
s = "不支持设置"; | |||||
} | |||||
if (type == ToothBrushBleCmd.SET_TOOTHBRUSH_TIME_GEARS) { | |||||
mList.add(0, " 设置默认刷牙时长和工作档位: 结果" + result + " " + s); | |||||
mMHandler.sendEmptyMessage(ToRefreUi); | |||||
} else { | |||||
mList.add(0, " 设置手动设置(自定义)档位: 结果" + result + " " + s); | |||||
mMHandler.sendEmptyMessage(ToRefreUi); | |||||
} | |||||
} | |||||
@Override | |||||
public void onTestFinish(int totalTime, int leftTime, int rightTime, int mode, int battery) { | |||||
mList.add(0, "刷牙完成: 总时长:" + totalTime + " 左时长:" + leftTime + " 右时长:" + rightTime + " 模式:" + mode + " 电量:" + battery); | |||||
mMHandler.sendEmptyMessage(ToRefreUi); | |||||
} | |||||
@Override | |||||
public void onTryOutResult(int result) { | |||||
mList.add(0, "设置使用结果:" + result + " ( 0:设置成功 1:设置失败,原因未知 2:不支持设置)"); | |||||
mMHandler.sendEmptyMessage(ToRefreUi); | |||||
} | |||||
@Override | |||||
public void onTwoLevelModeDefault(int mode) { | |||||
mList.add(0, "获取二级档位默认值:" + mode); | |||||
mMHandler.sendEmptyMessage(ToRefreUi); | |||||
} | |||||
@Override | |||||
public void onShowData(String data) { | |||||
Log.e("蓝牙牙刷",data); | |||||
} | |||||
private class MHandler extends Handler { | |||||
@Override | |||||
public void handleMessage(Message msg) { | |||||
super.handleMessage(msg); | |||||
switch (msg.what) { | |||||
case ToRefreUi: | |||||
if (listAdapter != null) { | |||||
listAdapter.notifyDataSetChanged(); | |||||
} | |||||
break; | |||||
case ToRequestToken: | |||||
mList.add(0, "请求授权"); | |||||
mToothBrushBleUtilsData.requestToken(System.currentTimeMillis()); | |||||
if (listAdapter != null) { | |||||
listAdapter.notifyDataSetChanged(); | |||||
} | |||||
break; | |||||
case GETBATTERY: | |||||
mToothBrushBleUtilsData.getBattery(); | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
} |
package aicare.net.cn.sdk.ailinksdkdemoandroid; | |||||
import com.pingwang.bluetoothlib.device.BaseBleDeviceData; | |||||
import com.pingwang.bluetoothlib.device.BleDevice; | |||||
import com.pingwang.bluetoothlib.device.BleSendCmdUtil; | |||||
import com.pingwang.bluetoothlib.device.SendBleBean; | |||||
import com.pingwang.bluetoothlib.device.SendMcuBean; | |||||
import com.pingwang.bluetoothlib.listener.OnBleOtherDataListener; | |||||
import com.pingwang.bluetoothlib.listener.OnBleVersionListener; | |||||
import com.pingwang.bluetoothlib.listener.OnMcuParameterListener; | |||||
import com.pingwang.bluetoothlib.utils.BleStrUtils; | |||||
import java.lang.ref.WeakReference; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
import cn.net.aicare.modulelibrary.module.ToothBrush.ToothBrushBleCmd; | |||||
/** | |||||
* 如果在解析包中。找不到这个类。可以直接把代码复制过去 | |||||
* 如果有这个类。这个类只演示用 | |||||
*/ | |||||
public class ToothBrushBleUtilsData extends BaseBleDeviceData { | |||||
public final static int TOOTHBRUSH_BLE = 0x2d; | |||||
private BleDevice mBleDevice = null; | |||||
private volatile static ToothBrushBleUtilsData toothBrushBleUtilsData = null; | |||||
private ToothBrushBleUtilsData(BleDevice bleDevice, BleToothBrushCallback bleToothBrushCallback) { | |||||
super(bleDevice); | |||||
mBleDevice = bleDevice; | |||||
this.bleToothBrushCallback = bleToothBrushCallback; | |||||
mBleDevice.setOnBleVersionListener(new OnBleVersionListener() { | |||||
@Override | |||||
public void onBmVersion(String version) { | |||||
//蓝牙版本号 | |||||
if (bleToothBrushCallback != null) | |||||
bleToothBrushCallback.onVersion(version); | |||||
} | |||||
}); | |||||
bleDevice.setOnMcuParameterListener(new OnMcuParameterListener() { | |||||
@Override | |||||
public void onMcuBatteryStatus(int status, int battery) { | |||||
if (bleToothBrushCallback != null) | |||||
bleToothBrushCallback.onGetBattery(status, battery); | |||||
} | |||||
}); | |||||
mBleDevice.setOnBleOtherDataListener(new OnBleOtherDataListener() { | |||||
@Override | |||||
public void onNotifyOtherData(byte[] data) { | |||||
} | |||||
}); | |||||
} | |||||
public static ToothBrushBleUtilsData getInstance() { | |||||
return toothBrushBleUtilsData; | |||||
} | |||||
/** | |||||
* 初始化话 | |||||
* | |||||
* @param bleDevice 蓝牙操作类 | |||||
* @param bleCallback 蓝牙基础回调接口 | |||||
*/ | |||||
public static void init(BleDevice bleDevice, BleToothBrushCallback bleCallback) { | |||||
toothBrushBleUtilsData=null; | |||||
toothBrushBleUtilsData=new ToothBrushBleUtilsData(bleDevice,bleCallback); | |||||
} | |||||
/** | |||||
* 获取到蓝牙设备对象 | |||||
* | |||||
* @return 蓝牙设备 | |||||
*/ | |||||
public BleDevice getBleDevice() { | |||||
WeakReference weakReference = new WeakReference(mBleDevice); | |||||
return (BleDevice) weakReference.get(); | |||||
} | |||||
@Override | |||||
public void onNotifyData(byte[] bytes, int type) { | |||||
if (bleToothBrushCallback != null) | |||||
bleToothBrushCallback.onShowData("蓝牙返回的A7: " + BleStrUtils.byte2HexStr(bytes)); | |||||
switch (bytes[0]) { | |||||
case ToothBrushBleCmd.GET_TOOTHBRUSH_TIME_GEARS: | |||||
if (bytes.length >= 5) { | |||||
int highTime = (bytes[1] & 0xff) << 8; | |||||
int lowTime = bytes[2] & 0xff; | |||||
int gears = bytes[3] & 0xff; | |||||
int gearsfrom = bytes[4] & 0xff; | |||||
if (bleToothBrushCallback != null) | |||||
bleToothBrushCallback.onGetDefaultGearAndDuration(highTime + lowTime, gears, gearsfrom); | |||||
} | |||||
break; | |||||
case ToothBrushBleCmd.SET_TOOTHBRUSH_TIME_GEARS: | |||||
case ToothBrushBleCmd.Set_Manual_Mode: | |||||
if (bytes.length >= 2) { | |||||
if (bleToothBrushCallback != null) | |||||
bleToothBrushCallback.onSetDefaultModeAndManualModeResult(bytes[0], bytes[1] & 0xff); | |||||
} | |||||
break; | |||||
case ToothBrushBleCmd.Get_Manual_Mode: | |||||
if (bytes.length >= 7) { | |||||
int hzH = (bytes[2] & 0xff) << 8; | |||||
int hzl = bytes[3] & 0xff; | |||||
int duty = bytes[4] & 0xff; | |||||
int timeH = (bytes[5] & 0xff) << 8; | |||||
int timeL = bytes[6] & 0xff; | |||||
if (bleToothBrushCallback != null) { | |||||
bleToothBrushCallback.onGetManualParameter(timeH + timeL, hzH + hzl, duty); | |||||
} | |||||
} | |||||
break; | |||||
case (byte) ToothBrushBleCmd.Brush_Teeth_to_Complete: | |||||
if (bytes.length >= 9) { | |||||
int mode = bytes[1] & 0xff; | |||||
int timeH = (bytes[2] & 0xff) << 8; | |||||
int timeL = bytes[3] & 0xff; | |||||
int lTimeH = (bytes[4] & 0xff) << 8; | |||||
int lTimeL = bytes[5] & 0xff; | |||||
int rTimeH = (bytes[6] & 0xff) << 8; | |||||
int rTimeL = bytes[7] & 0xff; | |||||
int battery = bytes[8] & 0xff; | |||||
if (bleToothBrushCallback != null) { | |||||
bleToothBrushCallback.onTestFinish(timeH + timeL, lTimeH + lTimeL, rTimeH + rTimeL, mode, battery); | |||||
} | |||||
} | |||||
break; | |||||
case ToothBrushBleCmd.The_Trial_Order: | |||||
//试用指令 | |||||
if (bytes.length >= 2) | |||||
if (bleToothBrushCallback != null) { | |||||
bleToothBrushCallback.onTryOutResult(bytes[1] & 0xff); | |||||
} | |||||
break; | |||||
case ToothBrushBleCmd.Get_Second_GEARS: | |||||
if (bytes.length >= 2) | |||||
if (bleToothBrushCallback != null) { | |||||
bleToothBrushCallback.onTwoLevelModeDefault(bytes[1] & 0xff); | |||||
} | |||||
} | |||||
} | |||||
@Override | |||||
public void onNotifyDataA6(byte[] hex) { | |||||
if (bleToothBrushCallback != null) | |||||
bleToothBrushCallback.onShowData("蓝牙返回的A6: " + BleStrUtils.byte2HexStr(hex)); | |||||
switch (hex[0]) { | |||||
case (byte) ToothBrushBleCmd.GET_TOOTHBRUSH_GEARS: | |||||
disposeSupportGears(hex); | |||||
break; | |||||
case ToothBrushBleCmd.REQUEST_TOKEN: | |||||
int result = hex[1] & 0xff; | |||||
if (bleToothBrushCallback != null) { | |||||
bleToothBrushCallback.onGetTokenResult(result); | |||||
} | |||||
break; | |||||
} | |||||
} | |||||
private void disposeSupportGears(byte[] hex) { | |||||
if (hex.length > 4 && hex[1] == 0x01) { | |||||
int stair = hex[2] & 0xff; | |||||
int secondLevel = hex[3] & 0xff; | |||||
List<Integer> stairs = new ArrayList<>(); | |||||
List<Integer> secondLevels = new ArrayList<>(); | |||||
if (hex.length >= 4 + stair) { | |||||
for (int i = 0; i < stair; i++) { | |||||
stairs.add((int) hex[i + 4] & 0xff); | |||||
} | |||||
} | |||||
if (hex.length >= 4 + stair + secondLevel) { | |||||
for (int i = 0; i < secondLevel; i++) { | |||||
secondLevels.add((int) hex[i + 4 + stair] & 0xff); | |||||
} | |||||
} | |||||
if (bleToothBrushCallback != null) | |||||
bleToothBrushCallback.onGetSupportGears(stairs, secondLevels); | |||||
} | |||||
} | |||||
private BleToothBrushCallback bleToothBrushCallback; | |||||
public interface BleToothBrushCallback { | |||||
/** | |||||
* 版本号 | |||||
* version number | |||||
* | |||||
* @param Version | |||||
*/ | |||||
void onVersion(String Version); | |||||
/** | |||||
* 牙刷支持的档位 | |||||
* Gear supported by toothbrush | |||||
* | |||||
* @param staif 一级档位 First gear | |||||
* @param secondLevel 二级档位 Second gear | |||||
*/ | |||||
void onGetSupportGears(List<Integer> staif, List<Integer> secondLevel); | |||||
/** | |||||
* 获取电量 | |||||
* Get battery | |||||
* | |||||
* @param batteryStatus 电池充电状态 Battery charging status | |||||
* 0x00:没有充电(默认) 0x00: No charging (default) | |||||
* 0x01:充电中 0x01: Charging | |||||
* 0x02:充满电 0x02: Fully charged | |||||
* 0x03:充电异常 0x03: abnormal charging | |||||
* @param batteryQuantity 电池电量百分比 (0—100) Battery power percentage (0-100) | |||||
*/ | |||||
void onGetBattery(int batteryStatus, int batteryQuantity); | |||||
/** | |||||
* 获得到默认的刷牙档位和时长 | |||||
* Get the default brushing position and duration | |||||
* | |||||
* @param time 刷牙时长 Brushing time | |||||
* @param gear 刷牙档位 Brushing gear | |||||
* @param gearFrom 刷牙档位级别 Brushing gear level | |||||
*/ | |||||
void onGetDefaultGearAndDuration(int time, int gear, int gearFrom); | |||||
/** | |||||
* 请求授权的回调 | |||||
* Callback to request authorization | |||||
* | |||||
* @param result 0:没有 1:已经授权 2:不需要授权 3:授权成功 {@link ToothBrushBleCmd#NO_TOKEN} | |||||
*/ | |||||
void onGetTokenResult(int result); | |||||
/** | |||||
* 获取手动档位的参数 | |||||
* Get the parameters of manual gear | |||||
* | |||||
* @param time 时长 duration | |||||
* @param hz 频率 frequency | |||||
* @param duty 占空比 Duty cycle | |||||
*/ | |||||
void onGetManualParameter(int time, int hz, int duty); | |||||
/** | |||||
* 设置默认档位和手动模式结果回调 | |||||
* | |||||
* @param type 类型 {@link ToothBrushBleCmd#SET_TOOTHBRUSH_TIME_GEARS, ToothBrushBleCmd#Set_Manual_Mode} | |||||
* @param result 0:设置成功 1:设置失败 2:不支持设置 | |||||
*/ | |||||
void onSetDefaultModeAndManualModeResult(byte type, int result); | |||||
/** | |||||
* 刷牙完成 | |||||
* Brushing is done | |||||
* | |||||
* @param totalTime 刷牙总时长 Total brushing time | |||||
* @param leftTime 左边刷牙时间 Brushing time on the left | |||||
* @param rightTime 右边刷牙时间 Brushing time on the right | |||||
* @param mode 刷牙模式 Brushing mode | |||||
* @param battery 电量 Power | |||||
*/ | |||||
void onTestFinish(int totalTime, int leftTime, int rightTime, int mode, int battery); | |||||
/** | |||||
* 试用回调 | |||||
* Trial callback | |||||
* | |||||
* @param result 0:设置成功 0: Setting is successful | |||||
* 1:设置失败,原因未知 1: Setting fails, the reason is unknown | |||||
* 2:不支持设置 2: Setting is not supported | |||||
*/ | |||||
void onTryOutResult(int result); | |||||
/** | |||||
* 获取二级档位默认值 | |||||
* Get the default value of the second gear | |||||
* | |||||
* @param mode 0x00:不支持 0x00: not supported | |||||
* 0x01-0xfe:工作档位编号 0x01-0xfe: working gear number | |||||
* 0xFF:手动设置档位 0xFF: manual setting of gear | |||||
*/ | |||||
void onTwoLevelModeDefault(int mode); | |||||
/** | |||||
* 蓝牙返回的数据 | |||||
* Data returned by Bluetooth | |||||
* | |||||
* @param data | |||||
*/ | |||||
void onShowData(String data); | |||||
} | |||||
/** | |||||
* 获取支持的单位 A6指令 | |||||
* Supported unit | |||||
*/ | |||||
public void getSupportGears() { | |||||
byte[] bytes = new byte[2]; | |||||
bytes[0] = ToothBrushBleCmd.GET_TOOTHBRUSH_GEARS; | |||||
bytes[1] = 0x01; | |||||
sendA6(bytes); | |||||
} | |||||
/** | |||||
* 获取到电量 | |||||
* Get power | |||||
*/ | |||||
public void getBattery() { | |||||
sendA6(BleSendCmdUtil.getInstance().getMcuBatteryStatus()); | |||||
} | |||||
/** | |||||
* 获取默认模式和时长 | |||||
* Get the default mode and duration | |||||
*/ | |||||
public void getdefaultGearAndDuration() { | |||||
byte[] bytes = new byte[1]; | |||||
bytes[0] = ToothBrushBleCmd.GET_TOOTHBRUSH_TIME_GEARS; | |||||
sendA7(bytes); | |||||
} | |||||
public void setOta() { | |||||
// 91 01 | |||||
byte[] bytes = new byte[2]; | |||||
bytes[0] = (byte) 0x91; | |||||
bytes[1] = 0x01; | |||||
sendA6(bytes); | |||||
} | |||||
/** | |||||
* 发起连接 | |||||
* Initiate connection | |||||
* | |||||
* @return | |||||
*/ | |||||
public void connectWifi() { | |||||
byte[] bytes = new byte[2]; | |||||
bytes[0] = (byte) 0x88; | |||||
bytes[1] = 0x01; | |||||
sendA6(bytes); | |||||
} | |||||
/** | |||||
* 设置试用 | |||||
* Set up trial | |||||
*/ | |||||
public void setTryOut(int id, int level, int hz, int duty) { | |||||
byte[] bytes = new byte[14]; | |||||
bytes[0] = ToothBrushBleCmd.The_Trial_Order; | |||||
bytes[1] = (byte) id; | |||||
bytes[2] = (byte) level; | |||||
bytes[3] = (byte) 0xff; | |||||
bytes[4] = (byte) (hz >> 8); | |||||
bytes[5] = (byte) hz; | |||||
bytes[6] = (byte) duty; | |||||
bytes[7] = (byte) 0; | |||||
bytes[8] = (byte) 0; | |||||
bytes[9] = (byte) 0; | |||||
bytes[10] = (byte) 0; | |||||
bytes[11] = (byte) 0; | |||||
bytes[12] = (byte) 0; | |||||
bytes[13] = (byte) 0; | |||||
sendA7(bytes); | |||||
} | |||||
/** | |||||
* 设置默认 | |||||
* Set the default | |||||
*/ | |||||
public void setDefault(int time, int mode, int level) { | |||||
byte[] bytes = new byte[5]; | |||||
bytes[0] = ToothBrushBleCmd.SET_TOOTHBRUSH_TIME_GEARS; | |||||
bytes[1] = (byte) (time >> 8); | |||||
bytes[2] = (byte) time; | |||||
bytes[3] = (byte) mode; | |||||
bytes[4] = (byte) level; | |||||
sendA7(bytes); | |||||
} | |||||
/** | |||||
* 下发数据上报成功 | |||||
* Successfully sent data and reported | |||||
*/ | |||||
public void testFinishSuccess() { | |||||
byte[] bytes = new byte[2]; | |||||
bytes[0] = (byte) ToothBrushBleCmd.Issue_Data_Report_Completed; | |||||
bytes[1] = 0x01; | |||||
sendA7(bytes); | |||||
} | |||||
/** | |||||
* APP 设置二级档位默认值 | |||||
* Set the default value of the second gear | |||||
*/ | |||||
public void setTwoLevelDefault(int modeId) { | |||||
byte[] bytes = new byte[2]; | |||||
bytes[0] = ToothBrushBleCmd.Set_Second_GEARS; | |||||
bytes[1] = (byte) modeId; | |||||
sendA7(bytes); | |||||
} | |||||
/** | |||||
* APP 获取二级档位默认值 | |||||
*/ | |||||
public void getTwoLevelDefault() { | |||||
byte[] bytes = new byte[1]; | |||||
bytes[0] = ToothBrushBleCmd.Get_Second_GEARS; | |||||
sendA7(bytes); | |||||
} | |||||
/** | |||||
* 开始刷牙 | |||||
* Get the default value of the second gear | |||||
*/ | |||||
public void starTooth() { | |||||
byte[] bytes = new byte[1]; | |||||
bytes[0] = ToothBrushBleCmd.Start_Close_ToothBrush; | |||||
sendA7(bytes); | |||||
} | |||||
/** | |||||
* 设置手动模式的参数 | |||||
* Set the parameters of manual mode | |||||
*/ | |||||
public void setManualParameter(int hz, int duty, int time) { | |||||
byte[] bytes = new byte[7]; | |||||
bytes[0] = ToothBrushBleCmd.Set_Manual_Mode; | |||||
bytes[1] = 0x00; | |||||
bytes[2] = (byte) (hz >> 8); | |||||
bytes[3] = (byte) hz; | |||||
bytes[4] = (byte) duty; | |||||
bytes[5] = (byte) (time >> 8); | |||||
bytes[6] = (byte) time; | |||||
sendA7(bytes); | |||||
} | |||||
/** | |||||
* 获取手动模式的参数 | |||||
* Get the parameters of manual mode | |||||
*/ | |||||
public void getManualParameter() { | |||||
byte[] bytes = new byte[1]; | |||||
bytes[0] = ToothBrushBleCmd.Get_Manual_Mode; | |||||
sendA7(bytes); | |||||
} | |||||
/** | |||||
* APP 请求授权 Payload | |||||
* Request authorization | |||||
* | |||||
* @param toothbrushId 时间搓 | |||||
*/ | |||||
public void requestToken(long toothbrushId) { | |||||
byte[] timebyte = long2Bytes(toothbrushId); //long 长度8 byte 时间搓是6个byte 所以去后面6位 | |||||
byte[] bytes = new byte[7]; | |||||
bytes[0] = ToothBrushBleCmd.REQUEST_TOKEN; | |||||
bytes[1] = timebyte[2]; | |||||
bytes[2] = timebyte[3]; | |||||
bytes[3] = timebyte[4]; | |||||
bytes[4] = timebyte[5]; | |||||
bytes[5] = timebyte[6]; | |||||
bytes[6] = timebyte[7]; | |||||
sendA6(bytes); | |||||
} | |||||
private byte[] long2Bytes(long num) { | |||||
byte[] byteNum = new byte[8]; | |||||
for (int ix = 0; ix < 8; ++ix) { | |||||
int offset = 64 - (ix + 1) * 8; | |||||
byteNum[ix] = (byte) ((num >> offset) & 0xff); | |||||
} | |||||
return byteNum; | |||||
} | |||||
private SendBleBean sendBleBean; | |||||
/** | |||||
* 发送A6指令 | |||||
* | |||||
* @param bytes | |||||
*/ | |||||
public void sendA6(byte[] bytes) { | |||||
if (sendBleBean == null) | |||||
sendBleBean = new SendBleBean(); | |||||
sendBleBean.setHex(bytes); | |||||
sendData(sendBleBean); | |||||
} | |||||
/** | |||||
* 断开连接 | |||||
* Disconnect | |||||
* | |||||
* @return SendBleBean | |||||
*/ | |||||
public void disconnectWifi() { | |||||
byte[] bytes = new byte[2]; | |||||
bytes[0] = (byte) 0x88; | |||||
bytes[1] = 0x00; | |||||
sendA6(bytes); | |||||
} | |||||
/** | |||||
* 发送A7指令 | |||||
* | |||||
* @param bytes | |||||
*/ | |||||
public void sendA7(byte[] bytes) { | |||||
SendMcuBean sendMcuBean = new SendMcuBean(); | |||||
sendMcuBean.setHex(TOOTHBRUSH_BLE, bytes); | |||||
sendData(sendMcuBean); | |||||
} | |||||
} |
package aicare.net.cn.sdk.ailinksdkdemoandroid; | package aicare.net.cn.sdk.ailinksdkdemoandroid; | ||||
import android.content.Intent; | |||||
import android.content.pm.ActivityInfo; | import android.content.pm.ActivityInfo; | ||||
import android.os.Bundle; | import android.os.Bundle; | ||||
import android.os.Handler; | import android.os.Handler; | ||||
public class ToothBrushWifiBleActivity extends BleBaseActivity implements View.OnClickListener, OnCallbackBle, ToothBrushWiFiBleUtilsData.BleToothBrushWiFiCallback, ToothBrushWiFiBleUtilsData.BleToothBrushCallback { | public class ToothBrushWifiBleActivity extends BleBaseActivity implements View.OnClickListener, OnCallbackBle, ToothBrushWiFiBleUtilsData.BleToothBrushWiFiCallback, ToothBrushWiFiBleUtilsData.BleToothBrushCallback { | ||||
private String TAG = ToothBrushWifiBleActivity.class.getName(); | private String TAG = ToothBrushWifiBleActivity.class.getName(); | ||||
private String mAddress; | private String mAddress; | ||||
private List<String> mList; | private List<String> mList; | ||||
private ArrayAdapter listAdapter; | private ArrayAdapter listAdapter; | ||||
} | } | ||||
@Override | |||||
protected void onNewIntent(Intent intent) { | |||||
super.onNewIntent(intent); | |||||
setIntent(intent); | |||||
} | |||||
@Override | @Override | ||||
public void onServiceSuccess() { | public void onServiceSuccess() { | ||||
mBluetoothService.setOnCallback(this); | mBluetoothService.setOnCallback(this); | ||||
BleDevice bleDevice = mBluetoothService.getBleDevice(mAddress); | BleDevice bleDevice = mBluetoothService.getBleDevice(mAddress); | ||||
if (bleDevice != null) { | if (bleDevice != null) { | ||||
ToothBrushWiFiBleUtilsData.init(bleDevice, this, this); | ToothBrushWiFiBleUtilsData.init(bleDevice, this, this); | ||||
mToothBrushWiFiBleUtilsData = ToothBrushWiFiBleUtilsData.getInstance(); | mToothBrushWiFiBleUtilsData = ToothBrushWiFiBleUtilsData.getInstance(); | ||||
mMHandler.sendEmptyMessageDelayed(ToRequestToken, 600); | mMHandler.sendEmptyMessageDelayed(ToRequestToken, 600); | ||||
if (gears != null) { | if (gears != null) { | ||||
try { | try { | ||||
mToothBrushWiFiBleUtilsData.setTryOut(Integer.parseInt(gears[1]), Integer.parseInt(gears[2]), 0, 0); | mToothBrushWiFiBleUtilsData.setTryOut(Integer.parseInt(gears[1]), Integer.parseInt(gears[2]), 0, 0); | ||||
} catch (NumberFormatException e) { | |||||
} catch (Exception e) { | |||||
e.printStackTrace(); | e.printStackTrace(); | ||||
Toast.makeText(this, "请输入时长,档位,档位级别(数字加符号)", Toast.LENGTH_SHORT).show(); | Toast.makeText(this, "请输入时长,档位,档位级别(数字加符号)", Toast.LENGTH_SHORT).show(); | ||||
} | } |
*/ | */ | ||||
public final static int TOOTHBRUSH_WIFI_BLE=0x12; | public final static int TOOTHBRUSH_WIFI_BLE=0x12; | ||||
/** | |||||
* 蓝牙牙刷 | |||||
*/ | |||||
public final static int TOOTHBRUSH_BLE = 0x2D; | |||||
/** | /** | ||||
* 八电极体脂秤 | * 八电极体脂秤 | ||||
*/ | */ | ||||
*/ | */ | ||||
public final static int BROADCAST_NUTRITION = 0x10003; | public final static int BROADCAST_NUTRITION = 0x10003; | ||||
} | } |
android:layout_width="wrap_content" | android:layout_width="wrap_content" | ||||
android:layout_height="wrap_content" | android:layout_height="wrap_content" | ||||
android:text="口罩" /> | android:text="口罩" /> | ||||
<Button | |||||
android:id="@+id/btn_toothbrush_ble" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:text="蓝牙牙刷" /> | |||||
</LinearLayout> | </LinearLayout> | ||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<RelativeLayout | |||||
xmlns:android="http://schemas.android.com/apk/res/android" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="match_parent" | |||||
android:orientation="vertical"> | |||||
<Button | |||||
android:id="@+id/default_try_out" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_marginTop="5dp" | |||||
android:text="试用" /> | |||||
<Button | |||||
android:id="@+id/default_mode" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_below="@+id/sn" | |||||
android:layout_toEndOf="@id/default_try_out" | |||||
android:layout_marginStart="9dp" | |||||
android:layout_marginTop="5dp" | |||||
android:text="默认档位" /> | |||||
<EditText | |||||
android:id="@+id/select_gears_et" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_alignTop="@id/default_mode" | |||||
android:layout_toEndOf="@id/default_mode" | |||||
android:hint="时长(s),档位,档位级别" | |||||
android:textSize="14dp" /> | |||||
<Button | |||||
android:id="@+id/support_unit" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_below="@+id/default_mode" | |||||
android:layout_marginTop="5dp" | |||||
android:text="获取支持档位" /> | |||||
<Button | |||||
android:id="@+id/default_time_mode" | |||||
android:layout_width="wrap_content" | |||||
android:layout_height="wrap_content" | |||||
android:layout_toEndOf="@id/support_unit" | |||||
android:layout_below="@+id/default_mode" | |||||
android:layout_marginTop="5dp" | |||||
android:text="获取时长和档位" /> | |||||
<ListView | |||||
android:id="@+id/log_list" | |||||
android:layout_marginTop="10dp" | |||||
android:layout_below="@id/default_time_mode" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="match_parent"> | |||||
</ListView> | |||||
</RelativeLayout> |
<?xml version="1.0" encoding="utf-8"?> | |||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="match_parent" | |||||
android:orientation="vertical"> | |||||
<androidx.recyclerview.widget.RecyclerView | |||||
android:id="@+id/recycler_view" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="match_parent" /> | |||||
</LinearLayout> |
<?xml version="1.0" encoding="utf-8"?> | |||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||||
xmlns:tools="http://schemas.android.com/tools" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="wrap_content" | |||||
android:minHeight="50dp" | |||||
android:orientation="vertical"> | |||||
<LinearLayout | |||||
android:layout_width="match_parent" | |||||
android:layout_height="0dp" | |||||
android:layout_weight="1" | |||||
android:orientation="horizontal"> | |||||
<TextView | |||||
android:id="@+id/tv_title" | |||||
android:layout_width="0dp" | |||||
android:layout_height="match_parent" | |||||
android:layout_marginStart="15dp" | |||||
android:layout_weight="1" | |||||
android:ellipsize="end" | |||||
android:gravity="center_vertical" | |||||
android:textColor="@android:color/black" | |||||
tools:text="请求授权" /> | |||||
<TextView | |||||
android:id="@+id/tv_result" | |||||
android:layout_width="50dp" | |||||
android:layout_height="match_parent" | |||||
android:gravity="center" | |||||
android:textColor="@android:color/holo_blue_dark" | |||||
tools:text="OK" /> | |||||
</LinearLayout> | |||||
<View | |||||
android:layout_width="match_parent" | |||||
android:layout_height="1dp" | |||||
android:background="?android:attr/listDivider" /> | |||||
</LinearLayout> |
<?xml version="1.0" encoding="utf-8"?> | |||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||||
xmlns:tools="http://schemas.android.com/tools" | |||||
android:layout_width="match_parent" | |||||
android:layout_height="25dp" | |||||
android:background="@android:color/holo_orange_light" | |||||
android:orientation="vertical"> | |||||
<LinearLayout | |||||
android:layout_width="match_parent" | |||||
android:layout_height="0dp" | |||||
android:layout_weight="1" | |||||
android:orientation="horizontal"> | |||||
<TextView | |||||
android:id="@+id/tv_title" | |||||
android:layout_width="0dp" | |||||
android:layout_height="match_parent" | |||||
android:layout_marginStart="15dp" | |||||
android:layout_weight="1" | |||||
android:ellipsize="end" | |||||
android:gravity="center_vertical" | |||||
android:maxLines="2" | |||||
android:textColor="@android:color/black" | |||||
tools:text="自动测试" /> | |||||
</LinearLayout> | |||||
</LinearLayout> |