This commit is contained in:
LUX-Timber 2024-04-03 16:57:44 +08:00
parent 5d67f8e7ca
commit 6f0f6d3d72
7 changed files with 264 additions and 16 deletions

View File

@ -53,6 +53,8 @@ dependencies {
implementation 'com.github.bumptech.glide:glide:4.12.0' implementation 'com.github.bumptech.glide:glide:4.12.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
implementation 'com.github.omicronapps:7-Zip-JBinding-4Android:Release-16.02-2.02'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
} }

View File

@ -1,9 +1,15 @@
package com.timber.soft.newkeyboard.activity package com.timber.soft.newkeyboard.activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.provider.Settings
import android.view.View import android.view.View
import android.view.inputmethod.InputMethodInfo
import android.view.inputmethod.InputMethodManager
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.timber.soft.newkeyboard.databinding.ActivityApplyBinding import com.timber.soft.newkeyboard.databinding.ActivityApplyBinding
import com.timber.soft.newkeyboard.tools.StatusBarTools import com.timber.soft.newkeyboard.tools.StatusBarTools
@ -11,6 +17,7 @@ import com.timber.soft.newkeyboard.tools.StatusBarTools
class ApplyActivity : AppCompatActivity() { class ApplyActivity : AppCompatActivity() {
private lateinit var binding: ActivityApplyBinding private lateinit var binding: ActivityApplyBinding
private lateinit var inputManager: InputMethodManager
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -25,12 +32,57 @@ class ApplyActivity : AppCompatActivity() {
(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE) or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE) or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
window.statusBarColor = Color.TRANSPARENT window.statusBarColor = Color.TRANSPARENT
} }
inputManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
binding.applyBack.setOnClickListener() { binding.applyBack.setOnClickListener() {
finish() finish()
} }
binding.idStep1.setOnClickListener() {
applyKeyboard()
}
binding.idStep2.setOnClickListener() {
chooseKeyboard()
} }
} }
override fun onResume() {
super.onResume()
updateUi()
}
private fun chooseKeyboard() {
inputManager.showInputMethodPicker()
}
private fun applyKeyboard() {
Intent(Settings.ACTION_INPUT_METHOD_SETTINGS).apply {
startActivity(this)
}
}
private fun updateUi() {
binding.idStep1.setSelected(isEnable())
binding.idStep2.setSelected(isChoose())
}
private fun isChoose(): Boolean {
Settings.Secure.getString(contentResolver, Settings.Secure.DEFAULT_INPUT_METHOD).let { id ->
return id.startsWith(packageName)
} ?: return false
}
private fun isEnable(): Boolean {
for (info: InputMethodInfo in inputManager.enabledInputMethodList) {
if (info.id.startsWith(packageName)) {
return true
}
}
return false
}
inner class StepReceive : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
updateUi()
}
}
}

View File

