Merge pull request #202 from amnezia-vpn/fix/android_various_fixes

Fix/android various fixes
This commit is contained in:
pokamest 2023-03-29 15:15:17 +02:00 committed by GitHub
commit 7e663b05d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 293 additions and 96 deletions

View file

@ -287,6 +287,8 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
}
}
set(value) {
field = value
if (value) {
mBinder.dispatchEvent(VPNServiceBinder.EVENTS.connected, "")
mConnectionTime = System.currentTimeMillis()
@ -886,45 +888,4 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
class CloseableFd(val fd: FileDescriptor) : Closeable {
override fun close() = Os.close(fd)
}
fun saveAsFile(configContent: String?, suggestedFileName: String): String {
val rootDirPath = cacheDir.absolutePath
val rootDir = File(rootDirPath)
if (!rootDir.exists()) {
rootDir.mkdirs()
}
val fileName = if (!TextUtils.isEmpty(suggestedFileName)) suggestedFileName else "amnezia.cfg"
val file = File(rootDir, fileName)
try {
file.bufferedWriter().use { out -> out.write(configContent) }
return file.toString()
} catch (e: Exception) {
e.printStackTrace()
}
return ""
}
fun shareFile(attachmentFile: String?) {
try {
val intent = Intent(Intent.ACTION_SEND)
intent.type = "text/*"
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
val file = File(attachmentFile)
val uri = FileProvider.getUriForFile(this, "${BuildConfig.APPLICATION_ID}.fileprovider", file)
intent.putExtra(Intent.EXTRA_STREAM, uri)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val createChooser = Intent.createChooser(intent, "Config sharing")
createChooser.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(createChooser)
} catch (e: Exception) {
Log.i(tag, e.message.toString())
}
}
}

View file

@ -32,7 +32,6 @@ class VPNServiceBinder(service: VPNService) : Binder() {
const val resumeActivate = 7
const val setNotificationText = 8
const val setFallBackNotification = 9
const val shareConfig = 10
const val importConfig = 11
}
@ -139,20 +138,6 @@ class VPNServiceBinder(service: VPNService) : Binder() {
return true
}
ACTIONS.shareConfig -> {
val byteArray = data.createByteArray()
val json = byteArray?.let { String(it) }
val config = JSONObject(json)
val configContent = config.getString("data")
val suggestedName = config.getString("suggestedName")
val filePath = mService.saveAsFile(configContent, suggestedName)
Log.i(tag, "save file: $filePath")
mService.shareFile(filePath)
return true
}
ACTIONS.importConfig -> {
val buffer = data.readString()
@ -196,7 +181,6 @@ class VPNServiceBinder(service: VPNService) : Binder() {
try {
mListener?.let {
if (it.isBinderAlive) {
Log.i(tag, "Dispatching event: binder alive")
val data = Parcel.obtain()
data.writeByteArray(payload?.toByteArray(charset("UTF-8")))
it.transact(code, data, Parcel.obtain(), 0)

View file

@ -5,6 +5,8 @@
package org.amnezia.vpn.qt;
import android.Manifest
import android.content.ClipData
import android.content.ClipboardManager
import android.content.ComponentName
import android.content.ContentResolver
import android.content.Context
@ -37,6 +39,9 @@ class VPNActivity : org.qtproject.qt.android.bindings.QtActivity() {
private val STORAGE_PERMISSION_CODE = 42
private val CAMERA_ACTION_CODE = 101
private val CREATE_FILE_ACTION_CODE = 102
private var tmpFileContentToSave: String = ""
companion object {
private lateinit var instance: VPNActivity
@ -56,6 +61,14 @@ class VPNActivity : org.qtproject.qt.android.bindings.QtActivity() {
@JvmStatic fun sendToService(actionCode: Int, body: String) {
VPNActivity.getInstance().dispatchParcel(actionCode, body)
}
@JvmStatic fun saveFileAs(fileContent: String, suggestedName: String) {
VPNActivity.getInstance().saveFile(fileContent, suggestedName)
}
@JvmStatic fun putTextToClipboard(text: String) {
VPNActivity.getInstance().putToClipboard(text)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
@ -76,6 +89,18 @@ class VPNActivity : org.qtproject.qt.android.bindings.QtActivity() {
startActivityForResult(intent, CAMERA_ACTION_CODE)
}
private fun saveFile(fileContent: String, suggestedName: String) {
tmpFileContentToSave = fileContent
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "text/*"
putExtra(Intent.EXTRA_TITLE, suggestedName)
}
startActivityForResult(intent, CREATE_FILE_ACTION_CODE)
}
override fun getSystemService(name: String): Any? {
return if (Build.VERSION.SDK_INT >= 29 && name == "clipboard") {
// QT will always attempt to read the clipboard if content is there.
@ -99,8 +124,6 @@ class VPNActivity : org.qtproject.qt.android.bindings.QtActivity() {
if (!isBound) {
Log.d(TAG, "dispatchParcel: not bound")
return
} else {
Log.d(TAG, "dispatchParcel: bound")
}
val out: Parcel = Parcel.obtain()
@ -330,13 +353,38 @@ class VPNActivity : org.qtproject.qt.android.bindings.QtActivity() {
val extra = data?.getStringExtra("result") ?: ""
onActivityMessage(UI_EVENT_QR_CODE_RECEIVED, extra)
}
if (requestCode == CREATE_FILE_ACTION_CODE && resultCode == RESULT_OK) {
data?.data?.also { uri ->
alterDocument(uri)
}
}
}
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK && event.repeatCount == 0) {
onBackPressed()
return true
private fun alterDocument(uri: Uri) {
try {
applicationContext.contentResolver.openFileDescriptor(uri, "w")?.use { fd ->
FileOutputStream(fd.fileDescriptor).use { fos ->
fos.write(tmpFileContentToSave.toByteArray())
}
}
} catch (e: FileNotFoundException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
tmpFileContentToSave = ""
}
private fun putToClipboard(text: String) {
this.runOnUiThread {
val clipboard = applicationContext.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager?
if (clipboard != null) {
val clip: ClipData = ClipData.newPlainText("", text)
clipboard.setPrimaryClip(clip)
}
}
return super.onKeyDown(keyCode, event)
}
}