234 lines
9.9 KiB
Kotlin
234 lines
9.9 KiB
Kotlin
package org.eu.octt.droidscriptin
|
||
|
||
import android.annotation.SuppressLint
|
||
import android.content.BroadcastReceiver
|
||
import android.content.Context
|
||
import android.content.Intent
|
||
import android.content.IntentFilter
|
||
import android.content.SharedPreferences
|
||
import androidx.appcompat.app.AppCompatActivity
|
||
import android.os.Bundle
|
||
import android.telephony.SmsMessage
|
||
import android.view.Menu
|
||
import android.view.MenuItem
|
||
import android.view.View
|
||
import android.view.Window
|
||
import android.webkit.JavascriptInterface
|
||
import android.webkit.WebView
|
||
import android.widget.EditText
|
||
import android.widget.LinearLayout
|
||
import android.widget.TextView
|
||
import android.widget.Toast
|
||
import org.json.JSONObject
|
||
|
||
class MainActivity : AppCompatActivity() {
|
||
private val EVENT_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED"
|
||
private var buttonReload: MenuItem? = null
|
||
private var buttonConfigurationOpen: MenuItem? = null
|
||
private var buttonConfigurationSave: MenuItem? = null
|
||
private var buttonConfigurationCancel: MenuItem? = null
|
||
//private var buttonClearlog: MenuItem? = null
|
||
private var webview: WebView? = null
|
||
private var labelLog: TextView? = null
|
||
private var layoutConfiguration: LinearLayout? = null
|
||
private var editScript: EditText? = null
|
||
private var sharedPrefs: SharedPreferences? = null
|
||
private var sharedPrefsEditor: SharedPreferences.Editor? = null
|
||
|
||
@SuppressLint("JavascriptInterface")
|
||
override fun onCreate(savedInstanceState: Bundle?) {
|
||
super.onCreate(savedInstanceState)
|
||
window.requestFeature(Window.FEATURE_ACTION_BAR)
|
||
setContentView(R.layout.activity_main)
|
||
sharedPrefs = getSharedPreferences("Prefs", 0)
|
||
sharedPrefsEditor = sharedPrefs!!.edit()
|
||
webview = this.findViewById(R.id.webview)
|
||
//labelLog = this.findViewById(R.id.label_log)
|
||
layoutConfiguration = this.findViewById(R.id.layout_configuration)
|
||
editScript = this.findViewById(R.id.edit_script)
|
||
//editScript!!.setMovementMethod(ScrollingMovementMethod())
|
||
reloadConfiguration()
|
||
//webview!!.setWebViewClient(WebViewClient())
|
||
webview!!.settings.javaScriptEnabled = true
|
||
webview!!.addJavascriptInterface(this, "Android")
|
||
reloadWebview()
|
||
|
||
// <https://stackoverflow.com/questions/11435354/receiving-sms-on-android-app>
|
||
val messageReceiver = object: BroadcastReceiver() {
|
||
override fun onReceive(context: Context, intent: Intent) {
|
||
val sharedPrefs: SharedPreferences = context.getSharedPreferences("Prefs", 0)
|
||
if (intent.action == EVENT_SMS_RECEIVED) {
|
||
val bundle = intent.extras
|
||
if (bundle != null) {
|
||
// get sms objects
|
||
val pdus = bundle["pdus"] as Array<Any>?
|
||
if (pdus!!.size == 0) {
|
||
return
|
||
}
|
||
// large message might be broken into many
|
||
val messages: Array<SmsMessage?> = arrayOfNulls<SmsMessage>(pdus.size)
|
||
val sb = StringBuilder()
|
||
for (i in pdus.indices) {
|
||
messages[i] = SmsMessage.createFromPdu(pdus[i] as ByteArray)
|
||
sb.append(messages[i]!!.getMessageBody())
|
||
}
|
||
val sender: String? = messages[0]!!.getOriginatingAddress()
|
||
val message = sb.toString()
|
||
execJavascript(" Android.onEvent('${EVENT_SMS_RECEIVED}'); Android.onSmsReceived('${argumentifyString(message)}', '${argumentifyString(sender.toString())}'); ")
|
||
//execJavascript("Android.SmsQueue.push({ sender: '${sender}', message: '${message}' }); Android.Callback('android.provider.Telephony.SMS_RECEIVED');")
|
||
//execJavascript("Android.SmsQueue.push({ sender: 1, message: 2 ); Android.Callback('android.provider.Telephony.SMS_RECEIVED')")
|
||
//smsListener!!.messageReceived(message)
|
||
// prevent any other broadcast receivers from receiving broadcast
|
||
// abortBroadcast();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
this.registerReceiver(messageReceiver, IntentFilter(EVENT_SMS_RECEIVED))
|
||
}
|
||
|
||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||
menuInflater.inflate(R.menu.menu_main, menu!!)
|
||
buttonReload = menu.findItem(R.id.button_reload)
|
||
buttonConfigurationOpen = menu.findItem(R.id.button_configuration_open)
|
||
buttonConfigurationSave = menu.findItem(R.id.button_configuration_save)
|
||
buttonConfigurationCancel = menu.findItem(R.id.button_configuration_cancel)
|
||
//buttonClearlog = menu.findItem(R.id.button_clearlog)
|
||
setConfigurationView(false)
|
||
return true
|
||
}
|
||
|
||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||
when (item.itemId) {
|
||
R.id.button_reload -> {
|
||
webview!!.clearCache(true)
|
||
reloadWebview()
|
||
}
|
||
R.id.button_configuration_open -> {
|
||
reloadConfiguration()
|
||
setConfigurationView(true)
|
||
}
|
||
R.id.button_configuration_save -> {
|
||
//sharedPrefsEditor!!.putString("editScript", editScript!!.text.toString())
|
||
WriteSharedPref("editScript", editScript!!.text.toString())
|
||
//sharedPrefsEditor!!.apply()
|
||
setConfigurationView(false)
|
||
reloadWebview()
|
||
}
|
||
R.id.button_configuration_cancel -> {
|
||
reloadConfiguration()
|
||
setConfigurationView(false)
|
||
}
|
||
//R.id.button_clearlog -> {
|
||
//sharedPrefsEditor!!.putString("Log", "")
|
||
// setConfigurationView(false)
|
||
//val url = new URL("https://example.com")
|
||
//val con = url.openConnection()
|
||
//con.setRequestMethod("GET")
|
||
//con.setRequestProperty("Cookie", "")
|
||
//var os = con.getOutputStream()
|
||
//os.write(input, 0, input.length)
|
||
//thread {
|
||
// Looper.prepare()
|
||
// val connection = URL("https://example.com").openConnection() as HttpURLConnection
|
||
// val data = connection.inputStream.bufferedReader().readText()
|
||
// runOnUiThread { Toast.makeText(applicationContext, data, Toast.LENGTH_SHORT).show() }
|
||
//}
|
||
//}
|
||
}
|
||
return super.onOptionsItemSelected(item)
|
||
}
|
||
|
||
private fun argumentifyString(text: String): String {
|
||
return text.replace("\"", "\\\"").replace("'", "\\'").replace("\n", "\\n")
|
||
}
|
||
|
||
private fun showHideView(view: View) {
|
||
view.visibility = (if (view.visibility == View.VISIBLE) View.INVISIBLE else View.VISIBLE)
|
||
}
|
||
|
||
private fun setViewVisibility(view: View, status: Boolean) {
|
||
view.visibility = (if (status) View.VISIBLE else View.INVISIBLE)
|
||
}
|
||
|
||
private fun reloadConfiguration() {
|
||
editScript!!.setText(ReadSharedPref("editScript", "").toString())//sharedPrefs!!.getString("editScript", ""))
|
||
}
|
||
|
||
private fun setConfigurationView(status: Boolean) {
|
||
buttonReload!!.isVisible = !status
|
||
buttonConfigurationOpen!!.isVisible = !status
|
||
buttonConfigurationSave!!.isVisible = status
|
||
buttonConfigurationCancel!!.isVisible = status
|
||
//buttonClearlog!!.isVisible = status
|
||
setViewVisibility(webview!!, !status)
|
||
//setViewVisibility(labelLog!!, !status)
|
||
setViewVisibility(layoutConfiguration!!, status)
|
||
setTitle(if (status) "⚙️ Configuration" else "\uD83C\uDF10️ WebView")
|
||
}
|
||
|
||
private fun reloadWebview() {
|
||
webview!!.loadUrl("file:///android_asset/index.html")
|
||
}
|
||
|
||
fun execJavascript(text: String) {
|
||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
|
||
webview!!.evaluateJavascript("(function(){${text}})();", null)
|
||
} else {
|
||
webview!!.loadUrl("javascript:(function(){${text}})();")
|
||
}
|
||
}
|
||
|
||
@JavascriptInterface
|
||
fun Toast(text: String, length: Int?) {
|
||
Toast.makeText(this, text, (length ?: Toast.LENGTH_LONG)).show()
|
||
}
|
||
|
||
private fun ReadSharedPref(key: String, default: Any): Any? {
|
||
val keys = sharedPrefs!!.all
|
||
for (entry in keys) {
|
||
if (entry.key == key) {
|
||
return entry.value
|
||
}
|
||
}
|
||
return default
|
||
}
|
||
|
||
// TODO: Actually handle non-strings
|
||
@JavascriptInterface
|
||
fun ReadSharedPrefJSI(key: String, fallback: String): String? {
|
||
sharedPrefs = getSharedPreferences("Prefs", 0)
|
||
val keys = sharedPrefs!!.all
|
||
for (entry in keys) {
|
||
if (entry.key == key) {
|
||
val jsonValue = entry.value.toString().replace("\"", "\\\"").replace("\n", "\\n")
|
||
return """{ "value": "${jsonValue}" }"""
|
||
}
|
||
}
|
||
return fallback
|
||
}
|
||
|
||
private fun WriteSharedPref(key: String, value: Any) {
|
||
when (value) {
|
||
is String -> sharedPrefsEditor!!.putString(key, value)
|
||
is Boolean -> sharedPrefsEditor!!.putBoolean(key, value)
|
||
is Int -> sharedPrefsEditor!!.putInt(key, value)
|
||
is Float -> sharedPrefsEditor!!.putFloat(key, value)
|
||
is Long -> sharedPrefsEditor!!.putLong(key, value)
|
||
}
|
||
sharedPrefsEditor!!.apply()
|
||
}
|
||
|
||
// TODO: Actually handle non-strings
|
||
@JavascriptInterface
|
||
fun WriteSharedPrefJSI(key: String, jsonValue: String) {
|
||
sharedPrefs = getSharedPreferences("Prefs", 0)
|
||
sharedPrefsEditor = sharedPrefs!!.edit()
|
||
val value = JSONObject(jsonValue).getString("value")
|
||
//when (value) {
|
||
// is String ->
|
||
sharedPrefsEditor!!.putString(key, value)
|
||
//}
|
||
sharedPrefsEditor!!.apply()
|
||
}
|
||
} |