@ -1,31 +1,48 @@
package com.timber.soft.newkeyboard.activity package com.timber.soft.newkeyboard.activity
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.provider.Settings
import android.view.View import android.view.View
import android.view.inputmethod.InputMethodInfo
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.engine.GlideException import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target import com.bumptech.glide.request.target.Target
import com.timber.soft.newkeyboard.R import com.timber.soft.newkeyboard.R
import com.timber.soft.newkeyboard.databinding.ActivityDetailsBinding import com.timber.soft.newkeyboard.databinding.ActivityDetailsBinding
import com.timber.soft.newkeyboard.model.DataModel import com.timber.soft.newkeyboard.model.DataModel
import com.timber.soft.newkeyboard.tools.AppVal
import com.timber.soft.newkeyboard.tools.StatusBarTools import com.timber.soft.newkeyboard.tools.StatusBarTools
import net.sf.sevenzipjbinding.ArchiveFormat
import net.sf.sevenzipjbinding.SevenZip
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream
import net.sf.sevenzipjbinding.impl.RandomAccessFileOutStream
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.InputStream
import java.io.RandomAccessFile
class DetailsActivity : AppCompatActivity() { class DetailsActivity : AppCompatActivity() {
private lateinit var binding: ActivityDetailsBinding private lateinit var binding: ActivityDetailsBinding
private lateinit var inputManager: InputMethodManager
private lateinit var previewUrl: String private lateinit var previewUrl: String
private lateinit var zipPath: String private lateinit var zipPath: String
private lateinit var dataModel: DataModel
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -41,9 +58,14 @@ class DetailsActivity : AppCompatActivity() {
window.statusBarColor = Color.TRANSPARENT window.statusBarColor = Color.TRANSPARENT
} }
val dataModel = intent.getSerializableExtra("KEY_EXTRA") as DataModel inputManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
dataModel = intent.getSerializableExtra("KEY_EXTRA") as DataModel
previewUrl = dataModel.thumb previewUrl = dataModel.thumb
zipPath = dataModel.zipUrl val cacheDir = cacheDir
val dataModelUrl = dataModel.zipUrl
zipPath = "$cacheDir/$dataModelUrl"
@ -89,8 +111,7 @@ class DetailsActivity : AppCompatActivity() {
// 淡入动画 // 淡入动画
.transition(DrawableTransitionOptions.withCrossFade()) .transition(DrawableTransitionOptions.withCrossFade())
// 加载失败占位图 // 加载失败占位图
.error(R.drawable.png_loading_err) .error(R.drawable.png_loading_err).transform(transformation)
.transform(transformation)
.into(binding.themeImage) .into(binding.themeImage)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
@ -98,9 +119,181 @@ class DetailsActivity : AppCompatActivity() {
} }
private fun applyTheme() { private fun applyTheme() {
// 检查是否启动键盘并设置
if (!isEnable() || !isChoose()) {
val intent = Intent(this, ApplyActivity::class.java)
startActivity(intent)
return
}
binding.themeProgressbar.visibility = View.VISIBLE
val file = File(zipPath)
// 判断缓存中是否存在文件
if (file.exists()) {
val allThemePath: String = getAllThemePath(dataModel.title)
val edit = sp.edit()
edit.run {
putString(AppVal.KEY_ALL_PATH, allThemePath)
apply()
}
} else {
getZipData(dataModel.title, dataModel.zipUrl, this,this::onResult)
}
}
private fun onResult(isSuccess: Boolean, path: String) {
binding.themeProgressbar.visibility = View.GONE
if (isSuccess) {
val lastIndexOf: Int = path.lastIndexOf(AppVal.res_path)
val substring = path.subSequence(0, lastIndexOf + AppVal.res_path.length).toString()
val edit = sp.edit()
edit.run {
putString(AppVal.KEY_ALL_PATH, substring)
apply()
}
edit.run {
putString(dataModel.title, substring)
apply()
}
Toast.makeText(this, getString(R.string.succ_apply), Toast.LENGTH_LONG).show()
finish()
} else {
Toast.makeText(this, getString(R.string.fail_apply), Toast.LENGTH_LONG).show()
}
}
interface ApplyListener {
fun applyListener(isSuccess: Boolean, str: String)
}
private fun getZipData(title: String, url: String, con: Context, listener: ApplyListener) {
Glide.with(con).asFile().load(url).addListener(object : RequestListener<File> {
override fun onLoadFailed(
e: GlideException?, model: Any?, target: Target<File>, isFirstResource: Boolean
): Boolean {
listener.applyListener(false, "")
return false
}
override fun onResourceReady(
resource: File,
model: Any,
target: Target<File>?,
dataSource: DataSource,
isFirstResource: Boolean
): Boolean {
val fileInputStream = FileInputStream(resource)
dealFile(title, url, fileInputStream, listener)
return false
}
}).preload()
}
private fun dealFile(
title: String, url: String, input: FileInputStream, listener: ApplyListener
) {
val zipPath = "${cacheDir}/${title}_ZIP"
val unPath = "${cacheDir}/${title}"
val zipBoolean = writeNewFile(input, zipPath)
val randomAccessFileInStream =
RandomAccessFileInStream(RandomAccessFile(File(zipPath), "r"))
val openInArchive = SevenZip.openInArchive(
ArchiveFormat.SEVEN_ZIP, randomAccessFileInStream
)
var out: RandomAccessFileOutStream? = null
if (zipBoolean) {
try {
var filePath: String = ""
openInArchive.simpleInterface.archiveItems.forEach { item ->
if (!item.isFolder) {
val file = File(unPath, item.path)
out = RandomAccessFileOutStream(RandomAccessFile(file, "rw"))
item.extractSlow(out)
filePath = file.path
} else {
File(unPath, item.path).mkdirs()
}
}
listener.applyListener(true, filePath)
} catch (ex: Exception) {
listener.applyListener(false, "")
} finally {
openInArchive.close()
randomAccessFileInStream.close()
out?.close()
}
}
}
private fun writeNewFile(input: InputStream, filePath: String): Boolean {
var stream: FileOutputStream? = null
var outStream: ByteArrayOutputStream? = null
try {
val outStream = ByteArrayOutputStream()
val bytes = ByteArray(4096)
var length = 0
while (input.read(bytes).also {
length = it
} != -1) {
outStream.write(bytes, 0, length)
}
val file = File(filePath)
if (!file.exists()) {
file.createNewFile()
}
stream = FileOutputStream(file)
stream.run {
write(outStream.toByteArray())
}
outStream.close()
stream.close()
return true
} catch (ex: Exception) {
outStream?.close()
stream?.close()
return false
}
}
private val sp: SharedPreferences = getSharedPreferences(
AppVal.SHARE_NAME, Context.MODE_PRIVATE
)
private fun getAllThemePath(zip: String): String {
val result = sp.getString(zip, "")
return result!!
}
/**
* 检查是否设置键盘
*/
private fun isChoose(): Boolean {
Settings.Secure.getString(contentResolver, Settings.Secure.DEFAULT_INPUT_METHOD).let { id ->
return id.startsWith(packageName)
} ?: return false
}
/**
* 检查是否启用键盘
*/
private fun isEnable(): Boolean {
for (info: InputMethodInfo in inputManager.enabledInputMethodList) {
if (info.id.startsWith(packageName)) {
return true
}
}
return false
} }
} }

