Commit c2949545 authored by idic's avatar idic

配合Nordic Server端更改腳本~

parent 8038658a
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinCommonCompilerArguments">
<option name="languageVersion" value="1.1" />
<option name="apiVersion" value="1.1" />
</component>
</project>
\ No newline at end of file
......@@ -14,11 +14,10 @@ import android.widget.*;
import org.prlab.idic.privacypolicy.adapter.MessageRecyclerViewAdapter;
import org.prlab.idic.privacypolicy.ble.BLECustomScript;
import org.prlab.idic.privacypolicy.pojo.Message;
import org.prlab.idic.privacypolicy.schedule.Schedulable;
import org.prlab.idic.privacypolicy.schedule.Scheduled;
import org.prlab.idic.privacypolicy.storage.PrivacyPolicyStorageImpl;
import org.prlab.idic.privacypolicy.tool.BaseUtils;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
......@@ -35,7 +34,7 @@ public class DeviceOperatorActivity extends AppCompatActivity {
private List<Message> mMessages = new LinkedList<>();
private TextView mMessageBarTextView;
private EditText mTemperatureEditText;
private TextView mTemperatureTextView;
private ImageButton mTemperatureButton;
private Switch mAirPurifierSwitch;
private RecyclerView.Adapter mMessageRecyclerViewAdapter;
......@@ -61,12 +60,12 @@ public class DeviceOperatorActivity extends AppCompatActivity {
private void initView() {
mMessageBarTextView = (TextView) findViewById(R.id.text_operation_message_bar);
mTemperatureEditText = (EditText) findViewById(R.id.edit_operation_current_temperature);
mTemperatureTextView = (TextView) findViewById(R.id.edit_operation_current_temperature);
mTemperatureButton = (ImageButton) findViewById(R.id.button_operation_send_temperature);
mTemperatureButton.setOnClickListener(mTemperatureClickedListener);
mAirPurifierSwitch = (Switch) findViewById(R.id.switch_operation_air_purifier);
mAirPurifierSwitch.setOnCheckedChangeListener(mOnAirPurifierSwitchCheckedListener);
mAirPurifierSwitch.setOnClickListener(mOnAirPurifierSwitchCheckedListener);
RecyclerView mMessageRecyclerView = (RecyclerView) findViewById(R.id.recycler_view_operation_info);
mMessageRecyclerViewAdapter = new MessageRecyclerViewAdapter(getResources(), mMessages);
......@@ -83,8 +82,9 @@ public class DeviceOperatorActivity extends AppCompatActivity {
}
private final UUID ROOT_UUID = UUID.fromString("01122334-4556-6778-899a-abbccddeeff0");
private final UUID TEMPERATURE_UUID = UUID.fromString("01122334-4556-6778-899a-abbccddeeff1");
private final UUID AIR_UUID = UUID.fromString("01122334-4556-6778-899a-abbccddeeff2");
private final UUID TEMPERATURE_UUID = UUID.fromString("01122335-4556-6778-899a-abbccddeeff0");
private final UUID AIR_UUID = UUID.fromString("01122336-4556-6778-899a-abbccddeeff0");
private final UUID CCCD_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
private View.OnClickListener mTemperatureClickedListener = new View.OnClickListener() {
@Override
......@@ -93,92 +93,86 @@ public class DeviceOperatorActivity extends AppCompatActivity {
BluetoothGattService service = mBluetoothGatt.getService(ROOT_UUID);
BluetoothGattCharacteristic temperature = service == null ? null : service.getCharacteristic(TEMPERATURE_UUID);
if (temperature != null) {
temperature.setValue(BaseUtils.int2Bytes(Integer.parseInt(String.valueOf(mTemperatureEditText.getText()))));
mBluetoothGatt.writeCharacteristic(temperature);
notifyTemperature();
}
}
}
};
private CompoundButton.OnCheckedChangeListener mOnAirPurifierSwitchCheckedListener = new CompoundButton.OnCheckedChangeListener() {
private View.OnClickListener mOnAirPurifierSwitchCheckedListener = new View.OnClickListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
public void onClick(View v) {
if (mBluetoothGatt != null) {
BluetoothGattService service = mBluetoothGatt.getService(ROOT_UUID);
BluetoothGattCharacteristic airPurifier = service == null ? null : service.getCharacteristic(AIR_UUID);
if (airPurifier != null) {
airPurifier.setValue(isChecked ? BaseUtils.int2Bytes(1) : BaseUtils.int2Bytes(0));
airPurifier.setValue(new byte[]{(byte) (mAirPurifierSwitch.isChecked() ? 1 : 0)});
mBluetoothGatt.writeCharacteristic(airPurifier);
}
}
}
};
private List<Schedulable> mPermissionSettingQueue = new LinkedList<>();
private boolean isSubscribe = false;
private void notifyTemperature() {
if (mBluetoothGatt == null) return;
synchronized (mBluetoothGatt) {
BluetoothGattService service = mBluetoothGatt.getService(ROOT_UUID);
BluetoothGattCharacteristic characteristic = service.getCharacteristic(TEMPERATURE_UUID);
if (characteristic != null) {
mBluetoothGatt.setCharacteristicNotification(characteristic, !isSubscribe);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CCCD_UUID);
descriptor.setValue(!isSubscribe ?
BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}
}
private void requestAirPurifier() {
synchronized (mBluetoothGatt) {
BluetoothGattService service = mBluetoothGatt.getService(ROOT_UUID);
BluetoothGattCharacteristic characteristic = service.getCharacteristic(AIR_UUID);
if (characteristic != null) {
mBluetoothGatt.readCharacteristic(characteristic);
}
}
}
private void resolveTemperature(final int value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mTemperatureTextView.setText(String.valueOf(value));
}
});
}
private void resolveAirPurifier(final int value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mAirPurifierSwitch.setChecked(value == 1);
}
});
}
private List<Scheduled> mPermissionSettingQueue = new LinkedList<>();
private BLECustomScript mBLECustomScript = new BLECustomScript() {
int expectedSuccessValue = 0;
int successValue = 0;
private void requestServices() {
void requestServices() {
if (successValue == expectedSuccessValue) {
setMessageBar("Try to request services.");
addMessage("Request Services", "Try to get temperature & air purifier state.");
requestTemperature();
notifyTemperature();
}
}
private void requestValue(UUID characteristicUUID) {
synchronized (mBluetoothGatt) {
BluetoothGattService service = mBluetoothGatt.getService(ROOT_UUID);
BluetoothGattCharacteristic characteristic = service.getCharacteristic(characteristicUUID);
if (characteristic != null) {
mBluetoothGatt.readCharacteristic(characteristic);
}
}
}
private void requestTemperature() {
requestValue(TEMPERATURE_UUID);
}
private void requestAirPurifier() {
requestValue(AIR_UUID);
}
private void resolveTemperature(final int value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (value == -99) {
addMessage("Temperature Service", "Get failure -> " + value);
mTemperatureEditText.setEnabled(false);
mTemperatureButton.setEnabled(false);
} else {
addMessage("Temperature Service", "Get success -> " + value);
mTemperatureEditText.setEnabled(true);
mTemperatureButton.setEnabled(true);
}
mTemperatureEditText.setText(String.valueOf(value));
}
});
}
private void resolveAirPurifier(final int value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (value != -1) {
addMessage("Air Purifier Service", "Get success -> " + (value == 1 ? "running" : "sleeping"));
} else {
addMessage("Air Purifier Service", "Get failure -> " + String.valueOf(value));
}
mAirPurifierSwitch.setChecked(value == 1);
}
});
}
private boolean settingPermission() {
if (mPermissionSettingQueue.size() > 0) {
Log.i(TAG, "Continue to work.");
......@@ -199,46 +193,56 @@ public class DeviceOperatorActivity extends AppCompatActivity {
layerUUIDs.add(String.valueOf(service.getUuid()));
//Write service layer selection
int selection = mPolicyStorage.get(layerUUIDs);
if (selection == -1) selection = 0;
final BluetoothGattCharacteristic characteristic = service.getCharacteristic(PRIVACY_POLICY_ACCEPT_UUID);
if (characteristic != null) {
final int finalSelection = selection;
mPermissionSettingQueue.add(new Schedulable() {
@Override
public void work() {
characteristic.setValue(BaseUtils.int2Bytes(finalSelection));
Log.i(TAG, Arrays.toString(BaseUtils.int2Bytes(finalSelection)));
gatt.writeCharacteristic(characteristic);
expectedSuccessValue++;
}
});
addMessage("Policy Setting", "Set " + BaseUtils.stringList2ArrayString(layerUUIDs) + " to " + selection + ".");
}
for (BluetoothGattCharacteristic characteristic2 : service.getCharacteristics()) {
layerUUIDs.add(String.valueOf(characteristic2.getUuid()));
//Write characteristic layer selection
selection = mPolicyStorage.get(layerUUIDs);
if (selection == -1) selection = 0;
final BluetoothGattDescriptor descriptor = characteristic2.getDescriptor(PRIVACY_POLICY_ACCEPT_UUID);
if (descriptor != null) {
final int finalSelection1 = selection;
mPermissionSettingQueue.add(new Schedulable() {
if (selection != -1) {
final BluetoothGattCharacteristic characteristic = service.getCharacteristic(PRIVACY_POLICY_ACCEPT_UUID);
if (characteristic != null) {
final int finalSelection = selection;
mPermissionSettingQueue.add(new Scheduled() {
@Override
public void work() {
descriptor.setValue(BaseUtils.int2Bytes(finalSelection1));
Log.i(TAG, Arrays.toString(BaseUtils.int2Bytes(finalSelection1)));
gatt.writeDescriptor(descriptor);
expectedSuccessValue++;
setCharacteristicPermission(mBluetoothGatt, characteristic, finalSelection);
}
});
addMessage("Policy Setting", "Set " + BaseUtils.stringList2ArrayString(layerUUIDs) + " to " + selection + ".");
}
}
for (BluetoothGattCharacteristic characteristic2 : service.getCharacteristics()) {
layerUUIDs.add(String.valueOf(characteristic2.getUuid()));
//Write characteristic layer selection
selection = mPolicyStorage.get(layerUUIDs);
if (selection != -1) {
final BluetoothGattDescriptor descriptor = characteristic2.getDescriptor(PRIVACY_POLICY_ACCEPT_UUID);
if (descriptor != null) {
final int finalSelection1 = selection;
mPermissionSettingQueue.add(new Scheduled() {
@Override
public void work() {
setDescriptorPermission(gatt, descriptor, finalSelection1);
}
});
addMessage("Policy Setting", "Set " + BaseUtils.stringList2ArrayString(layerUUIDs) + " to " + selection + ".");
}
}
layerUUIDs.remove(layerUUIDs.size() - 1);
}
}
settingPermission();
}
private void setCharacteristicPermission(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int selection) {
characteristic.setValue(new byte[]{(byte) selection});
Log.i(TAG, String.valueOf(selection));
gatt.writeCharacteristic(characteristic);
expectedSuccessValue++;
}
private void setDescriptorPermission(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int selection) {
descriptor.setValue(new byte[]{(byte) selection});
Log.i(TAG, String.valueOf(selection));
gatt.writeDescriptor(descriptor);
expectedSuccessValue++;
}
@Override
public void onWriteCharacteristicCompleted(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status, byte[] values) {
if (PRIVACY_POLICY_ACCEPT_UUID.equals(characteristic.getUuid())) {
......@@ -249,24 +253,17 @@ public class DeviceOperatorActivity extends AppCompatActivity {
"Set " + BaseUtils.stringList2ArrayString(layerUUIDs) + (status == GATT_SUCCESS ? " success" : " failure") + " .");
if (settingPermission())
requestServices();
} else if (TEMPERATURE_UUID.equals(characteristic.getUuid())) {
addMessage("Temperature Setting", "Set " + BaseUtils.bytesToInt(values) + " to the air conditioning.");
requestTemperature();
} else if (AIR_UUID.equals(characteristic.getUuid())) {
addMessage("Air Purifier Setting", "Turn " + (BaseUtils.bytesToInt(values) == 1 ? "on " : "off ") + "the air purifier" + ".");
addMessage("Air Purifier Setting", "Try to turn " + (BaseUtils.bytesToInt(values) == 1 ? "on " : "off ") + "the air purifier" + ".");
requestAirPurifier();
}
}
@Override
public void onReadCharacteristicCompleted(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status, byte[] values) {
if (TEMPERATURE_UUID.equals(characteristic.getUuid())) {
resolveTemperature(BaseUtils.bytesToInt(values));
if (mTemperatureEditText.getText().toString().equals("")) {
requestAirPurifier();
}
} else if (AIR_UUID.equals(characteristic.getUuid())) {
if (AIR_UUID.equals(characteristic.getUuid())) {
resolveAirPurifier(BaseUtils.bytesToInt(values));
addMessage("Air Purifier Setting", "The air purifier is " + (BaseUtils.bytesToInt(values) == 1 ? "on" : "off") + ".");
}
}
......@@ -281,6 +278,18 @@ public class DeviceOperatorActivity extends AppCompatActivity {
(status == GATT_SUCCESS ? " success" : " failure") + " .");
if (settingPermission())
requestServices();
} else if (CCCD_UUID.equals(descriptor.getUuid())) {
addMessage("Temperature Setting", (!isSubscribe ? "Subscribe" : "Unsubscribe")
+ " temperature data of air conditioner.");
isSubscribe = !isSubscribe;
runOnUiThread(new Runnable() {
@Override
public void run() {
mTemperatureButton.setImageResource(isSubscribe ? R.drawable.ic_timer_off_black_24dp : R.drawable.ic_timer_black_24dp);
}
});
requestAirPurifier();
setMessageBar("Device setting finished.");
}
}
......@@ -289,6 +298,13 @@ public class DeviceOperatorActivity extends AppCompatActivity {
}
@Override
public void onNotificationReceived(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
int value = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
resolveTemperature(value);
addMessage("Temperature Setting", "Receive temperature value : [" + value + "].");
}
@Override
public void onPairRequestReceived(BluetoothDevice device, int pin) {
......@@ -335,6 +351,11 @@ public class DeviceOperatorActivity extends AppCompatActivity {
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
mBLECustomScript.onNotificationReceived(gatt, characteristic);
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
// if ((status & (BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION | BluetoothGatt.GATT_INSUFFICIENT_ENCRYPTION)) != 0) {
......@@ -360,6 +381,7 @@ public class DeviceOperatorActivity extends AppCompatActivity {
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
mBLECustomScript.onWriteDescriptorCompleted(mBluetoothGatt, descriptor, status, descriptor.getValue());
}
};
private void registerPairRequestReceiver() {
......@@ -439,8 +461,8 @@ public class DeviceOperatorActivity extends AppCompatActivity {
int connectionState = mBluetoothManager.getConnectionState(mBluetoothGatt.getDevice(), BluetoothProfile.GATT);
Log.i(TAG, "Device connection status is " + connectionState + ".");
if (connectionState == BluetoothProfile.STATE_CONNECTED) {
boolean isBonded = mBluetoothAdapter.getBondedDevices().contains(mBluetoothGatt.getDevice());
Log.i(TAG, "Device is already bonded. :" + isBonded);
// boolean isBonded = mBluetoothAdapter.getBondedDevices().contains(mBluetoothGatt.getDevice());
// Log.i(TAG, "Device is already bonded. :" + isBonded);
// try {
// Method method = mBluetoothGatt.getDevice().getClass().getMethod("removeBond", (Class[]) null);
// method.invoke(mBluetoothGatt.getDevice(), (Object[]) null);
......@@ -482,8 +504,9 @@ public class DeviceOperatorActivity extends AppCompatActivity {
public void onBackPressed() {
super.onBackPressed();
if (mBluetoothGatt != null) {
mBluetoothGatt.disconnect();
disconnect();
mBluetoothGatt.close();
mBluetoothGatt = null;
}
}
......@@ -491,8 +514,9 @@ public class DeviceOperatorActivity extends AppCompatActivity {
protected void onDestroy() {
super.onDestroy();
if (mBluetoothGatt != null) {
mBluetoothGatt.disconnect();
disconnect();
mBluetoothGatt.close();
mBluetoothGatt = null;
}
}
}
......@@ -34,6 +34,8 @@ import static org.prlab.idic.privacypolicy.tool.NegotiatorConstants.ACTIVITY_SEL
*/
public class ReportActivity extends Activity implements LoaderManager.LoaderCallbacks<PrivacyPolicyReport> {
private static final String TAG = ReportActivity.class.getSimpleName();
private LinearLayout mReportLayout;
private TextView mReportTitleTextView;
private TextView mVersionTextView;
......
......@@ -15,6 +15,7 @@ public interface BLECustomScript {
void onReadCharacteristicCompleted(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status, byte[] values);
void onWriteDescriptorCompleted(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status, byte[] values);
void onReadDescriptorCompleted(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status, byte[] values);
void onNotificationReceived(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic);
void onPairRequestReceived(BluetoothDevice device, int pin);
void onPaired(BluetoothDevice device);
void onUnpaired(BluetoothDevice device);
......
......@@ -3,7 +3,7 @@ package org.prlab.idic.privacypolicy.schedule;
/**
* Created by IDIC on 2017/2/24.
*/
public interface Schedulable {
public interface Scheduled {
void work();
......
package org.prlab.idic.privacypolicy.tool;
import org.prlab.idic.privacypolicy.pojo.report.Layer;
import org.prlab.idic.privacypolicy.pojo.report.PrivacyPolicy;
import org.prlab.idic.privacypolicy.pojo.report.p3p.Remedy;
import java.nio.ByteBuffer;
......@@ -130,7 +129,7 @@ public class BaseUtils {
}
public static int bytesToInt(byte[] bytes) {
return ByteBuffer.wrap(bytes).getInt();
return bytes.length == 1 ? bytes[0] : ByteBuffer.wrap(bytes).getInt();
}
}
......@@ -3,7 +3,9 @@
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M6,18c0,0.55 0.45,1 1,1h1v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L11,19h2v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L16,19h1c0.55,0 1,-0.45 1,-1L18,8L6,8v10zM3.5,8C2.67,8 2,8.67 2,9.5v7c0,0.83 0.67,1.5 1.5,1.5S5,17.33 5,16.5v-7C5,8.67 4.33,8 3.5,8zM20.5,8c-0.83,0 -1.5,0.67 -1.5,1.5v7c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5v-7c0,-0.83 -0.67,-1.5 -1.5,-1.5zM15.53,2.16l1.3,-1.3c0.2,-0.2 0.2,-0.51 0,-0.71 -0.2,-0.2 -0.51,-0.2 -0.71,0l-1.48,1.48C13.85,1.23 12.95,1 12,1c-0.96,0 -1.86,0.23 -2.66,0.63L7.85,0.15c-0.2,-0.2 -0.51,-0.2 -0.71,0 -0.2,0.2 -0.2,0.51 0,0.71l1.31,1.31C6.97,3.26 6,5.01 6,7h12c0,-1.99 -0.97,-3.75 -2.47,-4.84zM10,5L9,5L9,4h1v1zM15,5h-1L14,4h1v1z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M15,1L9,1v2h6L15,1zM11,14h2L13,8h-2v6zM19.03,7.39l1.42,-1.42c-0.43,-0.51 -0.9,-0.99 -1.41,-1.41l-1.42,1.42C16.07,4.74 14.12,4 12,4c-4.97,0 -9,4.03 -9,9s4.02,9 9,9 9,-4.03 9,-9c0,-2.12 -0.74,-4.07 -1.97,-5.61zM12,20c-3.87,0 -7,-3.13 -7,-7s3.13,-7 7,-7 7,3.13 7,7 -3.13,7 -7,7z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M19.04,4.55l-1.42,1.42C16.07,4.74 14.12,4 12,4c-1.83,0 -3.53,0.55 -4.95,1.48l1.46,1.46C9.53,6.35 10.73,6 12,6c3.87,0 7,3.13 7,7 0,1.27 -0.35,2.47 -0.94,3.49l1.45,1.45C20.45,16.53 21,14.83 21,13c0,-2.12 -0.74,-4.07 -1.97,-5.61l1.42,-1.42 -1.41,-1.42zM15,1L9,1v2h6L15,1zM11,9.44l2,2L13,8h-2v1.44zM3.02,4L1.75,5.27 4.5,8.03C3.55,9.45 3,11.16 3,13c0,4.97 4.02,9 9,9 1.84,0 3.55,-0.55 4.98,-1.5l2.5,2.5 1.27,-1.27 -7.71,-7.71L3.02,4zM12,20c-3.87,0 -7,-3.13 -7,-7 0,-1.28 0.35,-2.48 0.95,-3.52l9.56,9.56c-1.03,0.61 -2.23,0.96 -3.51,0.96z"/>
</vector>
......@@ -29,7 +29,7 @@
android:layout_height="@dimen/item_size">
<ImageButton
android:src="@drawable/ic_android_black_24dp"
android:src="@drawable/ic_timer_black_24dp"
android:id="@+id/button_operation_send_temperature"
android:layout_alignParentEnd="true"
android:layout_width="@dimen/item_size"
......@@ -55,7 +55,7 @@
android:layout_width="wrap_content"
android:layout_height="@dimen/item_size"/>
<EditText
<TextView
android:id="@+id/edit_operation_current_temperature"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:layout_toStartOf="@id/text_operation_temperature_unit"
......@@ -65,8 +65,7 @@
android:gravity="center_vertical|end"
android:layout_width="match_parent"
android:layout_height="@dimen/item_size"
android:labelFor="@id/text_operation_current_temperature"
android:inputType="number"/>
android:labelFor="@id/text_operation_current_temperature"/>
</RelativeLayout>
......
......@@ -20,7 +20,7 @@
<string name="message_enable_first">Enable Bluetooth first. Press scanning button again.</string>
<string name="message_current_temperature">Current temperature</string>
<string name="message_air_purifier_status">Air Purifier state</string>
<string name="message_air_purifier_status">State of air purifier</string>
<string name="message_choose_policy">The policies you need to choose as follows.</string>
<string name="message_collect_data">We may collect data as follows.</string>
......
......@@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
classpath 'com.android.tools.build:gradle:2.2.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment