Files now saving with the file picker, not with the sharing mechanism
This commit is contained in:
parent
5f85bf62f5
commit
8d45af2034
6 changed files with 53 additions and 64 deletions
|
@ -888,45 +888,4 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
||||||
class CloseableFd(val fd: FileDescriptor) : Closeable {
|
class CloseableFd(val fd: FileDescriptor) : Closeable {
|
||||||
override fun close() = Os.close(fd)
|
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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ class VPNServiceBinder(service: VPNService) : Binder() {
|
||||||
const val resumeActivate = 7
|
const val resumeActivate = 7
|
||||||
const val setNotificationText = 8
|
const val setNotificationText = 8
|
||||||
const val setFallBackNotification = 9
|
const val setFallBackNotification = 9
|
||||||
const val shareConfig = 10
|
|
||||||
const val importConfig = 11
|
const val importConfig = 11
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,20 +138,6 @@ class VPNServiceBinder(service: VPNService) : Binder() {
|
||||||
return true
|
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 -> {
|
ACTIONS.importConfig -> {
|
||||||
val buffer = data.readString()
|
val buffer = data.readString()
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,9 @@ class VPNActivity : org.qtproject.qt.android.bindings.QtActivity() {
|
||||||
private val STORAGE_PERMISSION_CODE = 42
|
private val STORAGE_PERMISSION_CODE = 42
|
||||||
|
|
||||||
private val CAMERA_ACTION_CODE = 101
|
private val CAMERA_ACTION_CODE = 101
|
||||||
|
private val CREATE_FILE_ACTION_CODE = 102
|
||||||
|
|
||||||
|
private var tmpFileContentToSave: String = ""
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private lateinit var instance: VPNActivity
|
private lateinit var instance: VPNActivity
|
||||||
|
@ -56,6 +59,10 @@ class VPNActivity : org.qtproject.qt.android.bindings.QtActivity() {
|
||||||
@JvmStatic fun sendToService(actionCode: Int, body: String) {
|
@JvmStatic fun sendToService(actionCode: Int, body: String) {
|
||||||
VPNActivity.getInstance().dispatchParcel(actionCode, body)
|
VPNActivity.getInstance().dispatchParcel(actionCode, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic fun saveFileAs(fileContent: String, suggestedName: String) {
|
||||||
|
VPNActivity.getInstance().saveFile(fileContent, suggestedName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -76,6 +83,18 @@ class VPNActivity : org.qtproject.qt.android.bindings.QtActivity() {
|
||||||
startActivityForResult(intent, CAMERA_ACTION_CODE)
|
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? {
|
override fun getSystemService(name: String): Any? {
|
||||||
return if (Build.VERSION.SDK_INT >= 29 && name == "clipboard") {
|
return if (Build.VERSION.SDK_INT >= 29 && name == "clipboard") {
|
||||||
// QT will always attempt to read the clipboard if content is there.
|
// QT will always attempt to read the clipboard if content is there.
|
||||||
|
@ -328,5 +347,27 @@ class VPNActivity : org.qtproject.qt.android.bindings.QtActivity() {
|
||||||
val extra = data?.getStringExtra("result") ?: ""
|
val extra = data?.getStringExtra("result") ?: ""
|
||||||
onActivityMessage(UI_EVENT_QR_CODE_RECEIVED, extra)
|
onActivityMessage(UI_EVENT_QR_CODE_RECEIVED, extra)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (requestCode == CREATE_FILE_ACTION_CODE && resultCode == RESULT_OK) {
|
||||||
|
data?.data?.also { uri ->
|
||||||
|
alterDocument(uri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,12 +209,7 @@ void AndroidController::setNotificationText(const QString& title,
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidController::shareConfig(const QString& configContent, const QString& suggestedName) {
|
void AndroidController::shareConfig(const QString& configContent, const QString& suggestedName) {
|
||||||
QJsonObject rootObject;
|
AndroidVPNActivity::saveFileAs(configContent, suggestedName);
|
||||||
rootObject["data"] = configContent;
|
|
||||||
rootObject["suggestedName"] = suggestedName;
|
|
||||||
QJsonDocument doc(rootObject);
|
|
||||||
|
|
||||||
AndroidVPNActivity::sendToService(ServiceAction::ACTION_SHARE_CONFIG, doc.toJson());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -57,6 +57,14 @@ void AndroidVPNActivity::startQrCodeReader()
|
||||||
QJniObject::callStaticMethod<void>(CLASSNAME, "startQrCodeReader", "()V");
|
QJniObject::callStaticMethod<void>(CLASSNAME, "startQrCodeReader", "()V");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AndroidVPNActivity::saveFileAs(QString fileContent, QString suggestedFilename) {
|
||||||
|
QJniObject::callStaticMethod<void>(
|
||||||
|
CLASSNAME,
|
||||||
|
"saveFileAs", "(Ljava/lang/String;Ljava/lang/String;)V",
|
||||||
|
QJniObject::fromString(fileContent).object<jstring>(),
|
||||||
|
QJniObject::fromString(suggestedFilename).object<jstring>());
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
AndroidVPNActivity* AndroidVPNActivity::instance() {
|
AndroidVPNActivity* AndroidVPNActivity::instance() {
|
||||||
if (s_instance == nullptr) {
|
if (s_instance == nullptr) {
|
||||||
|
@ -70,9 +78,9 @@ AndroidVPNActivity* AndroidVPNActivity::instance() {
|
||||||
void AndroidVPNActivity::sendToService(ServiceAction type, const QString& data) {
|
void AndroidVPNActivity::sendToService(ServiceAction type, const QString& data) {
|
||||||
int messageType = (int)type;
|
int messageType = (int)type;
|
||||||
|
|
||||||
QJniEnvironment env;
|
|
||||||
QJniObject::callStaticMethod<void>(
|
QJniObject::callStaticMethod<void>(
|
||||||
CLASSNAME, "sendToService", "(ILjava/lang/String;)V",
|
CLASSNAME,
|
||||||
|
"sendToService", "(ILjava/lang/String;)V",
|
||||||
static_cast<int>(messageType),
|
static_cast<int>(messageType),
|
||||||
QJniObject::fromString(data).object<jstring>());
|
QJniObject::fromString(data).object<jstring>());
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,7 @@ public:
|
||||||
static void sendToService(ServiceAction type, const QString& data);
|
static void sendToService(ServiceAction type, const QString& data);
|
||||||
static void connectService();
|
static void connectService();
|
||||||
static void startQrCodeReader();
|
static void startQrCodeReader();
|
||||||
|
static void saveFileAs(QString fileContent, QString suggestedFilename);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void serviceConnected();
|
void serviceConnected();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue