Add connect, pause, sync
This commit is contained in:
parent
173e6690c2
commit
eaa6d72a3e
8 changed files with 339 additions and 79 deletions
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="JDK" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="JDK" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
|
89
app/src/main/java/de/asaril/bletail/BleConnectionHandler.kt
Normal file
89
app/src/main/java/de/asaril/bletail/BleConnectionHandler.kt
Normal file
|
@ -0,0 +1,89 @@
|
|||
package de.asaril.bletail
|
||||
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.bluetooth.le.ScanCallback
|
||||
import android.bluetooth.le.ScanResult
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import no.nordicsemi.android.ble.callback.SuccessCallback
|
||||
|
||||
class BleConnectionHandler(main: MainActivity) {
|
||||
|
||||
private var ble: UartManager? = null
|
||||
private val activity: MainActivity = main
|
||||
|
||||
var connected = false
|
||||
private set
|
||||
|
||||
private fun ByteArray.toHexString() = joinToString("") { "%02x".format(it) }
|
||||
|
||||
|
||||
fun connect(callback: ((Boolean) -> Unit)?) {
|
||||
|
||||
ble = UartManager(activity)
|
||||
ble!!.setGattCallbacks(DefaultUartManagerCallbacks())
|
||||
|
||||
val bluetoothManager: BluetoothManager =
|
||||
activity.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
|
||||
val bluetoothAdapter: BluetoothAdapter = bluetoothManager.adapter
|
||||
|
||||
if (!bluetoothAdapter.isEnabled) {
|
||||
val enableIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
|
||||
val requestEnableBt = 1
|
||||
activity.startActivityForResult(enableIntent, requestEnableBt)
|
||||
}
|
||||
|
||||
bluetoothAdapter.bluetoothLeScanner.startScan(object : ScanCallback() {
|
||||
override fun onScanResult(callbackType: Int, result: ScanResult) {
|
||||
super.onScanResult(callbackType, result)
|
||||
Log.i("BLEtail", "Remote device name: " + result.device.name)
|
||||
|
||||
if (result.device.name == "Bluefruit52") {
|
||||
bluetoothAdapter.bluetoothLeScanner.stopScan(this)
|
||||
ble!!.connect(result.device)
|
||||
.retry(3, 100)
|
||||
.useAutoConnect(true)
|
||||
.done {
|
||||
connected = true
|
||||
if (callback != null) {
|
||||
callback(connected)
|
||||
}
|
||||
}
|
||||
.fail { _: BluetoothDevice, _: Int ->
|
||||
connected = false
|
||||
if (callback != null) {
|
||||
callback(connected)
|
||||
}
|
||||
}
|
||||
.enqueue()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
fun disconnect(callback: ((Boolean) -> Unit)?) {
|
||||
ble!!.disconnect()
|
||||
.done {
|
||||
connected = false
|
||||
if (callback != null) {
|
||||
callback(connected)
|
||||
}
|
||||
}
|
||||
.enqueue()
|
||||
}
|
||||
|
||||
fun sendToBleUart(msgRaw: ByteArray) {
|
||||
if (connected) {
|
||||
val arr: ByteArray = CobsUtils.encode(msgRaw)
|
||||
Log.i("BLEtail", "tx:" + arr.toHexString())
|
||||
ble?.send(arr)
|
||||
} else {
|
||||
Log.w("BLEtail", "tx failed (not connected):" + msgRaw.toHexString())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,18 +1,9 @@
|
|||
package de.asaril.bletail
|
||||
|
||||
import CobsUtils
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.bluetooth.le.ScanCallback
|
||||
import android.bluetooth.le.ScanResult
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.text.InputType
|
||||
import android.util.Log
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.widget.EditText
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.SeekBar
|
||||
|
@ -23,56 +14,46 @@ import kotlinx.android.synthetic.main.activity_main.*
|
|||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private val LED_COUNT: Int = 40
|
||||
|
||||
private var ble: UartManager? = null
|
||||
private var ble: BleConnectionHandler? = null
|
||||
private var wasConnected = false
|
||||
|
||||
private var segments: MutableList<SegmentCardView>? = null
|
||||
private var paused = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
setSupportActionBar(toolbar)
|
||||
|
||||
ble = BleConnectionHandler(this)
|
||||
|
||||
segments = MutableList<SegmentCardView>(5, init = {
|
||||
SegmentCardView(this, it, 0, LED_COUNT - 1, Fx.Mode.THEATER_CHASE_RAINBOW, Color(), Color(), Color(), 0x0800, false)
|
||||
})
|
||||
for (s in segments!!) {
|
||||
s.sendCallback = this::sendToBleUart
|
||||
s.sendCallback = { bytes: ByteArray -> ble!!.sendToBleUart(bytes) }
|
||||
}
|
||||
|
||||
|
||||
ble = UartManager(this)
|
||||
ble!!.setGattCallbacks(DefaultUartManagerCallbacks())
|
||||
|
||||
val bluetoothManager: BluetoothManager =
|
||||
getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
|
||||
val bluetoothAdapter: BluetoothAdapter = bluetoothManager.adapter
|
||||
|
||||
if (!bluetoothAdapter.isEnabled) {
|
||||
val enableIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
|
||||
val requestEnableBt = 1
|
||||
startActivityForResult(enableIntent, requestEnableBt)
|
||||
}
|
||||
|
||||
bluetoothAdapter.bluetoothLeScanner.startScan(object : ScanCallback() {
|
||||
override fun onScanResult(callbackType: Int, result: ScanResult) {
|
||||
super.onScanResult(callbackType, result)
|
||||
Log.i("BLEtail", "Remote device name: " + result.device.name)
|
||||
|
||||
if (result.device.name == "Bluefruit52") {
|
||||
bluetoothAdapter.bluetoothLeScanner.stopScan(this)
|
||||
ble!!.connect(result.device)
|
||||
.retry(3, 100)
|
||||
.useAutoConnect(true)
|
||||
.enqueue()
|
||||
ble!!.connect { connected: Boolean ->
|
||||
if (connected) {
|
||||
val storedState = File(getExternalFilesDir(null)!!, "_stored.json")
|
||||
val loaded = storedState.exists() and loadFile(storedState)
|
||||
if (!loaded) {
|
||||
val defaultFile = File(getExternalFilesDir(null)!!, "default.json")
|
||||
if (defaultFile.exists()) {
|
||||
loadFile(defaultFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
updateConnection(connected)
|
||||
}
|
||||
|
||||
brightness!!.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
|
||||
override fun onProgressChanged(var1: SeekBar, var2: Int, var3: Boolean) {
|
||||
|
@ -90,15 +71,49 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
if (wasConnected) {
|
||||
ble?.connect { c -> updateConnection(c) }
|
||||
}
|
||||
super.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
saveFile("_stored")
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
wasConnected = (ble?.connected) ?: false
|
||||
ble?.disconnect { c -> updateConnection(c) }
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
segments = null
|
||||
ble!!.disconnect()
|
||||
ble!!.disconnect { c -> updateConnection(c) }
|
||||
val storedState = File(getExternalFilesDir(null)!!, "_stored.json")
|
||||
if (storedState.exists()) {
|
||||
storedState.deleteOnExit()
|
||||
}
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
menuInflater.inflate(R.menu.main_menu, menu)
|
||||
|
||||
val connected = (ble != null) and (ble!!.connected)
|
||||
menu.findItem(R.id.action_connection).apply {
|
||||
if (connected) {
|
||||
icon = getDrawable(R.drawable.ic_bluetooth_connected_black_24dp)
|
||||
title = getString(R.string.disconnect)
|
||||
} else {
|
||||
icon = getDrawable(R.drawable.ic_bluetooth_disabled_black_24dp)
|
||||
title = getString(R.string.connect)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -107,28 +122,30 @@ class MainActivity : AppCompatActivity() {
|
|||
val m = Fx.setNumSegments_msg.newBuilder()
|
||||
m.numSegments = count
|
||||
r.setNumSegments = m.build()
|
||||
sendToBleUart(r.build().toByteArray())
|
||||
if (ble != null) {
|
||||
ble!!.sendToBleUart(r.build().toByteArray())
|
||||
|
||||
val segLength: Int = LED_COUNT / count
|
||||
val segmentListLayout = findViewById<LinearLayout>(R.id.segmentList)
|
||||
val segLength: Int = LED_COUNT / count
|
||||
val segmentListLayout = findViewById<LinearLayout>(R.id.segmentList)
|
||||
|
||||
for (i in 0 until count) {
|
||||
segments!![i].start = segLength * i
|
||||
segments!![i].end = if (i == count - 1) {
|
||||
LED_COUNT - 1
|
||||
} else {
|
||||
(segLength * (i + 1) - 1)
|
||||
for (i in 0 until count) {
|
||||
segments!![i].start = segLength * i
|
||||
segments!![i].end = if (i == count - 1) {
|
||||
LED_COUNT - 1
|
||||
} else {
|
||||
(segLength * (i + 1) - 1)
|
||||
}
|
||||
segments!![i].sendSetSegment()
|
||||
}
|
||||
segments!![i].sendSetSegment()
|
||||
}
|
||||
|
||||
while (segmentListLayout.childCount > count) {
|
||||
val ind = segmentListLayout.childCount - 1
|
||||
segmentListLayout.removeViewAt(ind)
|
||||
}
|
||||
while (segmentListLayout.childCount < count) {
|
||||
val ind = segmentListLayout.childCount
|
||||
segmentListLayout.addView(segments!![ind], ind)
|
||||
while (segmentListLayout.childCount > count) {
|
||||
val ind = segmentListLayout.childCount - 1
|
||||
segmentListLayout.removeViewAt(ind)
|
||||
}
|
||||
while (segmentListLayout.childCount < count) {
|
||||
val ind = segmentListLayout.childCount
|
||||
segmentListLayout.addView(segments!![ind], ind)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,8 +158,9 @@ class MainActivity : AppCompatActivity() {
|
|||
val r: Fx.Root.Builder = Fx.Root.newBuilder()
|
||||
r.halt = Fx.halt_msg.newBuilder().build()
|
||||
val msgRaw = r.build().toByteArray()
|
||||
sendToBleUart(msgRaw)
|
||||
ble!!.disconnect()
|
||||
ble?.sendToBleUart(msgRaw)
|
||||
ble?.disconnect(null)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
builder.setNegativeButton("Cancel") { dialog, _ -> dialog.cancel() }
|
||||
|
@ -154,7 +172,7 @@ class MainActivity : AppCompatActivity() {
|
|||
val m = Fx.setBrightness_msg.newBuilder()
|
||||
m.brightness = value
|
||||
r.setBrightness = m.build()
|
||||
sendToBleUart(r.build().toByteArray())
|
||||
ble?.sendToBleUart(r.build().toByteArray())
|
||||
}
|
||||
|
||||
fun segCountClick(item: MenuItem) {
|
||||
|
@ -169,13 +187,6 @@ class MainActivity : AppCompatActivity() {
|
|||
)
|
||||
}
|
||||
|
||||
fun sendToBleUart(msgRaw: ByteArray) {
|
||||
val arr: ByteArray = CobsUtils.encode(msgRaw)
|
||||
fun ByteArray.toHexString() = joinToString("") { "%02x".format(it) }
|
||||
Log.i("BLEtail", "tx:" + arr.toHexString())
|
||||
ble?.send(arr)
|
||||
}
|
||||
|
||||
|
||||
fun serialize(): JSONObject {
|
||||
val j = JSONObject()
|
||||
|
@ -189,21 +200,32 @@ class MainActivity : AppCompatActivity() {
|
|||
return j
|
||||
}
|
||||
|
||||
fun deserialize(j: JSONObject) {
|
||||
fun deserialize(j: JSONObject): Boolean {
|
||||
brightness.progress = j.getInt("brightness")
|
||||
val jsegs = j.getJSONArray("segments")
|
||||
updateSegmentCards(jsegs.length())
|
||||
for (i in 0 until jsegs.length()) {
|
||||
val segNum = jsegs.length()
|
||||
if (segNum < 1) {
|
||||
return false
|
||||
}
|
||||
updateSegmentCards(segNum)
|
||||
for (i in 0 until segNum) {
|
||||
val jseg = jsegs[i] as JSONObject
|
||||
val idx = jseg.getInt("index")
|
||||
assert(idx < segments!!.size)
|
||||
segments!![idx].deserialize(jseg)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun loadFile(file: File) {
|
||||
private fun loadFile(file: File): Boolean {
|
||||
val j = JSONObject(file.readText())
|
||||
deserialize(j)
|
||||
val loaded = deserialize(j)
|
||||
if ((!loaded) and (file.name == "_stored.json")) {
|
||||
// remove broken stored state
|
||||
file.delete()
|
||||
return false
|
||||
}
|
||||
return loaded
|
||||
}
|
||||
|
||||
private fun saveFile(filename: String) {
|
||||
|
@ -240,5 +262,99 @@ class MainActivity : AppCompatActivity() {
|
|||
builder.show()
|
||||
}
|
||||
|
||||
fun pauseClick(item: MenuItem) {
|
||||
if ((ble != null) && (ble!!.connected)) {
|
||||
this.paused = !this.paused
|
||||
sendPause(item)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun sendPause(item: MenuItem) {
|
||||
val r = Fx.Root.newBuilder()
|
||||
if (paused) {
|
||||
val m = Fx.pause_msg.newBuilder()
|
||||
r.pause = m.build()
|
||||
item.icon = getDrawable(android.R.drawable.ic_media_play)
|
||||
item.title = getString(R.string.resume)
|
||||
} else {
|
||||
val m = Fx.resume_msg.newBuilder()
|
||||
r.resume = m.build()
|
||||
item.icon = getDrawable(android.R.drawable.ic_media_pause)
|
||||
item.title = getString(R.string.pause)
|
||||
}
|
||||
ble?.sendToBleUart(r.build().toByteArray())
|
||||
}
|
||||
|
||||
fun updateConnection(connected: Boolean) {
|
||||
(findViewById<View?>(R.id.action_connection) as MenuItem?)?.apply {
|
||||
if (connected) {
|
||||
icon = getDrawable(R.drawable.ic_bluetooth_connected_black_24dp)
|
||||
title = getString(R.string.disconnect)
|
||||
} else {
|
||||
icon = getDrawable(R.drawable.ic_bluetooth_disabled_black_24dp)
|
||||
title = getString(R.string.connect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun connectionClick(item: MenuItem) {
|
||||
val callback = { connected: Boolean ->
|
||||
item.apply {
|
||||
if (connected) {
|
||||
icon = getDrawable(R.drawable.ic_bluetooth_connected_black_24dp)
|
||||
title = getString(R.string.disconnect)
|
||||
} else {
|
||||
icon = getDrawable(R.drawable.ic_bluetooth_disabled_black_24dp)
|
||||
title = getString(R.string.connect)
|
||||
}
|
||||
}
|
||||
Unit
|
||||
}
|
||||
|
||||
if (ble != null) {
|
||||
if (ble!!.connected) {
|
||||
ble!!.disconnect(callback)
|
||||
} else {
|
||||
ble!!.connect(callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun stopClick(item: MenuItem) {
|
||||
if ((ble != null) && (ble!!.connected)) {
|
||||
paused = true
|
||||
sendPause(item)
|
||||
|
||||
val r = Fx.Root.newBuilder()
|
||||
val m = Fx.strip_off_msg.newBuilder()
|
||||
r.stripOff = m.build()
|
||||
ble?.sendToBleUart(r.build().toByteArray())
|
||||
}
|
||||
|
||||
val storedState = File(getExternalFilesDir(null)!!, "_stored.json")
|
||||
if (storedState.exists()) {
|
||||
storedState.deleteOnExit()
|
||||
}
|
||||
}
|
||||
|
||||
fun syncClick(item: MenuItem) {
|
||||
if ((ble != null) && (ble!!.connected) && (segments != null)) {
|
||||
var r = Fx.Root.newBuilder()
|
||||
val m = Fx.stop_msg.newBuilder()
|
||||
r.stop = m.build()
|
||||
ble?.sendToBleUart(r.build().toByteArray())
|
||||
|
||||
for (i in 0 until segments!!.size) {
|
||||
segments!![i].speed = segments!![0].speed
|
||||
segments!![i].updateView()
|
||||
}
|
||||
|
||||
r = Fx.Root.newBuilder()
|
||||
val m2 = Fx.start_msg.newBuilder()
|
||||
r.start = m2.build()
|
||||
ble?.sendToBleUart(r.build().toByteArray())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -266,17 +266,22 @@ class SegmentCardView : CardView {
|
|||
assert(this.index == j.getInt("index"))
|
||||
this.start = j.getInt("start")
|
||||
this.end = j.getInt("end")
|
||||
this.mode = Fx.Mode.forNumber(j.getInt("mode"))
|
||||
|
||||
val jcolors = j.getJSONArray("colors")
|
||||
this.colors[0] = Color.valueOf(jcolors[0] as Int)
|
||||
this.colors[1] = Color.valueOf(jcolors[1] as Int)
|
||||
this.colors[2] = Color.valueOf(jcolors[2] as Int)
|
||||
this.speed = j.getInt("speed")
|
||||
|
||||
this.reverse = j.getBoolean("reverse")
|
||||
|
||||
// set mode last as this will trigger setSegment
|
||||
this.mode = Fx.Mode.forNumber(j.getInt("mode"))
|
||||
updateView()
|
||||
sendSetSegment()
|
||||
}
|
||||
|
||||
private fun updateView() {
|
||||
fun updateView() {
|
||||
viewCol0!!.setColorFilter(colors[0].toArgb())
|
||||
viewCol1!!.setColorFilter(colors[1].toArgb())
|
||||
viewCol2!!.setColorFilter(colors[2].toArgb())
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<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="M7,12l-2,-2 -2,2 2,2 2,-2zM17.71,7.71L12,2h-1v7.59L6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 11,14.41L11,22h1l5.71,-5.71 -4.3,-4.29 4.3,-4.29zM13,5.83l1.88,1.88L13,9.59L13,5.83zM14.88,16.29L13,18.17v-3.76l1.88,1.88zM19,10l-2,2 2,2 2,-2 -2,-2z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<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="M13,5.83l1.88,1.88 -1.6,1.6 1.41,1.41 3.02,-3.02L12,2h-1v5.03l2,2v-3.2zM5.41,4L4,5.41 10.59,12 5,17.59 6.41,19 11,14.41V22h1l4.29,-4.29 2.3,2.29L20,18.59 5.41,4zM13,18.17v-3.76l1.88,1.88L13,18.17z"/>
|
||||
</vector>
|
|
@ -9,14 +9,28 @@
|
|||
android:iconTint="@android:color/secondary_text_dark"
|
||||
android:title="@string/load"
|
||||
android:onClick="loadBtnClick"
|
||||
app:showAsAction="ifRoom" />
|
||||
app:showAsAction="always" />
|
||||
<item
|
||||
android:id="@+id/saveBtn"
|
||||
android:title="@string/save"
|
||||
android:icon="@android:drawable/ic_menu_save"
|
||||
android:iconTint="@android:color/primary_text_dark"
|
||||
android:onClick="saveBtnClick"
|
||||
app:showAsAction="ifRoom"/>
|
||||
app:showAsAction="always"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_pause"
|
||||
android:icon="@android:drawable/ic_media_pause"
|
||||
android:onClick="pauseClick"
|
||||
android:title="@string/pause"
|
||||
app:showAsAction="always" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_connection"
|
||||
android:icon="@drawable/ic_bluetooth_disabled_black_24dp"
|
||||
android:onClick="connectionClick"
|
||||
android:title="@string/connect"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/segCountMenu"
|
||||
|
@ -48,8 +62,20 @@
|
|||
</menu>
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/action_halt"
|
||||
android:id="@+id/action_sync"
|
||||
android:icon="@android:drawable/ic_popup_sync"
|
||||
android:onClick="syncClick"
|
||||
android:title="@string/action_sync"
|
||||
app:showAsAction="collapseActionView" />
|
||||
<item
|
||||
android:id="@+id/action_stop"
|
||||
android:icon="@android:drawable/ic_lock_power_off"
|
||||
android:onClick="stopClick"
|
||||
android:title="@string/action_stop"
|
||||
app:showAsAction="collapseActionView" />
|
||||
<item
|
||||
android:id="@+id/action_halt"
|
||||
android:icon="@android:drawable/ic_delete"
|
||||
android:onClick="powerOffClick"
|
||||
android:title="@string/action_halt"
|
||||
app:showAsAction="collapseActionView" />
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<resources>
|
||||
<string name="app_name">BLEtail</string>
|
||||
<string name="action_halt">Halt</string>
|
||||
<string name="action_halt">Shutdown</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
<string name="seg3">3</string>
|
||||
<string name="seg5">5</string>
|
||||
|
@ -15,4 +15,10 @@
|
|||
<string name="brightness">Brightness</string>
|
||||
<string name="load">Load</string>
|
||||
<string name="save">Save</string>
|
||||
<string name="connect">Connect</string>
|
||||
<string name="disconnect">Disconnect</string>
|
||||
<string name="pause">Pause</string>
|
||||
<string name="resume">Resume</string>
|
||||
<string name="action_stop">Stop (Off)</string>
|
||||
<string name="action_sync">Sync</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue