1
0
mirror of https://github.com/fumiama/simple-dict-android.git synced 2026-06-10 21:24:20 +08:00
This commit is contained in:
fumiama
2021-02-18 17:26:28 +08:00
parent c82f715f55
commit 1e0a7b2a4c
15 changed files with 207 additions and 148 deletions

7
.idea/dictionaries/spayi.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<component name="ProjectDictionaryState">
<dictionary name="spayi">
<words>
<w>recv</w>
</words>
</dictionary>
</component>

View File

@@ -13,8 +13,9 @@ android {
applicationId "top.fumiama.simpledict" applicationId "top.fumiama.simpledict"
minSdkVersion 26 minSdkVersion 26
targetSdkVersion 30 targetSdkVersion 30
versionCode 4 versionCode 5
versionName '1.2' versionName '1.3'
resConfigs "zh", "zh-rCN"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }

View File

@@ -6,7 +6,7 @@ import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
import java.net.Socket import java.net.Socket
class Client(val ip: String, val port: Int) { class Client(private val ip: String, private val port: Int) {
//普通数据交互接口 //普通数据交互接口
private var sc: Socket? = null private var sc: Socket? = null
@@ -15,23 +15,22 @@ class Client(val ip: String, val port: Int) {
private var din: InputStream? = null private var din: InputStream? = null
//已连接标记 //已连接标记
var isConnect = false private val isConnect get() = sc != null && din != null && dout != null
/** /**
* 初始化普通交互连接 * 初始化普通交互连接
*/ */
fun initConnect(){ fun initConnect(depth: Int = 0){
try { if(depth > 3) Log.d("MyC", "connect server failed after $depth tries")
else try {
sc = Socket(ip, port) //通过socket连接服务器 sc = Socket(ip, port) //通过socket连接服务器
din = sc?.getInputStream() //获取输入流并转换为StreamReader约定编码格式 din = sc?.getInputStream() //获取输入流并转换为StreamReader约定编码格式
dout = sc?.getOutputStream() //获取输出流 dout = sc?.getOutputStream() //获取输出流
sc?.soTimeout = 10000 //设置连接超时限制 sc?.soTimeout = 2333 //设置连接超时限制
if (sc != null && din != null && dout != null) { //判断一下是否都连上避免NullPointException if (isConnect) Log.d("MyC", "connect server successful")
isConnect = true else {
Log.d("MyC", "connect server successful") Log.d("MyC", "connect server failed, now retry...")
} else { initConnect(depth + 1)
Log.d("MyC", "connect server failed,now retry...")
initConnect()
} }
} catch (e: IOException) { //获取输入输出流是可能报IOException的所以必须try-catch } catch (e: IOException) { //获取输入输出流是可能报IOException的所以必须try-catch
e.printStackTrace() e.printStackTrace()
@@ -45,30 +44,31 @@ class Client(val ip: String, val port: Int) {
fun sendMessage(message: CharSequence?) { fun sendMessage(message: CharSequence?) {
try { try {
if (isConnect) { if (isConnect) {
if (dout != null && message != null) { //判断输出流或者消息是否为空为空的话会产生nullpoint错误 if (message != null) { //判断输出流或者消息是否为空为空的话会产生nullpoint错误
dout!!.write(message.toString().toByteArray()) dout?.write(message.toString().toByteArray())
dout!!.flush() dout?.flush()
} else Log.d("MyC", "The message to be sent is empty or have no connect") Log.d("MyC", "Send msg: $message")
} else Log.d("MyC", "The message to be sent is empty")
Log.d("MyC", "send message succeed") Log.d("MyC", "send message succeed")
} else Log.d("MyC", "no connect to send message") } else Log.d("MyC", "send message failed: no connect")
} catch (e: IOException) { } catch (e: IOException) {
Log.d("MyC", "send message to cilent failed") Log.d("MyC", "send message failed: crash")
e.printStackTrace() e.printStackTrace()
} }
} }
fun receiveRawMessage() : ByteArray { fun receiveRawMessage(totalSize: Int = -1, bufferSize: Int = 4096) : ByteArray {
var re = byteArrayOf() var re = byteArrayOf()
try { try {
if (isConnect) { if (isConnect) {
Log.d("MyC", "开始接收服务端信息") Log.d("MyC", "开始接收服务端信息")
val inMessage = ByteArray(4096) //设置接受缓冲,避免接受数据过长占用过多内存 val inMessage = ByteArray(bufferSize) //设置接受缓冲,避免接受数据过长占用过多内存
var a: Int var a: Int
do { do {
a = din?.read(inMessage)?:0 //a存储返回消息的长度 a = din?.read(inMessage)?:0 //a存储返回消息的长度
Log.d("MyC", "reply length:$a: ${inMessage.decodeToString()}")
re += inMessage.copyOf(a) re += inMessage.copyOf(a)
} while (a == 4096) Log.d("MyC", "reply length:$a: ${re.decodeToString()}")
} while (a == bufferSize || totalSize > re.size)
} else Log.d("MyC", "no connect to receive message") } else Log.d("MyC", "no connect to receive message")
} catch (e: IOException) { } catch (e: IOException) {
Log.d("MyC", "receive message failed") Log.d("MyC", "receive message failed")
@@ -87,10 +87,12 @@ class Client(val ip: String, val port: Int) {
din?.close() din?.close()
dout?.close() dout?.close()
sc?.close() sc?.close()
sc = null
din = null
dout = null
} catch (e: IOException) { } catch (e: IOException) {
e.printStackTrace() e.printStackTrace()
} }
isConnect = false
Log.d("MyC", "关闭连接") Log.d("MyC", "关闭连接")
} }
} }

View File

@@ -9,10 +9,12 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.EditText import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.textfield.TextInputLayout
import com.lapism.search.internal.SearchLayout import com.lapism.search.internal.SearchLayout
import com.lapism.search.util.SearchUtils import com.lapism.search.util.SearchUtils
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
@@ -21,6 +23,14 @@ import kotlinx.android.synthetic.main.line_word.view.*
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private val dict = SimpleDict(Client("127.0.0.1", 8000), "fumiama") private val dict = SimpleDict(Client("127.0.0.1", 8000), "fumiama")
private var hasLiked = false private var hasLiked = false
private val fetchThread get() = Thread{
dict.fetchDict {
runOnUiThread {
Toast.makeText(this@MainActivity, "刷新成功", Toast.LENGTH_SHORT).show()
ffsw.isRefreshing = false
}
}
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -35,8 +45,10 @@ class MainActivity : AppCompatActivity() {
ffsw.apply { ffsw.apply {
setOnRefreshListener { setOnRefreshListener {
ad.refresh() ad.refresh()
isRefreshing = false fetchThread.start()
} }
isRefreshing = true
fetchThread.start()
} }
} }
@@ -107,15 +119,15 @@ class MainActivity : AppCompatActivity() {
} }
private fun showDictAlert(key: String, data: String?) { private fun showDictAlert(key: String, data: String?) {
val like = getSharedPreferences("dict", MODE_PRIVATE)?.contains(key)?:false val hintAdd = if(data != null && data != "null") "重设" else "添加"
hasLiked = false hasLiked = false
AlertDialog.Builder(this@MainActivity) AlertDialog.Builder(this@MainActivity)
.setTitle(key) .setTitle(key)
.setMessage(data) .setMessage(data)
.setPositiveButton(if(data != "null") "重设" else "添加") { _, _ -> .setPositiveButton(hintAdd) { _, _ ->
val t = EditText(this@MainActivity) val t = EditText(this@MainActivity)
AlertDialog.Builder(this@MainActivity) AlertDialog.Builder(this@MainActivity)
.setTitle("重设$key") .setTitle("$hintAdd$key")
.setView(t) .setView(t)
.setPositiveButton(android.R.string.ok) { _, _ -> .setPositiveButton(android.R.string.ok) { _, _ ->
if (t.text.isNotEmpty()) Thread { if (t.text.isNotEmpty()) Thread {
@@ -125,12 +137,8 @@ class MainActivity : AppCompatActivity() {
.setNegativeButton(android.R.string.cancel) { _, _ -> } .setNegativeButton(android.R.string.cancel) { _, _ -> }
.show() .show()
} }
.setNeutralButton(if(like) "取消收藏" else "收藏") { _, _ -> .setNeutralButton("删除") { _, _ ->
getSharedPreferences("dict", MODE_PRIVATE)?.edit()?.apply { Thread{dict -= key}.start()
if(like) remove(key) else putString(key, data)
hasLiked = true
apply()
}
} }
.setNegativeButton(android.R.string.cancel) { _, _ -> } .setNegativeButton(android.R.string.cancel) { _, _ -> }
.show() .show()
@@ -182,19 +190,38 @@ class MainActivity : AppCompatActivity() {
@SuppressLint("ClickableViewAccessibility", "SetTextI18n") @SuppressLint("ClickableViewAccessibility", "SetTextI18n")
override fun onBindViewHolder(holder: ListViewHolder, position: Int) { override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
Log.d("MyMain", "Bind like at $position") Log.d("MyMain", "Bind like at $position")
listKeys?.apply { Thread{
if (position < size) { listKeys?.apply {
val key = get(position) if (position < size) {
val data = getValue(key) val key = get(position)
holder.itemView.apply { val data = getValue(key)
ta.text = key val like = getSharedPreferences("dict", MODE_PRIVATE)?.contains(key) == true
tb.text = data runOnUiThread {
setOnClickListener { holder.itemView.apply {
showDictAlert(key, data) ta.text = key
tb.text = data
if(like) vl.setBackgroundResource(R.drawable.ic_like_filled)
setOnClickListener {
showDictAlert(key, data)
}
vl.setOnClickListener {
getSharedPreferences("dict", MODE_PRIVATE)?.edit()?.apply {
if(like) {
remove(key)
it.setBackgroundResource(R.drawable.ic_like)
} else {
putString(key, data)
it.setBackgroundResource(R.drawable.ic_like_filled)
}
hasLiked = true
apply()
}
}
}
} }
} }
} }
} }.start()
} }
override fun getItemCount() = listKeys?.size?:0 override fun getItemCount() = listKeys?.size?:0

View File

@@ -10,21 +10,44 @@ class SimpleDict(private val client: Client, private val pwd: String) { //must
//val size get() = dict.size //val size get() = dict.size
private val raw: ByteArray private val raw: ByteArray
get() { get() {
initDict() var times = 3
client.sendMessage("cat") var re: ByteArray
sleep(2333) var firstRecv: ByteArray
val re = client.receiveRawMessage() do {
closeDict() re = byteArrayOf()
initDict()
sendMessageWithDelay("cat", 2333)
try {
firstRecv = client.receiveRawMessage()
val firstStr = firstRecv.decodeToString()
var length = ""
for ((i, c) in firstStr.withIndex()) {
if(c.isDigit()) length += c
else {
if(i + 1 < firstRecv.size) re = firstRecv.copyOfRange(i, firstRecv.size)
break
}
}
re += client.receiveRawMessage(length.toInt() - re.size)
break
} catch (e: Exception){
e.printStackTrace()
}
closeDict()
} while (times-- > 0)
return re return re
} }
init { private fun sendMessageWithDelay(msg: CharSequence, delay: Long = 233) = Thread{
Thread{ fetchDict() }.start() client.sendMessage(msg)
} sleep(delay)
}.start()
private fun initDict() { private fun initDict() {
client.initConnect() client.initConnect()
client.sendMessage(pwd) client.sendMessage(pwd)
client.receiveRawMessage()
sleep(233)
} }
private fun closeDict() { private fun closeDict() {
@@ -45,59 +68,36 @@ class SimpleDict(private val client: Client, private val pwd: String) { //must
//fun filterKeys(predicate: (String) -> Boolean) = dict.filterKeys(predicate) //fun filterKeys(predicate: (String) -> Boolean) = dict.filterKeys(predicate)
fun filterValues(predicate: (String?) -> Boolean) = dict.filterValues(predicate) fun filterValues(predicate: (String?) -> Boolean) = dict.filterValues(predicate)
fun fetchDict() { fun fetchDict(doOnLoadSuccess: ()->Unit = {
Log.d("MySD", "Fetch dict success")
}) {
val dictBlock = ByteArray(128) val dictBlock = ByteArray(128)
dict = hashMapOf()
raw.inputStream().let { raw.inputStream().let {
var c = '1' while (it.read(dictBlock, 0, 128) == 128) analyzeDictBlk(dictBlock)
while (!it.read().toChar().isDigit()) Log.d("MySD", "Skip banner.") doOnLoadSuccess()
while (c.isDigit()) {
c = it.read().toChar()
Log.d("MySD", "Skip digit $c.")
}
dictBlock[0] = c.toByte()
if(it.read(dictBlock, 1, 127) == 127) {
analyzeDictBlk(dictBlock)
while (it.read(dictBlock, 0, 128) == 128) analyzeDictBlk(dictBlock)
}
} }
} }
/*fun keysWithPattern(pattern: String): MutableSet<String>{ operator fun minusAssign(key: String) {
val re = mutableSetOf<String>()
initDict() initDict()
client.sendMessage("lst") sendMessageWithDelay("del")
sleep(233) client.receiveMessage()
sendMessageWithDelay(key)
client.receiveMessage() client.receiveMessage()
client.sendMessage(pattern)
client.receiveMessage()?.substringBeforeLast('\n')?.split('\n')?.forEach {
re.add(it)
}
closeDict() closeDict()
return re
} }
fun getDirectly(key: String): String? {
initDict()
client.sendMessage("get")
sleep(233)
client.receiveMessage()
client.sendMessage(key)
val re = client.receiveMessage()
closeDict()
return re
}*/
operator fun get(key: String) = dict[key] operator fun get(key: String) = dict[key]
operator fun set(key: String, value: String): String? { operator fun set(key: String, value: String): String? {
val p = dict[key] val p = dict[key]
initDict() initDict()
client.sendMessage("set") sendMessageWithDelay("set")
sleep(233)
client.receiveMessage() client.receiveMessage()
client.sendMessage(key) sendMessageWithDelay(key)
client.receiveMessage() client.receiveMessage()
client.sendMessage(value) sendMessageWithDelay(value)
client.receiveMessage() client.receiveMessage()
closeDict() closeDict()
dict[key] = value dict[key] = value

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportHeight="1024"
android:viewportWidth="1024">
<path
android:fillColor="@android:color/holo_red_light"
android:pathData="M668 117C833 117 939 250 939 428c0 138-125 291-372 462a97 97 0 0 1-110 0C210 718 85 566 85 428 85 250 191 117 356 117c60 0 100 21 156 68C568 138 608 117 668 117z m0 63c-41 0-70 15-117 55-2 2-14 12-18 15a32 32 0 0 1-42 0c-4-3-16-14-18-15-47-40-76-55-117-55C230 180 149 281 149 427 149 538 263 675 494 835a32 32 0 0 0 37 0C761 675 875 538 875 427c0-145-81-246-207-246z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportHeight="1024"
android:viewportWidth="1024">
<path
android:fillColor="@android:color/holo_red_light"
android:pathData="M668 117C833 117 939 250 939 428c0 138-125 291-372 462a97 97 0 0 1-110 0C210 718 85 566 85 428 85 250 191 117 356 117c60 0 100 21 156 68C568 138 608 117 668 117z"/>
</vector>

View File

@@ -1,32 +1,33 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/colorSurface"> android:background="?attr/colorSurface">
<com.google.android.material.appbar.CollapsingToolbarLayout <androidx.core.widget.NestedScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
app:contentScrim="?attr/colorSurface" android:fillViewport="true"
app:layout_scrollFlags="scroll">
app:layout_scrollFlags="scroll" <com.google.android.material.appbar.CollapsingToolbarLayout
app:toolbarId="@+id/toolbar">
<com.lapism.search.widget.MaterialSearchView
android:id="@+id/ffms"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
app:layout_behavior="com.lapism.search.widget.SearchBehavior" /> app:contentScrim="?attr/colorSurface"
</com.google.android.material.appbar.CollapsingToolbarLayout> app:toolbarId="@+id/toolbar">
<com.lapism.search.widget.MaterialSearchView
android:id="@+id/ffms"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="com.lapism.search.widget.SearchBehavior" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</androidx.core.widget.NestedScrollView>
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
@@ -46,6 +47,4 @@
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -1,31 +1,50 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:foreground="?android:attr/selectableItemBackground" android:foreground="?android:attr/selectableItemBackground">
android:orientation="vertical">
<TextView <View
android:id="@+id/ta" android:id="@+id/vl"
android:layout_width="match_parent" android:layout_width="32dp"
android:layout_height="wrap_content" android:layout_height="32dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:fontFamily="@font/gotham" android:background="@drawable/ic_like"
android:text="TextView" app:layout_constraintBottom_toBottomOf="parent"
android:textColor="?attr/colorOnSurface" app:layout_constraintEnd_toEndOf="parent"
android:textSize="22sp" /> app:layout_constraintTop_toTopOf="parent"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"/>
<TextView <LinearLayout
android:id="@+id/tb"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:layout_marginStart="16dp" android:orientation="vertical">
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp" <TextView
android:layout_marginBottom="8dp" android:id="@+id/ta"
android:text="TextView" /> android:layout_width="match_parent"
</LinearLayout> android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:fontFamily="@font/gotham"
android:textColor="?attr/colorOnSurface"
android:textSize="22sp" />
<TextView
android:id="@+id/tb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -4,11 +4,11 @@
<!-- Primary brand color. --> <!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item> <item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item> <item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item> <item name="colorOnPrimary">@android:color/black</item>
<!-- Secondary brand color. --> <!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item> <item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item> <item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item> <item name="colorOnSecondary">@android:color/black</item>
<!-- Status bar color. --> <!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item> <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. --> <!-- Customize your theme here. -->

View File

@@ -1,12 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<color name="purple_200">#FFBB86FC</color> <color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color> <color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color> <color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="colorPrimary">#BA8D08</color> <color name="colorPrimary">#BA8D08</color>
<color name="colorPrimaryVariant">#FF9800</color> <color name="colorPrimaryVariant">#FF9800</color>
<color name="colorSecondary">#FF845E</color> <color name="colorSecondary">#FF845E</color>

View File

@@ -1,3 +0,0 @@
<resources>
<dimen name="fab_margin">16dp</dimen>
</resources>

View File

@@ -1,12 +1,3 @@
<resources> <resources>
<string name="app_name">SimpleDict</string> <string name="app_name">SimpleDict</string>
<string name="action_settings">Settings</string>
<!-- Strings used for fragments for navigation -->
<string name="first_fragment_label">First Fragment</string>
<string name="second_fragment_label">Second Fragment</string>
<string name="next">Next</string>
<string name="previous">Previous</string>
<string name="hello_first_fragment">Hello first fragment</string>
<string name="hello_second_fragment">Hello second fragment. Arg: %1$s</string>
</resources> </resources>

Binary file not shown.

View File

@@ -10,8 +10,8 @@
{ {
"type": "SINGLE", "type": "SINGLE",
"filters": [], "filters": [],
"versionCode": 4, "versionCode": 5,
"versionName": "1.2", "versionName": "1.3",
"outputFile": "app-winrelease.apk" "outputFile": "app-winrelease.apk"
} }
] ]