# mijiaSDK
**Repository Path**: xiaowei-sauce/mijiaSDK
## Basic Information
- **Project Name**: mijiaSDK
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: dev
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 2
- **Created**: 2025-09-08
- **Last Updated**: 2025-09-08
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# mijiaSDK文档
---
## 目的
本文档为接入mijiaSDK的第三方开发者提供开发独立App的指导。
## 前提条件
在进行独立App开发前,您需要
- 了解产品功能描述、产品Model等相关概念 [小米智能硬件开放平台](https://open.home.mi.com/resource.html#/summarize)
- 完成产品登记,并完成固件调试 [产品登记](https://open.home.mi.com/develop.html#/product)
- 了解Android开发、上线等一系列流程 [安卓开发](http://developer.android.com/)
- 完成小米开发者账号的注册和资质认证 [小米开放平台](https://dev.mi.com/console/)
## 基础准备
在您正式进行产品接入前,需要首先完成一下准备工作
### 1. 帐号接入
mijiaSDK目前支持小米帐号登陆,开发者需要到[小米帐号开放平台](http://dev.xiaomi.com/)注册自己的App信息,**并在小米帐号系统Oauth权限管理中,申请并审核通过“智能家庭服务”权限,请确保申请通过此权限,否则不能正常使用**。如果在接入过程中遇到问题,可加QQ群385428920咨询。然后下载[小米帐号最新版SDK](https://github.com/xiaomipassport/oauth-Android-sdk),并集成到自己应用中。
### 2. 消息推送
mijiaSDK中集成有Mipush,目前主要是用于订阅设备事件。App使用前,开发者需要到[小米消息推送服务](http://dev.xiaomi.com/doc/?page_id=1670)注册自己的App信息。
还需将信息注册到智能家居后台。注册方式:请将注册信息发送到haojianxiu@xiaomi.com
注册信息示例:
```
IOS App 信息:
Bundle ID:xxx
AppID: xxx
AppKey: xxx
AppSecret:xxx
Android App信息:
packageName:xxx
AppID: xxx
AppKey: xxx
AppSecret: xxx
```
### 3. 注册AppId,AppKey以及设备信息
将应用注册到小米帐号时,会生成相关的AppId和Appkey,需要将这部分信息注册到智能家居后台,否则会返回错误"app_id is null"。
请将AppId及所属公司名称发送到haojianxiu@xiaomi.com进行注册。
## 产品接入
### 1. 云端配置产品信息
将应用需要支持的设备信息注册到智能家居后台。
### 2. 撰写设备功能描述文档
首先,这里简述一下MiotDevice的模型,一个Device包含一个或者多个Service,此处的Service代表设备的一种能力,一个具体的设备可能有多种能力。一个Service包含一系列property,action:
* property表示该service当前状态,property具有名称,数据类型,默认值,以及其值改变时是否触发事件
* action表示service可以控制的动作
撰写一份xml格式的设备功能描述文档,用于描述设备具体功能,可以参考demo中附带的ddd_SmartSocket.xml(小米智能插座)以及ddd_AuxAircondition.xml(奥克斯空调)。
### 3. 生成设备代码
撰写完设备功能描述文档后,使用提供的脚本codegenerator.jar,运行如下命令
```
java -jar codegenerator.jar src/main/assets/ddd_SmartSocket.xml
```
运行时将最后一个变量替换为自己xml文档的相对路径,运行成功后将生成SmartSocketBase.java以及SmartSocketBaseService.java两个文件(生成文件数量与xml中定义的service数量有关)
## 使用SDK开发App
接下来将简要介绍如何配置和使用mijiaSDK开发自己的App,也可以参考其中的demo。
### 1. 配置AndroidManifest.xml
* mijiaSDK支持的最低android版本
```xml
```
* mijiaSDK需要的权限列表
```xml
```
### 2. 初始化SDK
这里简单描述如何初始化mijiaSDK,可以参考demo中TestApplication.java
* 首先初始化MiotManager:
```Java
MiotManager.getInstance().initialize(getApplicationContext());
```
* 然后将小米帐号处的AppId,AppKey设置到SDK中:
```Java
AppConfiguration appConfig = new AppConfiguration();
appConfig.setAppId(AppConfig.APP_ID);
appConfig.setAppKey(AppConfig.APP_KEY);
MiotManager.getInstance().setAppConfig(appConfig);
```
* 接着将App需要处理的设备配置到SDK中:
```Java
try {
DeviceModel plug = DeviceModelFactory.createDeviceModel(TestApplication.this,
TestConstants.CHUANGMI_PLUG_M1,
TestConstants.CHUANGMI_PLUG_M1_URL,
ChuangmiPlugM1.class);
MiotManager.getInstance().addModel(plug);
} catch (DeviceModelException e) {
e.printStackTrace();
}
```
方法createDeviceModel中的参数依次为:context;model:云端注册的设备model;url:xml格式的profile文档,需要放到项目assets目录下;clazz(Class>):之前生成的设备代码的class
* 最后bindService:
```Java
MiotManager.getInstance().open();
```
如果返回值为0,则为绑定成功。退出应用时需要unBind:
```Java
MiotManager.getInstance().close()
```
同上,返回值为0,则为解绑成功
* 将用户信息保存到Service中,可以参考demo中AccountActivity.java
```Java
private void processAuthResult(XiaomiOAuthResults results) {
String accessToken = results.getAccessToken();
String expiresIn = results.getExpiresIn();
String scope = results.getScopes();
String state = results.getState();
String tokenType = results.getTokenType();
String macKey = results.getMacKey();
String macAlgorithm = results.getMacAlgorithm();
...
new XiaomiAccountGetPeopleInfoTask(accessToken, expiresIn, macKey, macAlgorithm,
new XiaomiAccountGetPeopleInfoTask.Handler() {
@Override
public void onSucceed(People people) {
Log.d(TAG, "XiaomiAccountGetPeopleInfoTask OK");
try {
MiotManager.getPeopleManager().savePeople(people);
initUserInfo();
} catch (MiotException e) {
e.printStackTrace();
}
}
@Override
public void onFailed() {
Log.d(TAG, "XiaomiAccountGetPeopleInfoTask Failed");
}
}).execute();
}
```
### 3. 开发设备相关功能
SDK目前提供了如下功能:
1. **获取设备列表**:获取设备
2. **快连设备**:用于将新设备联网,也就是快连(目前快连默认完成绑定设备)
3. **绑定设备**: 完成设备与用户的帐号绑定关系
4. **解绑设备**:允许用户解除与设备的绑定关系
5. **分享设备**:用户可以将设备分享给其他人(目前仅小米帐号)
6. **控制设备**:包括获取设备状态、下发指令和订阅设备事件
目前这些操作的log信息是默认打开的,可以通过一下接口关闭log信息
```Java
miot.service.common.utils.Logger.enableLog(true);
```
#### 获取设备列表
调用DeviceManager中的设备发现接口,可以参考demo中MiDeviceManager.java相关代码
```Java
try {
MiotManager.getDeviceManager().getRemoteDeviceList(new DeviceManager.DeviceHandler() {
@Override
public void onSucceed(List devices) {
//TODO
}
@Override
public void onFailed(int errCode, String description) {
//TODO
}
});
} catch (MiotException e) {
e.printStackTrace();
}
```
#### 快连设备
* 发现待连接设备
调用DeviceManager中的设备扫描接口,可以参考demo中MiDeviceManager.java相关代码
```Java
List types = new ArrayList<>();
types.add(DiscoveryType.MIOT_WIFI);
try {
MiotManager.getDeviceManager().startScan(types, new DeviceManager.DeviceHandler() {
@Override
public void onSucceed(List devices) {
//TODO
}
@Override
public void onFailed(int errCode, String description) {
//TODO
});
} catch (MiotException e) {
e.printStackTrace();
}
```
需要注意的是,Android6.0加入运行时权限,扫描Wifi设备需要运行时权限的支持,关于运行时权限,详见[google文档](https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html?hl=zh-cn#behavior-runtime-permissions),demo中有一个简单的示例,代码如下所示:
```Java
private static final int REQUEST_LOCATION_PERMISSION = 10000;
@TargetApi(23)
private boolean hasPermission() {
return Build.VERSION.SDK_INT < 23 ||
ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
@TargetApi(23)
private void requestPermission() {
if (Build.VERSION.SDK_INT < 23) {
return;
}
String[] permissions = new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
};
ActivityCompat.requestPermissions(this, permissions, REQUEST_LOCATION_PERMISSION);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_LOCATION_PERMISSION:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
MiDeviceManager.getInstance().startScan();
} else {
Log.e(TAG, "no permission to scan device");
}
}
}
```
* 配置快连图标和文案:将快连图标放置到自己工程的res/drawable-xxhdpi目录下,并命名为kuailian_miio_icon.png。在strings.xml文件添加
```xml
(文案)
```
* 快连设备,获取到设备列表后,如果设备是待连接的设备,可以调用以下方法连接到云端,具体可以参考demo中DeviceActivity.class:
```Java
private void connectDevice(AbstractDevice device) {
try {
MiotManager.getDeviceConnector().connectToCloud(device, new CompletionHandler() {
@Override
public void onSucceed() {
Logger.d(TAG, "connect device onSucceed");
}
@Override
public void onFailed(int errCode, String description) {
Logger.e(TAG, "connect device onFailed: " + errCode + description);
}
});
} catch (MiotException e) {
e.printStackTrace();
}
}
```
#### 绑定设备
绑定设备,即为将设备绑定到一个用户帐号下,只能用于未绑定的广域网设备(目前快连过程中会默认绑定设备)
```Java
try {
MiotManager.getDeviceManager().takeOwnership(abstractDevice, new CompletionHandler() {
@Override
public void onSucceed() {
Logger.d(TAG, "takeOwnership onSucceed");
}
@Override
public void onFailed(int errCode, String description) {
Logger.e(TAG, "takeOwnership onFialed: " + errCode + " " + description);
}
});
} catch (MiotException e) {
e.printStackTrace();
}
```
#### 解绑设备
解绑设备,即为从用户名下删除该设备,并重置该设备
```Java
try {
MiotManager.getDeviceManager().disclaimOwnership(abstractDevice, new CompletionHandler() {
@Override
public void onSucceed() {
Logger.d(TAG, "disclaimOwnership onSucceed");
}
@Override
public void onFailed(int errCode, String description) {
Logger.e(TAG, "disclaimOwnership onFialed: " + errCode + " " + description);
}
});
} catch (MiotException e) {
e.printStackTrace();
}
```
#### 分享设备
* 将设备分享给其他人
```Java
try {
MiotManager.getDeviceManager().shareDevice(mAbstractDevice, userId, new CompletionHandler() {
@Override
public void onSucceed() {
Logger.d(TAG, "shareDevice onSucceed");
}
@Override
public void onFailed(int errCode, String description) {
Logger.e(TAG, "shareDevice onFailed: " + errCode + " " + description);
}
});
} catch (MiotException e) {
e.printStackTrace();
}
```
其中userId为用户小米帐号ID。
* 取消分享
```Java
try {
MiotManager.getDeviceManager().cancelShare(mAbstractDevice, userId, new CompletionHandler() {
@Override
public void onSucceed() {
Logger.d(TAG, "cancelShare onSucceed");
}
@Override
public void onFailed(int errCode, String description) {
Logger.e(TAG, "cancelShare onFailed: " + errCode + " " + description);
}
});
} catch (MiotException e) {
e.printStackTrace();
}
```
* 查看设备被分享用户列表
```Java
try {
MiotManager.getDeviceManager().querySharedUsers(mAbstractDevice, new CommonHandler>() {
@Override
public void onSucceed(List result) {
Logger.d(TAG, "querySharedUsers onSucceed");
...
}
@Override
public void onFailed(int errCode, String description) {
Logger.e(TAG, "querySharedUsers onFailed: " + errCode + " " + description);
}
});
} catch (MiotException e) {
e.printStackTrace();
}
```
* 被分享者查看设备分享邀请
```Java
try {
MiotManager.getDeviceManager().querySharedRequests(new CommonHandler>() {
@Override
public void onSucceed(List result) {
Logger.d(TAG, "querySharedRequests onSucceed");
...
}
@Override
public void onFailed(int errCode, String description) {
Logger.e(TAG, "querySharedRequests: " + errCode + description);
}
});
} catch (MiotException e) {
e.printStackTrace();
}
```
* 接受或者拒绝设备分享邀请
```Java
sharedRequest.setShareStatus(ShareStatus.accept);
try {
MiotManager.getDeviceManager().replySharedRequest(sharedRequest, new CompletionHandler() {
@Override
public void onSucceed() {
Logger.d(TAG, "replySharedRequest onSucceed");
}
@Override
public void onFailed(int errCode, String description) {
Logger.e(TAG, "replySharedRequest: " + errCode + description);
}
});
} catch (MiotException e) {
e.printStackTrace();
}
```
其中ShareStatus中accept为接受邀请,reject为拒绝邀请。
#### 控制设备
这里以小米插座为例,简要说明一下,具体可以参见demo中PlugActivity
* 获取设备状态
```Java
public void getProperties() {
try {
mBaseService.getProperties(new PlugBaseService.GetPropertiesCompletionHandler() {
@Override
public void onSucceed(final PlugBaseService.Power power, final PlugBaseService.WifiLed wifiLed, final Integer temperature) {
show("getProperties", String.format("Power=%s WifiLed=%s Temperature=%s", power, wifiLed, temperature));
mHandler.post(new Runnable() {
@Override
public void run() {
tvPower.setText(String.valueOf(power));
tvWifiLed.setText(String.valueOf(wifiLed));
tvTemperature.setText(String.valueOf(temperature));
}
});
}
@Override
public void onFailed(int errCode, String description) {
show("getProperties", String.format("Failed, code: %d %s", errCode, description));
}
});
} catch (MiotException e) {
e.printStackTrace();
}
}
```
* 下发命令
```Java
public void setPower() {
try {
PlugBaseService.Power power = PlugBaseService.Power.on;
mBaseService.setPower(power, new CompletionHandler() {
@Override
public void onSucceed() {
show("setPower", "OK");
}
@Override
public void onFailed(int errCode, String description) {
show("setPower", String.format("Failed, code: %d %s", errCode, description));
}
});
} catch (MiotException e) {
e.printStackTrace();
}
}
```
* 订阅状态变化
需要注意的是订阅部分使用的是MiPush的服务,其与应用包名绑定。
```Java
public void subscribeNotification() {
try {
mBaseService.subscribeNotifications(new CompletionHandler() {
@Override
public void onSucceed() {
show("subscribe", "OK");
}
@Override
public void onFailed(int errCode, String description) {
show("subscribe", String.format("Failed, code: %d %s", errCode, description));
}
}, new PlugBaseService.PropertyNotificationListener() {
@Override
public void onPowerChanged(final PlugBaseService.Power power) {
show("onPowerChanged: ", String.valueOf(power));
mHandler.post(new Runnable() {
@Override
public void run() {
tvPower.setText(String.valueOf(power));
}
});
}
@Override
public void onWifiLedChanged(final PlugBaseService.WifiLed wifiLed) {
show("onWifiLedChanged: ", String.valueOf(wifiLed));
mHandler.post(new Runnable() {
@Override
public void run() {
tvWifiLed.setText(String.valueOf(wifiLed));
}
});
}
@Override
public void onTemperatureChanged(final Integer temperature) {
show("onWifiLedChanged: ", String.valueOf(temperature));
mHandler.post(new Runnable() {
@Override
public void run() {
tvTemperature.setText(String.valueOf(temperature));
}
});
}
});
} catch (MiotException e) {
e.printStackTrace();
}
}
```
* 局域网控制
局域网控制是默认打开的,可以通过通过下面接口进行关闭
```Java
MiotManager.getDeviceManipulator().enableLanCtrl(false);
```
### 4. Mipush
目前,智能家庭后台的push消息格式是这样:{type:****, body: *****},其中type有以下几种:device、share、scene和adv,这几类消息SDK会尝试解析,不会传递给客户端,独立APP的push消息格式不要和这个重复。其他Push消息SDK会通过广播的方式将其发送出来,具体可以参考如下代码:
```Java
public static final String PUSH_MESSAGE = "com.xiaomi.push.message";
public static final String PUSH_COMMAND = "com.xiaomi.push.command";
public void registerPush() {
IntentFilter filter = new IntentFilter();
filter.addAction(PUSH_COMMAND);
filter.addAction(PUSH_MESSAGE);
registerReceiver(mReceiver, filter);
}
BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
switch (action) {
case PUSH_COMMAND:
MiPushCommandMessage command = (MiPushCommandMessage) intent.getSerializableExtra("command");
Logger.d(TAG, "command: " + command.toString());
break;
case PUSH_MESSAGE:
MiPushMessage message = (MiPushMessage) intent.getSerializableExtra("message");
Logger.d(TAG, "message: " + message.toString());
break;
}
}
};
```
## 备注
1. 在进行独立App开发时,您可以通过您在[小米智能硬件开放平台](https://open.home.mi.com/)注册的开发者帐号绑定设备并进行调试,相关文档请参阅小米智能硬件开放平台的相关文档
2. 如果您在开发中遇到任何问题,可以联系xuxiaotian@xiaomi.com和hejianhui@xiaomi.com