mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-06-25 20:07:51 +02:00
Backend abstraction + added android support + partial high DPI scaling + added missing files
This commit is contained in:
32
android/app/src/main/java/DeviceManager.kt
Normal file
32
android/app/src/main/java/DeviceManager.kt
Normal file
@ -0,0 +1,32 @@
|
||||
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.*;
|
||||
|
||||
class DeviceManager {
|
||||
public fun init() {
|
||||
|
||||
}
|
||||
}
|
192
android/app/src/main/java/MainActivity.kt
Normal file
192
android/app/src/main/java/MainActivity.kt
Normal file
@ -0,0 +1,192 @@
|
||||
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;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user