Files
armorpaint/base/sources/backends/KincActivity.kt
T
2025-03-09 17:02:12 +01:00

256 lines
7.9 KiB
Kotlin

package org.armory3d
import android.app.NativeActivity
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.os.Vibrator
import android.os.VibrationEffect
import android.os.Build
import android.view.KeyEvent
import android.view.View
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import kotlin.system.exitProcess
import android.content.ContentResolver;
import android.util.Log
import android.view.DragAndDropPermissions;
import android.view.DragEvent;
import android.webkit.MimeTypeMap;
import android.view.DragEvent.ACTION_DRAG_STARTED;
import android.view.DragEvent.ACTION_DROP;
import androidx.core.database.getStringOrNull
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import kotlin.math.log
class IronActivity: NativeActivity(), KeyEvent.Callback {
companion object {
var instance: IronActivity? = null
@JvmStatic
fun showKeyboard() {
instance!!.inputManager!!.showSoftInput(instance!!.window.decorView, 0)
}
@JvmStatic
fun hideKeyboard() {
instance!!.inputManager!!.hideSoftInputFromWindow(instance!!.window.decorView.windowToken, 0)
instance!!.delayedHideSystemUI()
}
@JvmStatic
fun loadURL(url: String) {
val i = Intent(Intent.ACTION_VIEW, Uri.parse(url))
instance!!.startActivity(i)
}
@JvmStatic
fun getLanguage(): String {
return java.util.Locale.getDefault().language
}
@JvmStatic
fun getRotation(): Int {
val context: Context = instance!!.applicationContext
val manager: WindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
return manager.defaultDisplay.rotation
}
@JvmStatic
fun getScreenDpi(): Int {
val context: Context = instance!!.applicationContext
val manager: WindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
val metrics: android.util.DisplayMetrics = android.util.DisplayMetrics()
manager.defaultDisplay.getMetrics(metrics)
return metrics.xdpi.toInt()
}
@JvmStatic
fun getRefreshRate(): Int {
val context: Context = instance!!.applicationContext
val manager: WindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
return manager.defaultDisplay.refreshRate.toInt()
}
@JvmStatic
fun getDisplayWidth(): Int {
val context: Context = instance!!.applicationContext
val manager: WindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
val size: android.graphics.Point = android.graphics.Point()
manager.defaultDisplay.getRealSize(size)
return size.x
}
@JvmStatic
fun getDisplayHeight(): Int {
val context: Context = instance!!.applicationContext
val manager: WindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
val size: android.graphics.Point = android.graphics.Point()
manager.defaultDisplay.getRealSize(size)
return size.y
}
@JvmStatic
fun stop() {
instance!!.runOnUiThread {
fun run() {
instance!!.finish()
exitProcess(0)
}
}
}
class MyHandler(private val ironActivity: IronActivity) : Handler() {
override fun handleMessage(msg: Message) {
ironActivity.hideSystemUI()
}
}
@JvmStatic
public fun pickFile() {
val intent: Intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "*/*"
instance!!.startActivityForResult(Intent.createChooser(intent, "Select File"), 1)
}
}
var inputManager: InputMethodManager? = null
private var isDisabledStickyImmersiveMode = false
private val hideSystemUIHandler = MyHandler(this)
override fun onCreate(state: Bundle?) {
super.onCreate(state)
hideSystemUI()
instance = this
inputManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
isDisabledStickyImmersiveMode = try {
val ai: ApplicationInfo = packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA)
val bundle: Bundle = ai.metaData
bundle.getBoolean("disableStickyImmersiveMode")
} catch (e: PackageManager.NameNotFoundException) {
false
} catch (e: NullPointerException) {
false
}
window.decorView.setOnDragListener(
fun (view: View, dragEvent: DragEvent): Boolean {
if (dragEvent.action == ACTION_DRAG_STARTED) return true
if (dragEvent.action == ACTION_DROP) {
val dropPermissions = requestDragAndDropPermissions(dragEvent)
importFile(dragEvent.clipData.getItemAt(0).uri)
dropPermissions.release()
return true
}
return false
}
);
}
private fun hideSystemUI() {
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
}
private fun delayedHideSystemUI() {
hideSystemUIHandler.removeMessages(0)
if (!isDisabledStickyImmersiveMode) {
hideSystemUIHandler.sendEmptyMessageDelayed(0, 300)
}
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
delayedHideSystemUI()
}
else {
hideSystemUIHandler.removeMessages(0)
}
}
override fun onKeyMultiple(keyCode: Int, count: Int, event: KeyEvent): Boolean {
this.nativeIronKeyPress(event.characters)
return false
}
private external fun nativeIronKeyPress(chars: String)
private external fun onAndroidFilePicked(pickedPath: String)
private external fun getMobileTitle(): String
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 1 && resultCode == RESULT_OK) {
importFile(data.data!!)
}
}
private fun importFile(pickedFile: Uri) {
val resolver: ContentResolver = applicationContext.contentResolver
val inps: InputStream = resolver.openInputStream(pickedFile)!!
try {
val bis: BufferedInputStream = BufferedInputStream(inps)
val dir: File = File(filesDir.absolutePath + "/" + getMobileTitle())
dir.mkdirs()
var path: List<String> = pickedFile.path!!.split("/")
// Samsung files app removes extension from fileName
val filePath: Array<String> = arrayOf(android.provider.MediaStore.Images.Media.DATA)
val cursor: android.database.Cursor = contentResolver.query(pickedFile, filePath, null, null, null)!!
cursor.moveToFirst()
val pickedPath: String? = cursor.getStringOrNull(cursor.getColumnIndex(filePath[0]))
if (pickedPath != null) {
path = pickedPath.split("/")
}
cursor.close()
var fileName: String = path[path.size - 1]
// Extension still unknown
if (!fileName.contains(".")) {
var ext: String = MimeTypeMap.getSingleton().getExtensionFromMimeType(contentResolver.getType(pickedFile))!!
// Note: for obj/fbx file, the extension returned is bin..
if (ext == "bin") {
bis.mark(0)
val header: StringBuilder = StringBuilder()
for (i in 0..17) {
val c: Int = bis.read()
if (c == -1) break
header.append(c.toChar())
}
ext = if (header.toString() == "Kaydara FBX Binary") "fbx" else "obj"
bis.reset()
}
fileName += "." + ext
}
val dst: String = filesDir.absolutePath + "/" + getMobileTitle() + "/" + fileName
val os: OutputStream = FileOutputStream(dst)
try {
val buf = ByteArray(1024)
var len = bis.read(buf)
while (len > 0) {
os.write(buf, 0, len)
len = bis.read(buf)
}
onAndroidFilePicked(dst)
}
catch (e: IOException) {}
}
catch (e: FileNotFoundException) {}
catch (e: IOException) {}
}
}