Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Stefan Zabka
Companion App Android
Commits
3e789563
Commit
3e789563
authored
Aug 22, 2019
by
Stefan Zabka
Browse files
Merge branch 'master' into navigation
parents
7c13b0fb
3624ec85
Pipeline
#2914
passed with stage
in 3 minutes and 42 seconds
Changes
13
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
app/src/main/java/de/ccc/events/badge/card10/MainActivity.kt
View file @
3e789563
...
...
@@ -97,17 +97,17 @@ class MainActivity : AppCompatActivity() {
}
fun
permissionGranted
()
{
val
workManager
=
WorkManager
.
getInstance
(
this
)
if
(!
bluetoothAdapter
.
bondedDevices
.
isEmpty
()
)
{
val
updateClockRequest
=
PeriodicWorkRequestBuilder
<
UpdateClockJob
>(
UPDATE_CLOCK_FREQUENCY_MINS
.
toLong
(),
TimeUnit
.
MINUTES
)
.
build
()
workManager
.
enqueueUniquePeriodicWork
(
WORK_NAME
,
ExistingPeriodicWorkPolicy
.
REPLACE
,
updateClockRequest
)
}
else
{
workManager
.
cancelUniqueWork
(
WORK_NAME
)
}
//
val workManager = WorkManager.getInstance(this)
//
if (!bluetoothAdapter.bondedDevices.isEmpty()
//
) {
//
val updateClockRequest =
//
PeriodicWorkRequestBuilder<UpdateClockJob>(UPDATE_CLOCK_FREQUENCY_MINS.toLong(), TimeUnit.MINUTES)
//
.build()
//
workManager
//
.enqueueUniquePeriodicWork(WORK_NAME, ExistingPeriodicWorkPolicy.REPLACE, updateClockRequest)
//
} else {
//
workManager.cancelUniqueWork(WORK_NAME)
//
}
}
override
fun
onBackPressed
()
{
...
...
app/src/main/java/de/ccc/events/badge/card10/common/ConnectionService.kt
View file @
3e789563
...
...
@@ -26,10 +26,10 @@ import android.bluetooth.*
import
android.content.Context
import
android.util.Log
import
de.ccc.events.badge.card10.CARD10_BLUETOOTH_MAC_PREFIX
import
de.ccc.events.badge.card10.CARD10_SERVICE_UUID
import
de.ccc.events.badge.card10.R
import
de.ccc.events.badge.card10.filetransfer.LowEffortService
import
java.lang.IllegalStateException
import
java.lang.NullPointerException
import
de.ccc.events.badge.card10.time.Card10Service
import
java.util.*
private
const
val
TAG
=
"ConnectionService"
...
...
@@ -37,6 +37,7 @@ private const val TAG = "ConnectionService"
object
ConnectionService
{
var
device
:
BluetoothDevice
?
=
null
var
leService
:
LowEffortService
?
=
null
var
card10Service
:
Card10Service
?
=
null
var
mtu
=
100
private
var
connection
:
BluetoothGatt
?
=
null
...
...
@@ -98,6 +99,8 @@ object ConnectionService {
if
(
service
.
uuid
==
fileServiceUuid
)
{
leService
=
LowEffortService
(
service
)
}
else
if
(
service
.
uuid
==
CARD10_SERVICE_UUID
)
{
card10Service
=
Card10Service
(
service
)
}
}
...
...
@@ -160,7 +163,13 @@ object ConnectionService {
}
fun
writeCharacteristic
(
characteristic
:
BluetoothGattCharacteristic
):
Boolean
{
return
connection
?.
writeCharacteristic
(
characteristic
)
?:
false
val
status
=
connection
?.
writeCharacteristic
(
characteristic
)
?:
false
if
(!
status
)
{
Log
.
d
(
TAG
,
"Write status: $status"
)
}
return
status
}
}
\ No newline at end of file
app/src/main/java/de/ccc/events/badge/card10/filetransfer/LowEffortService.kt
View file @
3e789563
...
...
@@ -80,13 +80,7 @@ class LowEffortService(
val
bytes
=
packet
.
getBytes
()
centralTx
.
value
=
bytes
val
status
=
ConnectionService
.
writeCharacteristic
(
centralTx
)
if
(!
status
)
{
Log
.
d
(
TAG
,
"Write status: $status"
)
}
return
status
return
ConnectionService
.
writeCharacteristic
(
centralTx
)
}
fun
setOnPacketReceivedListener
(
packetListener
:
OnPacketReceivedListener
)
{
...
...
app/src/main/java/de/ccc/events/badge/card10/main/MainFragment.kt
View file @
3e789563
...
...
@@ -23,56 +23,62 @@
package
de.ccc.events.badge.card10.main
import
android.bluetooth.BluetoothAdapter
import
android.icu.util.UniversalTimeScale
import
android.os.Bundle
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
android.widget.Button
import
androidx.constraintlayout.widget.ConstraintLayout
import
androidx.fragment.app.Fragment
import
androidx.navigation.NavDirections
import
androidx.navigation.fragment.findNavController
import
de.ccc.events.badge.card10.CARD10_BLUETOOTH_MAC_PREFIX
import
de.ccc.events.badge.card10.R
import
de.ccc.events.badge.card10.filetransfer.FileTransferFragment
import
de.ccc.events.badge.card10.hatchery.AppListFragment
import
de.ccc.events.badge.card10.sparkle.BeautifulFragment
import
de.ccc.events.badge.card10.time.TimeUpdateDialog
import
kotlinx.android.synthetic.main.main_fragment.*
/**
* The initial fragment, the user can access all implemented functions
*/
class
MainFragment
:
Fragment
()
{
private
val
bluetoothAdapter
=
BluetoothAdapter
.
getDefaultAdapter
()
override
fun
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
?,
savedInstanceState
:
Bundle
?)
:
View
?{
/** TODO: find out and document what this does*/
if
(
requireActivity
().
intent
.
action
==
"application/x.card10.app"
){
findNavController
().
navigate
(
MainFragmentDirections
.
Installer
())
return
null
}
return
inflater
.
inflate
(
R
.
layout
.
main_fragment
,
container
,
false
)
}
override
fun
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
?,
savedInstanceState
:
Bundle
?)
=
inflater
.
inflate
(
R
.
layout
.
main_fragment
,
container
,
false
)
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
/**TODO: discuss whether databinding layout is acceptable so we can move this into the xml
*/
button_mood
.
setOnClickListener
{
startFragment
(
MainFragmentDirections
.
Mood
())
}
button_beautiful
.
setOnClickListener
{
startFragment
(
MainFragmentDirections
.
Beautiful
())
}
button_hatchery
.
setOnClickListener
{
startFragment
(
MainFragmentDirections
.
AppList
())
}
val
findNavController
=
findNavController
()
button_pair
.
setOnClickListener
{
findNavController
.
navigate
(
MainFragmentDirections
.
Scan
())
}
button_mood
.
setOnClickListener
{
findNavController
.
navigate
(
MainFragmentDirections
.
Mood
())
}
button_beautiful
.
setOnClickListener
{
findNavController
.
navigate
(
MainFragmentDirections
.
Beautiful
())
}
button_hatchery
.
setOnClickListener
{
findNavController
.
navigate
(
MainFragmentDirections
.
AppList
())
}
button_send
.
setOnClickListener
{
findNavController
.
navigate
(
MainFragmentDirections
.
Transfer
())
}
button_set_time
.
setOnClickListener
{
val
dialogFragment
=
TimeUpdateDialog
()
dialogFragment
.
show
(
fragmentManager
!!
,
"time"
)
dialogFragment
.
setTime
()
dialogFragment
.
dismiss
()
}
val
bondedCard10s
=
bluetoothAdapter
.
bondedDevices
.
filter
{
it
.
address
.
startsWith
(
CARD10_BLUETOOTH_MAC_PREFIX
,
true
)
}
if
(
bondedCard10s
.
isNotEmpty
())
{
val
device
=
bondedCard10s
[
0
]
label_status
.
text
=
getString
(
R
.
string
.
main_label_paired
,
device
.
name
,
device
.
address
)
showConnectedView
(
view
)
}
else
{
startFragment
(
MainFragmentDirections
.
Disconnected
())
label_status
.
text
=
getString
(
R
.
string
.
main_label_not_connected
)
showDisconnectedView
(
view
)
}
}
private
fun
showConnectedView
(
view
:
View
)
{
view
.
findViewById
<
ConstraintLayout
>(
R
.
id
.
container_connected
).
visibility
=
View
.
VISIBLE
view
.
findViewById
<
ConstraintLayout
>(
R
.
id
.
container_disconnected
).
visibility
=
View
.
GONE
view
.
findViewById
<
Button
>(
R
.
id
.
button_pair
).
text
=
getString
(
R
.
string
.
main_button_manage_pairings
)
}
private
fun
startFragment
(
direction
:
NavDirections
)
{
findNavController
().
navigate
(
direction
)
private
fun
showDisconnectedView
(
view
:
View
)
{
view
.
findViewById
<
ConstraintLayout
>(
R
.
id
.
container_connected
).
visibility
=
View
.
GONE
view
.
findViewById
<
ConstraintLayout
>(
R
.
id
.
container_disconnected
).
visibility
=
View
.
VISIBLE
}
}
app/src/main/java/de/ccc/events/badge/card10/scanner/ScannerListAdapter.kt
View file @
3e789563
...
...
@@ -26,10 +26,12 @@ import android.view.LayoutInflater
import
android.view.ViewGroup
import
androidx.recyclerview.widget.RecyclerView
import
java.util.*
import
kotlin.collections.HashSet
class
ScannerListAdapter
(
val
clickListener
:
(
Device
)
->
Unit
)
:
RecyclerView
.
Adapter
<
DeviceViewHolder
>()
{
private
val
list
=
LinkedList
<
Device
>()
private
val
foundDevices
=
mutableSetOf
<
String
>()
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
DeviceViewHolder
{
val
inflater
=
LayoutInflater
.
from
(
parent
.
context
)
...
...
@@ -44,6 +46,12 @@ class ScannerListAdapter(val clickListener: (Device) -> Unit) : RecyclerView.Ada
override
fun
getItemCount
():
Int
=
list
.
size
fun
put
(
device
:
Device
)
{
if
(
foundDevices
.
contains
(
device
.
btMac
))
{
return
}
else
{
foundDevices
.
add
(
device
.
btMac
)
}
list
.
remove
(
device
)
list
.
add
(
device
)
notifyDataSetChanged
()
...
...
app/src/main/java/de/ccc/events/badge/card10/time/Card10Service.kt
0 → 100644
View file @
3e789563
/*
* Copyright by the original author or authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package
de.ccc.events.badge.card10.time
import
android.bluetooth.BluetoothGattCharacteristic
import
android.bluetooth.BluetoothGattService
import
de.ccc.events.badge.card10.TIME_CHARACTERISTIC_UUID
import
de.ccc.events.badge.card10.common.ConnectionService
import
java.nio.ByteBuffer
class
Card10Service
(
service
:
BluetoothGattService
)
{
private
val
timeCharacteristic
:
BluetoothGattCharacteristic
init
{
timeCharacteristic
=
service
.
getCharacteristic
(
TIME_CHARACTERISTIC_UUID
)
timeCharacteristic
.
writeType
=
BluetoothGattCharacteristic
.
WRITE_TYPE_NO_RESPONSE
}
fun
setTime
()
{
val
buffer
=
ByteBuffer
.
allocate
(
8
)
buffer
.
putLong
(
System
.
currentTimeMillis
())
timeCharacteristic
.
value
=
buffer
.
array
()
ConnectionService
.
writeCharacteristic
(
timeCharacteristic
)
}
}
\ No newline at end of file
app/src/main/java/de/ccc/events/badge/card10/
main/DisconnectedFragment
.kt
→
app/src/main/java/de/ccc/events/badge/card10/
time/TimeUpdateDialog
.kt
View file @
3e789563
...
...
@@ -20,37 +20,23 @@
* SOFTWARE.
*/
package
de.ccc.events.badge.card10.
main
package
de.ccc.events.badge.card10.
time
import
android.bluetooth.BluetoothAdapter
import
android.os.Bundle
import
android.util.Log
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
androidx.fragment.app.Fragment
import
androidx.navigation.fragment.findNavController
import
de.ccc.events.badge.card10.CARD10_BLUETOOTH_MAC_PREFIX
import
androidx.fragment.app.DialogFragment
import
de.ccc.events.badge.card10.R
import
kotlinx.android.synthetic.main.disconnected_fragment.*
import
de.ccc.events.badge.card10.common.ConnectionService
private
const
val
TAG
=
"TimeUpdateDialog"
/**
* Here we give the user the option to start his device and connect it
*/
class
DisconnectedFragment
:
Fragment
()
{
private
val
bluetoothAdapter
=
BluetoothAdapter
.
getDefaultAdapter
()
override
fun
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
?,
savedInstanceState
:
Bundle
?)
:
View
=
inflater
.
inflate
(
R
.
layout
.
disconnected_fragment
,
container
,
false
)
class
TimeUpdateDialog
:
DialogFragment
()
{
override
fun
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
?,
savedInstanceState
:
Bundle
?)
=
inflater
.
inflate
(
R
.
layout
.
time_update_dialog
,
container
,
false
)
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
button_pair
.
setOnClickListener
{
findNavController
().
navigate
(
DisconnectedFragmentDirections
.
Scanner
())
}
val
bondedCard10s
=
bluetoothAdapter
.
bondedDevices
.
filter
{
it
.
address
.
startsWith
(
CARD10_BLUETOOTH_MAC_PREFIX
,
true
)
}
if
(
bondedCard10s
.
isNotEmpty
())
{
findNavController
().
navigate
(
DisconnectedFragmentDirections
.
Connected
())
}
fun
setTime
()
{
ConnectionService
.
card10Service
?.
setTime
()
?:
Log
.
e
(
TAG
,
"card10 service not initialized"
)
}
}
}
\ No newline at end of file
app/src/main/res/layout/loading_dialog.xml
View file @
3e789563
...
...
@@ -3,17 +3,17 @@
android:orientation=
"vertical"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:padding=
"@dimen/
loading_
dialog_padding"
>
android:padding=
"@dimen/dialog_padding"
>
<ProgressBar
android:layout_width=
"@dimen/
loading
_dialog_progress"
android:layout_height=
"@dimen/
loading
_dialog_progress"
<ProgressBar
android:layout_width=
"@dimen/
progress
_dialog_progress
_size
"
android:layout_height=
"@dimen/
progress
_dialog_progress
_size
"
android:layout_gravity=
"center"
android:indeterminate=
"true"
/>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:layout_marginTop=
"@dimen/
loading
_dialog_text_margin"
android:layout_marginTop=
"@dimen/
progress
_dialog_text_margin"
android:text=
"@string/loading_dialog_loading"
/>
</LinearLayout>
\ No newline at end of file
app/src/main/res/layout/main_fragment.xml
View file @
3e789563
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:padding=
"@dimen/activity_padding"
>
...
...
@@ -23,13 +23,27 @@
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/image_logo"
/>
<Button
android:id=
"@+id/button_pair"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"@string/main_button_pair"
android:layout_marginTop=
"@dimen/main_label_margin"
style=
"@style/MainButton"
app:layout_constraintTop_toBottomOf=
"@id/label_status"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
/>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width=
"match_parent"
android:layout_height=
"0dp"
android:id=
"@+id/container_connected"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@id/button_pair"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/image_logo"
>
android:id=
"@+id/container_disconnected"
>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width=
"match_parent"
android:layout_height=
"0dp"
app:layout_constraintTop_toBottomOf=
"@id/button_pair"
android:id=
"@+id/container_connected"
>
<Button
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"@dimen/main_label_margin"
...
...
@@ -48,8 +62,7 @@
android:text=
"@string/main_button_send_file"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/button_hatchery"
android:enabled=
"false"
/>
app:layout_constraintTop_toBottomOf=
"@+id/button_hatchery"
/>
<Button
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
...
...
@@ -71,6 +84,16 @@
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
/>
<Button
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"@dimen/main_button_margin"
style=
"@style/MainButton"
android:id=
"@+id/button_set_time"
android:text=
"@string/main_button_set_time"
app:layout_constraintTop_toBottomOf=
"@+id/button_beautiful"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
...
...
app/src/main/res/layout/time_update_dialog.xml
0 → 100644
View file @
3e789563
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:orientation=
"vertical"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:padding=
"@dimen/dialog_padding"
>
<ProgressBar
android:layout_width=
"@dimen/progress_dialog_progress_size"
android:layout_height=
"@dimen/progress_dialog_progress_size"
android:layout_gravity=
"center"
android:indeterminate=
"true"
/>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:layout_marginTop=
"@dimen/progress_dialog_text_margin"
android:text=
"@string/time_update_dialog_setting"
/>
</LinearLayout>
\ No newline at end of file
app/src/main/res/navigation/nav_graph.xml
View file @
3e789563
...
...
@@ -12,9 +12,8 @@
<action
android:id=
"@+id/AppList"
app:destination=
"@id/appListFragment"
/>
<action
android:id=
"@+id/Transfer"
app:destination=
"@id/fileTransferFragment"
/>
<action
android:id=
"@+id/Disconnected"
app:destination=
"@id/disconnectedFragment"
/>
<action
android:id=
"@+id/Installer"
app:destination=
"@id/installerFragment"
/>
<action
android:id=
"@+id/Scan"
app:destination=
"@id/scannerFragment"
/>
</fragment>
<fragment
android:id=
"@+id/installerFragment"
android:name=
"de.ccc.events.badge.card10.installer.InstallerFragment"
android:label=
"InstallerFragment"
tools:layout=
"@layout/installer_fragment"
/>
...
...
@@ -37,14 +36,6 @@
app:destination=
"@id/batchTransferFragment"
/>
<argument
android:name=
"app"
app:argType=
"de.ccc.events.badge.card10.hatchery.App"
/>
</fragment>
<fragment
android:id=
"@+id/disconnectedFragment"
android:name=
"de.ccc.events.badge.card10.main.DisconnectedFragment"
android:label=
"DisconnectedFragment"
>
<action
android:id=
"@+id/Connected"
app:destination=
"@id/mainFragment"
/>
<action
android:id=
"@+id/Scanner"
app:destination=
"@id/scannerFragment"
app:enterAnim=
"@anim/nav_default_enter_anim"
app:exitAnim=
"@anim/nav_default_exit_anim"
app:popEnterAnim=
"@anim/nav_default_pop_enter_anim"
app:popExitAnim=
"@anim/nav_default_pop_exit_anim"
/>
</fragment>
<fragment
android:id=
"@+id/batchTransferFragment"
android:name=
"de.ccc.events.badge.card10.filetransfer.BatchTransferFragment"
android:label=
"BatchTransferFragment"
>
...
...
app/src/main/res/values/dimensions.xml
View file @
3e789563
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen
name=
"activity_padding"
>
24dp
</dimen>
<dimen
name=
"dialog_padding"
>
24dp
</dimen>
<dimen
name=
"logo_margin_bottom"
>
24dp
</dimen>
<dimen
name=
"main_label_margin"
>
32dp
</dimen>
...
...
@@ -13,9 +14,8 @@
<dimen
name=
"app_list_item_padding"
>
16dp
</dimen>
<dimen
name=
"app_detail_description_margin"
>
16dp
</dimen>
<dimen
name=
"loading_dialog_padding"
>
24dp
</dimen>
<dimen
name=
"loading_dialog_progress"
>
48dp
</dimen>
<dimen
name=
"loading_dialog_text_margin"
>
16dp
</dimen>
<dimen
name=
"progress_dialog_progress_size"
>
48dp
</dimen>
<dimen
name=
"progress_dialog_text_margin"
>
16dp
</dimen>
<dimen
name=
"default_list_item_margin_side"
>
16dp
</dimen>
<dimen
name=
"default_list_item_height"
>
56dp
</dimen>
...
...
app/src/main/res/values/strings.xml
View file @
3e789563
...
...
@@ -10,6 +10,7 @@
<string
name=
"main_button_send_file"
>
Send File
</string>
<string
name=
"main_button_mood"
>
Change Mood
</string>
<string
name=
"main_button_beautiful"
>
Beautiful
</string>
<string
name=
"main_button_set_time"
>
Set Time
</string>
<string
name=
"file_transfer_button_pick_file"
>
Select file
</string>
<string
name=
"file_transfer_button_start_transfer"
>
Start
</string>
...
...
@@ -32,6 +33,8 @@
<string
name=
"dialog_action_ok"
>
OK
</string>
<string
name=
"dialog_action_cancel"
>
Cancel
</string>
<string
name=
"time_update_dialog_setting"
>
Setting time
</string>
<string
name=
"hatchery_error_generic"
>
Something went wrong
</string>
<string
name=
"app_detail_downloads"
>
Downloads: %1$d
</string>
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment