mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-02-22 12:33:57 +01:00
193 lines
6.6 KiB
Kotlin
193 lines
6.6 KiB
Kotlin
package org.sdrpp.sdrpp;
|
|
|
|
import android.app.NativeActivity;
|
|
import android.app.AlertDialog;
|
|
import android.app.PendingIntent;
|
|
import android.content.Intent;
|
|
import android.content.IntentFilter;
|
|
import android.content.BroadcastReceiver;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.pm.PackageManager;
|
|
import android.hardware.usb.*;
|
|
import android.Manifest;
|
|
import android.os.Bundle;
|
|
import android.view.View;
|
|
import android.view.KeyEvent;
|
|
import android.view.inputmethod.InputMethodManager;
|
|
import android.util.Log;
|
|
import android.content.res.AssetManager;
|
|
|
|
import androidx.core.app.ActivityCompat;
|
|
|
|
import androidx.core.content.PermissionChecker;
|
|
|
|
import java.util.concurrent.LinkedBlockingQueue;
|
|
import java.io.*;
|
|
|
|
private const val ACTION_USB_PERMISSION = "org.sdrpp.sdrpp.USB_PERMISSION";
|
|
|
|
private val usbReceiver = object : BroadcastReceiver() {
|
|
override fun onReceive(context: Context, intent: Intent) {
|
|
if (ACTION_USB_PERMISSION == intent.action) {
|
|
synchronized(this) {
|
|
var _this = context as MainActivity;
|
|
_this.SDR_device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
|
|
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
|
|
_this.SDR_conn = _this.usbManager!!.openDevice(_this.SDR_device);
|
|
|
|
// Save SDR info
|
|
_this.SDR_VID = _this.SDR_device!!.getVendorId();
|
|
_this.SDR_PID = _this.SDR_device!!.getProductId()
|
|
_this.SDR_FD = _this.SDR_conn!!.getFileDescriptor();
|
|
}
|
|
|
|
// Whatever the hell this does
|
|
context.unregisterReceiver(this);
|
|
|
|
// Hide again the system bars
|
|
_this.hideSystemBars();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class MainActivity : NativeActivity() {
|
|
private val TAG : String = "SDR++";
|
|
public var usbManager : UsbManager? = null;
|
|
public var SDR_device : UsbDevice? = null;
|
|
public var SDR_conn : UsbDeviceConnection? = null;
|
|
public var SDR_VID : Int = -1;
|
|
public var SDR_PID : Int = -1;
|
|
public var SDR_FD : Int = -1;
|
|
|
|
fun checkAndAsk(permission: String) {
|
|
if (PermissionChecker.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
|
|
ActivityCompat.requestPermissions(this, arrayOf(permission), 1);
|
|
}
|
|
}
|
|
|
|
public fun hideSystemBars() {
|
|
val decorView = getWindow().getDecorView();
|
|
val uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
|
decorView.setSystemUiVisibility(uiOptions);
|
|
}
|
|
|
|
public override fun onCreate(savedInstanceState: Bundle?) {
|
|
// Hide bars
|
|
hideSystemBars();
|
|
|
|
// Ask for required permissions, without these the app cannot run.
|
|
checkAndAsk(Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
|
checkAndAsk(Manifest.permission.READ_EXTERNAL_STORAGE);
|
|
|
|
// TODO: Have the main code wait until these two permissions are available
|
|
|
|
// Register events
|
|
usbManager = getSystemService(Context.USB_SERVICE) as UsbManager;
|
|
val permissionIntent = PendingIntent.getBroadcast(this, 0, Intent(ACTION_USB_PERMISSION), 0)
|
|
val filter = IntentFilter(ACTION_USB_PERMISSION)
|
|
registerReceiver(usbReceiver, filter)
|
|
|
|
// Get permission for all USB devices
|
|
val devList = usbManager!!.getDeviceList();
|
|
for ((name, dev) in devList) {
|
|
usbManager!!.requestPermission(dev, permissionIntent);
|
|
}
|
|
|
|
// Ask for internet permission
|
|
checkAndAsk(Manifest.permission.INTERNET);
|
|
|
|
super.onCreate(savedInstanceState)
|
|
}
|
|
|
|
public override fun onResume() {
|
|
// Hide bars again
|
|
hideSystemBars();
|
|
super.onResume();
|
|
}
|
|
|
|
fun showSoftInput() {
|
|
val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager;
|
|
inputMethodManager.showSoftInput(window.decorView, 0);
|
|
}
|
|
|
|
fun hideSoftInput() {
|
|
val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager;
|
|
inputMethodManager.hideSoftInputFromWindow(window.decorView.windowToken, 0);
|
|
hideSystemBars();
|
|
}
|
|
|
|
// Queue for the Unicode characters to be polled from native code (via pollUnicodeChar())
|
|
private var unicodeCharacterQueue: LinkedBlockingQueue<Int> = LinkedBlockingQueue()
|
|
|
|
// We assume dispatchKeyEvent() of the NativeActivity is actually called for every
|
|
// KeyEvent and not consumed by any View before it reaches here
|
|
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
|
if (event.action == KeyEvent.ACTION_DOWN) {
|
|
unicodeCharacterQueue.offer(event.getUnicodeChar(event.metaState))
|
|
}
|
|
return super.dispatchKeyEvent(event)
|
|
}
|
|
|
|
fun pollUnicodeChar(): Int {
|
|
return unicodeCharacterQueue.poll() ?: 0
|
|
}
|
|
|
|
public fun createIfDoesntExist(path: String) {
|
|
// This is a directory, create it in the filesystem
|
|
var folder = File(path);
|
|
var success = true;
|
|
if (!folder.exists()) {
|
|
success = folder.mkdirs();
|
|
}
|
|
if (!success) {
|
|
Log.e(TAG, "Could not create folder with path " + path);
|
|
}
|
|
}
|
|
|
|
public fun extractDir(aman: AssetManager, local: String, rsrc: String): Int {
|
|
val flist = aman.list(rsrc);
|
|
var ecount = 0;
|
|
for (fp in flist) {
|
|
val lpath = local + "/" + fp;
|
|
val rpath = rsrc + "/" + fp;
|
|
|
|
Log.w(TAG, "Extracting '" + rpath + "' to '" + lpath + "'");
|
|
|
|
// Create local path if non-existent
|
|
createIfDoesntExist(local);
|
|
|
|
// Create if directory
|
|
val ext = extractDir(aman, lpath, rpath);
|
|
|
|
// Extract if file
|
|
if (ext == 0) {
|
|
// This is a file, extract it
|
|
val _os = FileOutputStream(lpath);
|
|
val _is = aman.open(rpath);
|
|
val ilen = _is.available();
|
|
var fbuf = ByteArray(ilen);
|
|
_is.read(fbuf, 0, ilen);
|
|
_os.write(fbuf);
|
|
_os.close();
|
|
_is.close();
|
|
}
|
|
|
|
ecount++;
|
|
}
|
|
return ecount;
|
|
}
|
|
|
|
public fun getAppDir(): String {
|
|
val fdir = getFilesDir().getAbsolutePath();
|
|
|
|
// Extract all resources to the app directory
|
|
val aman = getAssets();
|
|
extractDir(aman, fdir + "/res", "res");
|
|
createIfDoesntExist(fdir + "/modules");
|
|
|
|
return fdir;
|
|
}
|
|
}
|