View File

@ -2,7 +2,4 @@ package com.timber.soft.newkeyboard.tools
object ImgTools { object ImgTools {
} }

View File

@ -53,7 +53,7 @@
android:layout_height="43dp" android:layout_height="43dp"
android:layout_below="@id/theme_image" android:layout_below="@id/theme_image"
android:layout_marginStart="15dp" android:layout_marginStart="15dp"
android:layout_marginTop="26dp" android:layout_marginTop="64dp"
android:layout_marginEnd="15dp" android:layout_marginEnd="15dp"
android:background="@drawable/shape_theme_set" android:background="@drawable/shape_theme_set"
android:gravity="center" android:gravity="center"

View File

@ -9,4 +9,6 @@
<string name="more_feature">Activate Soft Keyboard to enable more features!</string> <string name="more_feature">Activate Soft Keyboard to enable more features!</string>
<string name="apply_step1_select">Step 1: Select</string> <string name="apply_step1_select">Step 1: Select</string>
<string name="apply_step2_eanble">Step 2: Enable</string> <string name="apply_step2_eanble">Step 2: Enable</string>
<string name="succ_apply">Application successful</string>
<string name="fail_apply">Application failed, please try again</string>
</resources> </resources>

View File

@ -9,6 +9,7 @@ pluginManagement {
} }
mavenCentral() mavenCentral()
gradlePluginPortal() gradlePluginPortal()
maven { url 'https://jitpack.io' }
} }
} }
dependencyResolutionManagement { dependencyResolutionManagement {
@ -16,6 +17,7 @@ dependencyResolutionManagement {
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
maven { url 'https://jitpack.io' }
} }
} }