Work towards API 30 compatibility
This commit is contained in:
+1
-1
@@ -6,7 +6,7 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = 'com.tutpro.baresip'
|
applicationId = 'com.tutpro.baresip'
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 29
|
targetSdkVersion 30
|
||||||
versionCode = 163
|
versionCode = 163
|
||||||
versionName = '29.2.1'
|
versionName = '29.2.1'
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
|
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
|
tools:ignore="ScopedStorage" android:maxSdkVersion="28" />
|
||||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||||
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
||||||
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
|
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
|
||||||
|
|||||||
@@ -1103,18 +1103,17 @@ Java_com_tutpro_baresip_Api_account_1mediaaf(JNIEnv *env, jobject thiz, jstring
|
|||||||
return account_mediaaf(acc);
|
return account_mediaaf(acc);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Java_com_tutpro_baresip_Api_account_1set_1mediaaf(JNIEnv *env, jobject thiz, jstring jAcc, jint jAf) {
|
Java_com_tutpro_baresip_Api_account_1set_1mediaaf(JNIEnv *env, jobject thiz, jstring jAcc, jint jAf) {
|
||||||
const char *native_acc = (*env)->GetStringUTFChars(env, jAcc, 0);
|
const char *native_acc = (*env)->GetStringUTFChars(env, jAcc, 0);
|
||||||
struct account *acc = (struct account *)strtoul(native_acc, NULL, 10);
|
struct account *acc = (struct account *)strtoul(native_acc, NULL, 10);
|
||||||
(*env)->ReleaseStringUTFChars(env, jAcc, native_acc);
|
(*env)->ReleaseStringUTFChars(env, jAcc, native_acc);
|
||||||
LOGD("setting account mediaaf to '%d'\n", jAf);
|
LOGD("setting account mediaaf to '%d'\n", jAf);
|
||||||
account_set_mediaaf(acc, jAf);
|
return account_set_mediaaf(acc, jAf);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jstring JNICALL
|
JNIEXPORT jstring JNICALL
|
||||||
Java_com_tutpro_baresip_Api_account_1extra(JNIEnv *env, jobject thiz, jstring javaAcc)
|
Java_com_tutpro_baresip_Api_account_1extra(JNIEnv *env, jobject thiz, jstring javaAcc) {
|
||||||
{
|
|
||||||
const char *native_acc = (*env)->GetStringUTFChars(env, javaAcc, 0);
|
const char *native_acc = (*env)->GetStringUTFChars(env, javaAcc, 0);
|
||||||
struct account *acc = (struct account *) strtoul(native_acc, NULL, 10);
|
struct account *acc = (struct account *) strtoul(native_acc, NULL, 10);
|
||||||
(*env)->ReleaseStringUTFChars(env, javaAcc, native_acc);
|
(*env)->ReleaseStringUTFChars(env, javaAcc, native_acc);
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ object Api {
|
|||||||
external fun account_dtmfmode(acc: String): Int
|
external fun account_dtmfmode(acc: String): Int
|
||||||
external fun account_set_dtmfmode(acc: String, mode: Int): Int
|
external fun account_set_dtmfmode(acc: String, mode: Int): Int
|
||||||
external fun account_mediaaf(acc: String): Int
|
external fun account_mediaaf(acc: String): Int
|
||||||
external fun account_set_mediaaf(acc: String, af: Int)
|
external fun account_set_mediaaf(acc: String, af: Int): Int
|
||||||
external fun account_extra(acc: String): String
|
external fun account_extra(acc: String): String
|
||||||
external fun account_debug(acc: String)
|
external fun account_debug(acc: String)
|
||||||
|
|
||||||
|
|||||||
@@ -415,7 +415,7 @@ class BaresipService: Service() {
|
|||||||
Log.d(TAG, "uaAdd ${ua.account.aor} at BaresipService")
|
Log.d(TAG, "uaAdd ${ua.account.aor} at BaresipService")
|
||||||
uas.add(ua)
|
uas.add(ua)
|
||||||
if (ua.account.preferIPv6Media)
|
if (ua.account.preferIPv6Media)
|
||||||
Api.ua_set_media_af(ua.uap, Api.AF_INET6)
|
Api.account_set_mediaaf(ua.account.accp, Api.AF_INET6)
|
||||||
if (Api.ua_isregistered(uap)) {
|
if (Api.ua_isregistered(uap)) {
|
||||||
Log.d(TAG, "Ua ${ua.account.aor} is registered")
|
Log.d(TAG, "Ua ${ua.account.aor} is registered")
|
||||||
status.add(R.drawable.dot_green)
|
status.add(R.drawable.dot_green)
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import android.net.Uri
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.CountDownTimer
|
import android.os.CountDownTimer
|
||||||
|
import android.provider.DocumentsContract
|
||||||
|
import android.provider.MediaStore
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
import android.text.method.HideReturnsTransformationMethod
|
import android.text.method.HideReturnsTransformationMethod
|
||||||
@@ -21,6 +23,7 @@ import android.text.method.PasswordTransformationMethod
|
|||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
@@ -28,6 +31,8 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
|||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
import com.tutpro.baresip.databinding.ActivityMainBinding
|
import com.tutpro.baresip.databinding.ActivityMainBinding
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
import java.io.FileOutputStream
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
@@ -62,6 +67,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
private lateinit var stopState: String
|
private lateinit var stopState: String
|
||||||
private var speakerIcon: MenuItem? = null
|
private var speakerIcon: MenuItem? = null
|
||||||
private lateinit var swipeRefresh: SwipeRefreshLayout
|
private lateinit var swipeRefresh: SwipeRefreshLayout
|
||||||
|
private var downloadsInputStream: FileInputStream? = null
|
||||||
|
private var downloadsOutputStream: FileOutputStream? = null
|
||||||
|
|
||||||
private lateinit var baresipService: Intent
|
private lateinit var baresipService: Intent
|
||||||
|
|
||||||
@@ -1074,15 +1081,23 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
R.id.backup -> {
|
R.id.backup -> {
|
||||||
|
if (Build.VERSION.SDK_INT >= 29) {
|
||||||
|
pickupFileFromDownloads(BACKUP_CODE)
|
||||||
|
} else {
|
||||||
if (Utils.requestPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
if (Utils.requestPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||||
BACKUP_PERMISSION_REQUEST_CODE))
|
BACKUP_PERMISSION_REQUEST_CODE)) {
|
||||||
|
val path = BaresipService.downloadsPath + "/baresip.bs"
|
||||||
|
downloadsOutputStream = FileOutputStream(File(path))
|
||||||
askPassword(getString(R.string.encrypt_password))
|
askPassword(getString(R.string.encrypt_password))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
R.id.restore -> {
|
R.id.restore -> {
|
||||||
if (Utils.requestPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE,
|
if (Build.VERSION.SDK_INT >= 29 ||
|
||||||
|
Utils.requestPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||||
RESTORE_PERMISSION_REQUEST_CODE))
|
RESTORE_PERMISSION_REQUEST_CODE))
|
||||||
askPassword(getString(R.string.decrypt_password))
|
startRestore()
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.about -> {
|
R.id.about -> {
|
||||||
@@ -1163,6 +1178,27 @@ class MainActivity : AppCompatActivity() {
|
|||||||
updateIcons(Account.ofAor(activityAor)!!)
|
updateIcons(Account.ofAor(activityAor)!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BACKUP_CODE -> {
|
||||||
|
if (resultCode == Activity.RESULT_OK)
|
||||||
|
data?.data?.also {
|
||||||
|
Log.d(TAG, "******** $it")
|
||||||
|
downloadsOutputStream = applicationContext.contentResolver.openOutputStream(it)
|
||||||
|
as FileOutputStream
|
||||||
|
if (downloadsOutputStream != null)
|
||||||
|
askPassword(getString(R.string.encrypt_password))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RESTORE_CODE -> {
|
||||||
|
if (resultCode == Activity.RESULT_OK)
|
||||||
|
data?.data?.also {
|
||||||
|
downloadsInputStream = applicationContext.contentResolver.openInputStream(it)
|
||||||
|
as FileInputStream
|
||||||
|
if (downloadsInputStream != null)
|
||||||
|
askPassword(getString(R.string.decrypt_password))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ABOUT_CODE -> {
|
ABOUT_CODE -> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1176,7 +1212,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
when (requestCode) {
|
when (requestCode) {
|
||||||
|
|
||||||
RECORD_PERMISSION_REQUEST_CODE -> {
|
RECORD_PERMISSION_REQUEST_CODE -> {
|
||||||
if ((grantResults.size > 0) && (grantResults[0] != PackageManager.PERMISSION_GRANTED))
|
if ((grantResults.isNotEmpty()) && (grantResults[0] != PackageManager.PERMISSION_GRANTED))
|
||||||
Utils.alertView(this, getString(R.string.notice),
|
Utils.alertView(this, getString(R.string.notice),
|
||||||
getString(R.string.no_calls), ::startBaresip)
|
getString(R.string.no_calls), ::startBaresip)
|
||||||
else
|
else
|
||||||
@@ -1184,16 +1220,49 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BACKUP_PERMISSION_REQUEST_CODE ->
|
BACKUP_PERMISSION_REQUEST_CODE ->
|
||||||
if ((grantResults.size > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED))
|
if ((grantResults.isNotEmpty()) && (grantResults[0] == PackageManager.PERMISSION_GRANTED))
|
||||||
askPassword(getString(R.string.encrypt_password))
|
askPassword(getString(R.string.encrypt_password))
|
||||||
|
|
||||||
RESTORE_PERMISSION_REQUEST_CODE ->
|
RESTORE_PERMISSION_REQUEST_CODE ->
|
||||||
if ((grantResults.size > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED))
|
if ((grantResults.isNotEmpty()) && (grantResults[0] == PackageManager.PERMISSION_GRANTED))
|
||||||
askPassword(getString(R.string.decrypt_password))
|
startRestore()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun startRestore() {
|
||||||
|
if (Build.VERSION.SDK_INT >= 29) {
|
||||||
|
pickupFileFromDownloads(RESTORE_CODE)
|
||||||
|
} else {
|
||||||
|
val path = BaresipService.downloadsPath + "/baresip.bs"
|
||||||
|
downloadsInputStream = FileInputStream(File(path))
|
||||||
|
askPassword(getString(R.string.decrypt_password))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(29)
|
||||||
|
private fun pickupFileFromDownloads(activityCode: Int) {
|
||||||
|
val intent = when (activityCode) {
|
||||||
|
BACKUP_CODE -> {
|
||||||
|
Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||||
|
addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
type = "application/octet-stream"
|
||||||
|
putExtra(Intent.EXTRA_TITLE, "baresip.bs")
|
||||||
|
putExtra(DocumentsContract.EXTRA_INITIAL_URI, MediaStore.Downloads.EXTERNAL_CONTENT_URI)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RESTORE_CODE -> {
|
||||||
|
Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
||||||
|
addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
type = "application/octet-stream"
|
||||||
|
putExtra(DocumentsContract.EXTRA_INITIAL_URI, MediaStore.Downloads.EXTERNAL_CONTENT_URI)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
startActivityForResult(intent, activityCode)
|
||||||
|
}
|
||||||
|
|
||||||
private fun quitRestart(reStart: Boolean) {
|
private fun quitRestart(reStart: Boolean) {
|
||||||
if (stopState == "initial") {
|
if (stopState == "initial") {
|
||||||
Log.d(TAG, "quitRestart Restart = $reStart")
|
Log.d(TAG, "quitRestart Restart = $reStart")
|
||||||
@@ -1378,54 +1447,57 @@ class MainActivity : AppCompatActivity() {
|
|||||||
File(BaresipService.filesPath).walk().forEach {
|
File(BaresipService.filesPath).walk().forEach {
|
||||||
if (it.name.endsWith(".png")) files.add(it.name)
|
if (it.name.endsWith(".png")) files.add(it.name)
|
||||||
}
|
}
|
||||||
val bsFile = getString(R.string.app_name) + ".bs"
|
val zipFile = getString(R.string.app_name_plus) + ".zip"
|
||||||
val backupFilePath = BaresipService.downloadsPath + "/$bsFile"
|
|
||||||
val zipFile = getString(R.string.app_name) + ".zip"
|
|
||||||
val zipFilePath = BaresipService.filesPath + "/$zipFile"
|
val zipFilePath = BaresipService.filesPath + "/$zipFile"
|
||||||
if (!Utils.zip(files, zipFile)) {
|
if (!Utils.zip(files, zipFile)) {
|
||||||
Log.w(TAG, "Failed to write zip file '$zipFile'")
|
Log.w(TAG, "Failed to write zip file '$zipFile'")
|
||||||
Utils.alertView(this, getString(R.string.error),
|
Utils.alertView(this, getString(R.string.error),
|
||||||
String.format(getString(R.string.backup_failed), bsFile))
|
String.format(getString(R.string.backup_failed),
|
||||||
|
downloadsOutputFile))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val content = Utils.getFileContents(zipFilePath)
|
val content = Utils.getFileContents(zipFilePath)
|
||||||
if (content == null) {
|
if (content == null) {
|
||||||
Log.w(TAG, "Failed to read zip file '$zipFile'")
|
Log.w(TAG, "Failed to read zip file '$zipFile'")
|
||||||
Utils.alertView(this, getString(R.string.error),
|
Utils.alertView(this, getString(R.string.error),
|
||||||
String.format(getString(R.string.backup_failed), bsFile))
|
String.format(getString(R.string.backup_failed),
|
||||||
|
downloadsOutputFile))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!Utils.encryptToFile(backupFilePath, content, password)) {
|
if (!Utils.encryptToStream(downloadsOutputStream, content, password)) {
|
||||||
Utils.alertView(this, getString(R.string.error),
|
Utils.alertView(this, getString(R.string.error),
|
||||||
String.format(getString(R.string.backup_failed), bsFile))
|
String.format(getString(R.string.backup_failed),
|
||||||
|
downloadsOutputFile))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
Utils.alertView(this, getString(R.string.info),
|
Utils.alertView(this, getString(R.string.info),
|
||||||
String.format(getString(R.string.backed_up), bsFile))
|
String.format(getString(R.string.backed_up),
|
||||||
|
downloadsOutputFile))
|
||||||
Utils.deleteFile(File(zipFilePath))
|
Utils.deleteFile(File(zipFilePath))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun restore(password: String) {
|
private fun restore(password: String) {
|
||||||
val bsFile = getString(R.string.app_name) + ".bs"
|
val zipFile = getString(R.string.app_name_plus) + ".zip"
|
||||||
val backupFilePath = BaresipService.downloadsPath + "/$bsFile"
|
|
||||||
val zipFile = getString(R.string.app_name) + ".zip"
|
|
||||||
val zipFilePath = BaresipService.filesPath + "/$zipFile"
|
val zipFilePath = BaresipService.filesPath + "/$zipFile"
|
||||||
val zipData = Utils.decryptFromFile(backupFilePath, password)
|
val zipData = Utils.decryptFromStream(downloadsInputStream, password)
|
||||||
if (zipData == null) {
|
if (zipData == null) {
|
||||||
Utils.alertView(this, getString(R.string.error),
|
Utils.alertView(this, getString(R.string.error),
|
||||||
String.format(getString(R.string.restore_failed), bsFile))
|
String.format(getString(R.string.restore_failed),
|
||||||
|
downloadsInputFile))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!Utils.putFileContents(zipFilePath, zipData)) {
|
if (!Utils.putFileContents(zipFilePath, zipData)) {
|
||||||
Log.w(TAG, "Failed to write zip file '$zipFile'")
|
Log.w(TAG, "Failed to write zip file '$zipFile'")
|
||||||
Utils.alertView(this, getString(R.string.error),
|
Utils.alertView(this, getString(R.string.error),
|
||||||
String.format(getString(R.string.restore_failed), bsFile))
|
String.format(getString(R.string.restore_failed),
|
||||||
|
downloadsInputFile))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!Utils.unZip(zipFilePath)) {
|
if (!Utils.unZip(zipFilePath)) {
|
||||||
Log.w(TAG, "Failed to unzip file '$zipFile'")
|
Log.w(TAG, "Failed to unzip file '$zipFile'")
|
||||||
Utils.alertView(this, getString(R.string.error),
|
Utils.alertView(this, getString(R.string.error),
|
||||||
String.format(getString(R.string.restore_failed), bsFile))
|
String.format(getString(R.string.restore_failed),
|
||||||
|
downloadsInputFile))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
Utils.deleteFile(File(zipFilePath))
|
Utils.deleteFile(File(zipFilePath))
|
||||||
@@ -1797,6 +1869,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
const val CONTACT_CODE = 7
|
const val CONTACT_CODE = 7
|
||||||
const val CHATS_CODE = 8
|
const val CHATS_CODE = 8
|
||||||
const val CHAT_CODE = 9
|
const val CHAT_CODE = 9
|
||||||
|
const val BACKUP_CODE = 10
|
||||||
|
const val RESTORE_CODE = 11
|
||||||
|
|
||||||
const val BACKUP_PERMISSION_REQUEST_CODE = 1
|
const val BACKUP_PERMISSION_REQUEST_CODE = 1
|
||||||
const val RESTORE_PERMISSION_REQUEST_CODE = 2
|
const val RESTORE_PERMISSION_REQUEST_CODE = 2
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ import android.graphics.Bitmap.createScaledBitmap
|
|||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.net.LinkAddress
|
import android.net.LinkAddress
|
||||||
import android.net.LinkProperties
|
import android.net.LinkProperties
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.provider.OpenableColumns
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -418,14 +420,14 @@ object Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getFileContents(filePath: String): ByteArray? {
|
fun getFileContents(filePath: String): ByteArray? {
|
||||||
try {
|
return try {
|
||||||
return File(filePath).readBytes()
|
File(filePath).readBytes()
|
||||||
} catch (e: FileNotFoundException) {
|
} catch (e: FileNotFoundException) {
|
||||||
Log.e("Baresip", "File '$filePath' not found: ${e.printStackTrace()}")
|
Log.e("Baresip", "File '$filePath' not found: ${e.printStackTrace()}")
|
||||||
return null
|
null
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("Baresip", "Failed to read file '$filePath': ${e.printStackTrace()}")
|
Log.e("Baresip", "Failed to read file '$filePath': ${e.printStackTrace()}")
|
||||||
return null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,6 +442,18 @@ object Utils {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun fileNameOfUri(ctx: Context, uri: Uri): String {
|
||||||
|
val cursor = ctx.contentResolver.query(uri, null, null, null, null)
|
||||||
|
var name = ""
|
||||||
|
if (cursor != null) {
|
||||||
|
val index = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
|
||||||
|
cursor.moveToFirst()
|
||||||
|
name = cursor.getString(index)
|
||||||
|
cursor.close()
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
fun saveBitmap(bitmap: Bitmap, file: File): Boolean {
|
fun saveBitmap(bitmap: Bitmap, file: File): Boolean {
|
||||||
if (file.exists()) file.delete()
|
if (file.exists()) file.delete()
|
||||||
try {
|
try {
|
||||||
@@ -504,29 +518,28 @@ object Utils {
|
|||||||
return plainData
|
return plainData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun encryptToStream(stream: FileOutputStream?, content: ByteArray, password: String): Boolean {
|
||||||
fun encryptToFile(filePath: String, content: ByteArray, password: String): Boolean {
|
|
||||||
val obj = encrypt(content, password.toCharArray())
|
val obj = encrypt(content, password.toCharArray())
|
||||||
try {
|
try {
|
||||||
ObjectOutputStream(FileOutputStream(File(filePath))).use {
|
ObjectOutputStream(stream).use {
|
||||||
it.writeObject(obj)
|
it.writeObject(obj)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("Baresip", "Write failed: ${e.printStackTrace()}")
|
Log.w("Baresip", "encryptToStream failed: $e")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun decryptFromFile(filePath: String, password: String): ByteArray? {
|
fun decryptFromStream(stream: FileInputStream?, password: String): ByteArray? {
|
||||||
var plainData: ByteArray? = null
|
var plainData: ByteArray? = null
|
||||||
try {
|
try {
|
||||||
ObjectInputStream(FileInputStream(File(filePath))).use {
|
ObjectInputStream(stream).use {
|
||||||
val obj = it.readObject() as Crypto
|
val obj = it.readObject() as Crypto
|
||||||
plainData = decrypt(obj, password.toCharArray())
|
plainData = decrypt(obj, password.toCharArray())
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("Baresip", "Decrypt failed from file '$filePath'")
|
Log.w("Baresip", "decryptFromStream failed: $e")
|
||||||
}
|
}
|
||||||
return plainData
|
return plainData
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user