codec2_talkie/codec2talkie/src/main/java/com/radio/codec2talkie/MainActivity.java

846 wiersze
34 KiB
Java
Czysty Zwykły widok Historia

2020-11-28 14:47:52 +00:00
package com.radio.codec2talkie;
2022-07-05 12:36:05 +00:00
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
2021-10-09 17:42:40 +00:00
import androidx.annotation.NonNull;
2020-11-28 14:47:52 +00:00
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
2021-10-09 17:37:31 +00:00
import androidx.core.view.MenuCompat;
2021-01-25 09:39:09 +00:00
import androidx.preference.PreferenceManager;
2020-11-28 14:47:52 +00:00
import android.Manifest;
2020-11-29 15:03:14 +00:00
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
2022-07-04 19:18:49 +00:00
import android.content.ComponentName;
import android.content.Context;
2020-11-28 15:00:23 +00:00
import android.content.Intent;
import android.content.IntentFilter;
2022-07-04 19:18:49 +00:00
import android.content.ServiceConnection;
2021-01-25 09:39:09 +00:00
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
2020-12-09 17:10:01 +00:00
import android.graphics.Color;
import android.graphics.PorterDuff;
2020-12-09 17:15:18 +00:00
import android.graphics.PorterDuffColorFilter;
import android.graphics.Typeface;
2020-12-12 15:21:07 +00:00
import android.hardware.usb.UsbManager;
2022-07-04 19:18:49 +00:00
import android.os.Build;
2020-11-28 14:47:52 +00:00
import android.os.Bundle;
2020-12-03 13:25:02 +00:00
import android.os.Handler;
2022-07-04 19:18:49 +00:00
import android.os.IBinder;
2020-12-03 13:25:02 +00:00
import android.os.Looper;
import android.os.Message;
2022-07-04 19:18:49 +00:00
import android.os.Messenger;
import android.os.SystemClock;
import android.util.Log;
import android.view.KeyEvent;
2021-01-24 13:01:54 +00:00
import android.view.Menu;
import android.view.MenuItem;
2020-11-29 15:03:14 +00:00
import android.view.MotionEvent;
import android.view.View;
2021-02-10 17:03:49 +00:00
import android.view.WindowManager;
import android.widget.FrameLayout;
2022-08-17 18:46:16 +00:00
import android.widget.ImageButton;
2020-12-09 17:10:01 +00:00
import android.widget.ProgressBar;
2020-11-29 14:50:59 +00:00
import android.widget.TextView;
import android.widget.Toast;
2020-11-28 14:47:52 +00:00
2022-07-05 11:59:15 +00:00
import com.radio.codec2talkie.app.AppMessage;
2022-07-04 19:18:49 +00:00
import com.radio.codec2talkie.app.AppService;
import com.radio.codec2talkie.app.AppWorker;
2022-06-19 14:07:19 +00:00
import com.radio.codec2talkie.connect.BleConnectActivity;
2021-01-27 10:52:54 +00:00
import com.radio.codec2talkie.connect.BluetoothConnectActivity;
2021-10-10 18:22:56 +00:00
import com.radio.codec2talkie.connect.BluetoothSocketHandler;
import com.radio.codec2talkie.connect.TcpIpConnectActivity;
2022-08-26 13:03:51 +00:00
import com.radio.codec2talkie.maps.MapActivity;
2022-08-11 13:40:06 +00:00
import com.radio.codec2talkie.settings.SettingsWrapper;
2022-07-10 16:55:47 +00:00
import com.radio.codec2talkie.storage.log.LogItemActivity;
import com.radio.codec2talkie.protocol.ProtocolFactory;
2021-10-09 17:27:17 +00:00
import com.radio.codec2talkie.recorder.RecorderActivity;
2021-01-25 09:39:09 +00:00
import com.radio.codec2talkie.settings.PreferenceKeys;
2021-01-24 17:56:46 +00:00
import com.radio.codec2talkie.settings.SettingsActivity;
2022-07-17 19:48:19 +00:00
import com.radio.codec2talkie.storage.message.group.MessageGroupActivity;
2021-10-12 13:53:01 +00:00
import com.radio.codec2talkie.tools.AudioTools;
2021-10-17 14:56:50 +00:00
import com.radio.codec2talkie.tools.RadioTools;
2021-01-27 10:13:07 +00:00
import com.radio.codec2talkie.transport.TransportFactory;
2021-01-27 10:52:54 +00:00
import com.radio.codec2talkie.connect.UsbConnectActivity;
import com.radio.codec2talkie.connect.UsbPortHandler;
import java.util.LinkedList;
import java.util.List;
2021-02-06 13:52:58 +00:00
import java.util.Locale;
2022-07-19 10:00:40 +00:00
public class MainActivity extends AppCompatActivity implements ServiceConnection {
2020-11-28 14:47:52 +00:00
private static final String TAG = MainActivity.class.getSimpleName();
2022-07-05 12:36:05 +00:00
private final static int REQUEST_PERMISSIONS = 1;
2021-02-07 15:21:26 +00:00
// S9 level at -93 dBm as per VHF Managers Handbook
2021-10-18 06:18:55 +00:00
private final static int S_METER_S0_VALUE_DB = -147;
2021-02-07 15:21:26 +00:00
// from S0 up to S9+40
2021-10-18 06:37:58 +00:00
private final static int S_METER_RANGE_DB = 100;
2021-10-24 15:47:33 +00:00
private final static long BACK_EXIT_MS_DELAY = 2000;
private final String[] _requiredPermissions = new String[] {
Manifest.permission.BLUETOOTH,
2022-06-18 16:41:46 +00:00
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.RECORD_AUDIO,
2022-07-04 19:18:49 +00:00
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
2020-11-28 20:45:47 +00:00
2022-07-04 19:18:49 +00:00
private AppService _appService;
2021-01-25 09:39:09 +00:00
2021-02-06 14:34:30 +00:00
private SharedPreferences _sharedPreferences;
private boolean _isTestMode;
2022-06-19 14:07:19 +00:00
private boolean _isBleEnabled;
2020-12-08 11:20:30 +00:00
private TextView _textConnInfo;
2020-12-05 20:35:21 +00:00
private TextView _textStatus;
private TextView _textTelemetry;
2021-01-25 09:39:09 +00:00
private TextView _textCodecMode;
2021-02-06 11:45:09 +00:00
private TextView _textRssi;
2021-01-25 12:45:45 +00:00
private ProgressBar _progressAudioLevel;
private ProgressBar _progressRssi;
2022-08-17 18:46:16 +00:00
private ImageButton _btnPtt;
private Menu _menu;
2020-11-29 14:50:59 +00:00
public static boolean isPaused = false;
private boolean _isConnecting = false;
2022-07-05 06:57:31 +00:00
private boolean _isAppExit = false;
private boolean _isAppRestart = false;
2022-08-06 18:29:01 +00:00
private boolean _isRigCtlUsbConnected = false;
2022-07-05 06:57:31 +00:00
2022-07-04 19:18:49 +00:00
private long _backPressedTimestamp;
2020-11-29 15:03:14 +00:00
@SuppressLint("ClickableViewAccessibility")
2020-11-28 14:47:52 +00:00
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate()");
2021-10-12 18:46:17 +00:00
// title
2021-01-31 09:56:07 +00:00
String appName = getResources().getString(R.string.app_name);
2021-01-31 09:57:34 +00:00
setTitle(appName + " v" + BuildConfig.VERSION_NAME);
2021-01-31 09:56:07 +00:00
2021-01-25 09:39:09 +00:00
_sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
2020-11-28 14:47:52 +00:00
setContentView(R.layout.activity_main);
2020-11-29 14:50:59 +00:00
2020-12-08 11:20:30 +00:00
_textConnInfo = findViewById(R.id.textBtName);
_textStatus = findViewById(R.id.textStatus);
_textTelemetry = findViewById(R.id.textTelemetry);
2021-02-06 11:45:09 +00:00
_textRssi = findViewById(R.id.textRssi);
2021-01-25 09:39:09 +00:00
2021-10-12 18:46:17 +00:00
// UV bar
int barMaxValue = AppWorker.getAudioMaxLevel() - AppWorker.getAudioMinLevel();
2021-01-25 12:45:45 +00:00
_progressAudioLevel = findViewById(R.id.progressAudioLevel);
_progressAudioLevel.setMax(barMaxValue);
_progressAudioLevel.getProgressDrawable().setColorFilter(
new PorterDuffColorFilter(AudioTools.colorFromAudioLevel(AppWorker.getAudioMinLevel()), PorterDuff.Mode.SRC_IN));
2020-12-05 20:35:21 +00:00
2021-10-12 18:46:17 +00:00
// S-meter
_progressRssi = findViewById(R.id.progressRssi);
_progressRssi.setMax(S_METER_RANGE_DB);
_progressRssi.getProgressDrawable().setColorFilter(
new PorterDuffColorFilter(Color.GRAY, PorterDuff.Mode.SRC_IN));
2021-10-12 18:46:17 +00:00
// PTT button
_btnPtt = findViewById(R.id.btnPtt);
_btnPtt.setEnabled(false);
_btnPtt.setOnTouchListener(onBtnPttTouchListener);
2021-01-25 09:39:09 +00:00
_textCodecMode = findViewById(R.id.codecMode);
2021-10-12 18:46:17 +00:00
// BT/USB disconnects
registerReceiver(onBluetoothDisconnected, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
2020-12-12 15:21:07 +00:00
registerReceiver(onUsbDetached, new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED));
2020-12-05 19:04:49 +00:00
2022-08-11 13:40:06 +00:00
_isTestMode = SettingsWrapper.isLoopbackTransport(_sharedPreferences);
_isBleEnabled = SettingsWrapper.isBleTransport(_sharedPreferences);
2021-10-12 18:46:17 +00:00
// show/hide S-meter
FrameLayout frameRssi = findViewById(R.id.frameRssi);
2022-08-16 10:12:35 +00:00
if (SettingsWrapper.isFreeDvSoundModemModulation(_sharedPreferences)) {
frameRssi.setVisibility(View.VISIBLE);
2022-08-16 14:34:52 +00:00
} else if (SettingsWrapper.isKissExtensionEnabled(_sharedPreferences) && !SettingsWrapper.isSoundModemEnabled(_sharedPreferences)) {
int sLevelId = RadioTools.getMinimumDecodeSLevelLabel(_sharedPreferences, S_METER_S0_VALUE_DB);
TextView sLevel = findViewById(sLevelId);
if (sLevel != null) {
sLevel.setTypeface(null, Typeface.BOLD_ITALIC);
}
2022-08-16 10:12:35 +00:00
frameRssi.setVisibility(View.VISIBLE);
} else {
frameRssi.setVisibility(View.GONE);
}
2021-02-10 17:03:49 +00:00
// screen always on / auto turn screen on / run above app lock
2021-02-10 17:03:49 +00:00
if (_sharedPreferences.getBoolean(PreferenceKeys.APP_KEEP_SCREEN_ON, false)) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
if (_sharedPreferences.getBoolean(PreferenceKeys.APP_TURN_SCREEN_ON, false)) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
if (_sharedPreferences.getBoolean(PreferenceKeys.APP_NO_LOCK, false)) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
}
2021-10-12 18:46:17 +00:00
2022-07-05 06:57:31 +00:00
_isAppRestart = false;
_isAppExit = false;
startTransportConnection();
2020-11-28 15:00:23 +00:00
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG, "onStart()");
}
@Override
protected void onStop() {
super.onStop();
Log.i(TAG, "onStop()");
}
@Override
protected void onRestart() {
super.onRestart();
Log.i(TAG, "onRestart()");
}
@Override
2020-12-12 15:21:07 +00:00
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy()");
unregisterReceiver(onBluetoothDisconnected);
unregisterReceiver(onUsbDetached);
}
@Override
protected void onPause() {
super.onPause();
Log.i(TAG, "onPause()");
isPaused = true;
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "onResume()");
isPaused = false;
if (!AppService.isRunning && !_isConnecting) {
_btnPtt.setEnabled(false);
startTransportConnection();
}
}
2022-07-05 06:57:31 +00:00
private void exitApplication() {
Log.i(TAG, "exitApplication()");
2022-07-05 06:57:31 +00:00
_isAppExit = true;
if (_appService != null) {
_appService.stopRunning();
}
}
private void restartApplication() {
Log.i(TAG, "restartApplication()");
2022-07-05 06:57:31 +00:00
_isAppRestart = true;
2022-07-04 19:18:49 +00:00
if (_appService != null) {
_appService.stopRunning();
}
}
private void startTransportConnection() {
Log.i(TAG, "startTransportConnection()");
if (AppService.isRunning) {
startAppService(AppService.transportType);
} else if (requestPermissions()) {
2022-08-11 13:40:06 +00:00
switch (SettingsWrapper.getCurrentTransportType(_sharedPreferences)) {
case LOOPBACK:
_textConnInfo.setText(R.string.main_status_loopback_test);
startAppService(TransportFactory.TransportType.LOOPBACK);
break;
2022-08-11 13:40:06 +00:00
case SOUND_MODEM:
_textConnInfo.setText(R.string.main_status_sound_modem);
2022-08-11 13:40:06 +00:00
// start sound modem without rig cat usb connection
if (SettingsWrapper.isSoundModemRigDisabled(_sharedPreferences))
2022-08-05 21:37:13 +00:00
startAppService(TransportFactory.TransportType.SOUND_MODEM);
2022-08-11 13:40:06 +00:00
// otherwise try to connect with usb for cat ptt
2022-08-05 21:37:13 +00:00
else
startUsbConnectActivity();
break;
2022-08-11 13:40:06 +00:00
case TCP_IP:
startTcpIpConnectActivity();
break;
2022-08-11 13:40:06 +00:00
case USB:
startUsbConnectActivity();
break;
2022-08-11 13:40:06 +00:00
case BLUETOOTH:
case BLE:
startBluetoothConnectActivity();
break;
2021-10-11 09:06:03 +00:00
}
}
}
2022-07-05 12:36:05 +00:00
private final ActivityResultLauncher<Intent> _usbActivityLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
Intent data = result.getData();
assert data != null;
int resultCode = result.getResultCode();
2022-08-11 13:40:06 +00:00
if (SettingsWrapper.isSoundModemEnabled(_sharedPreferences)) {
2022-08-06 18:29:01 +00:00
_isRigCtlUsbConnected = resultCode == RESULT_OK;
2022-08-05 21:37:13 +00:00
startAppService(TransportFactory.TransportType.SOUND_MODEM);
} else if (resultCode == RESULT_CANCELED) {
_textConnInfo.setText(R.string.main_status_loopback_test);
startAppService(TransportFactory.TransportType.LOOPBACK);
2022-07-05 12:36:05 +00:00
} else if (resultCode == RESULT_OK) {
_textConnInfo.setText(data.getStringExtra("name"));
startAppService(TransportFactory.TransportType.USB);
}
}
);
2020-12-08 11:20:30 +00:00
protected void startUsbConnectActivity() {
_isConnecting = true;
2022-08-06 18:29:01 +00:00
_isRigCtlUsbConnected = false;
2022-07-05 12:36:05 +00:00
_usbActivityLauncher.launch(new Intent(this, UsbConnectActivity.class));
2020-12-08 11:20:30 +00:00
}
2022-07-05 12:36:05 +00:00
private final ActivityResultLauncher<Intent> _bluetoothActivityLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
Intent data = result.getData();
assert data != null;
int resultCode = result.getResultCode();
if (resultCode == RESULT_CANCELED) {
// fall back to loopback if bluetooth failed
_textConnInfo.setText(R.string.main_status_loopback_test);
startAppService(TransportFactory.TransportType.LOOPBACK);
} else if (resultCode == RESULT_OK) {
_textConnInfo.setText(data.getStringExtra("name"));
if (_isBleEnabled) {
startAppService(TransportFactory.TransportType.BLE);
} else {
startAppService(TransportFactory.TransportType.BLUETOOTH);
}
}
}
);
2020-11-28 15:00:23 +00:00
protected void startBluetoothConnectActivity() {
_isConnecting = true;
2022-06-19 14:07:19 +00:00
Intent bluetoothConnectIntent;
if (_isBleEnabled) {
bluetoothConnectIntent = new Intent(this, BleConnectActivity.class);
} else {
bluetoothConnectIntent = new Intent(this, BluetoothConnectActivity.class);
}
2022-07-05 12:36:05 +00:00
_bluetoothActivityLauncher.launch(bluetoothConnectIntent);
2020-11-28 20:45:47 +00:00
}
2022-07-05 12:36:05 +00:00
private final ActivityResultLauncher<Intent> _tcpipActivityLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
Intent data = result.getData();
assert data != null;
int resultCode = result.getResultCode();
if (resultCode == RESULT_CANCELED) {
// fall back to loopback if tcp/ip failed
_textConnInfo.setText(R.string.main_status_loopback_test);
startAppService(TransportFactory.TransportType.LOOPBACK);
} else if (resultCode == RESULT_OK) {
_textConnInfo.setText(data.getStringExtra("name"));
startAppService(TransportFactory.TransportType.TCP_IP);
}
}
);
protected void startTcpIpConnectActivity() {
_isConnecting = true;
2022-07-05 12:36:05 +00:00
_tcpipActivityLauncher.launch(new Intent(this, TcpIpConnectActivity.class));
}
2022-07-05 12:36:05 +00:00
private final ActivityResultLauncher<Intent> _recorderActivityLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(), result -> { });
2021-10-11 06:38:45 +00:00
protected void startRecorderActivity() {
2022-07-05 12:36:05 +00:00
_recorderActivityLauncher.launch(new Intent(this, RecorderActivity.class));
}
private final ActivityResultLauncher<Intent> _logViewActivityLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(), result -> { });
protected void startLogViewActivity() {
_logViewActivityLauncher.launch(new Intent(this, LogItemActivity.class));
}
2022-08-26 13:03:51 +00:00
protected void startMapViewActivity() {
_logViewActivityLauncher.launch(new Intent(this, MapActivity.class));
}
2022-07-05 12:36:05 +00:00
private final ActivityResultLauncher<Intent> _settingsActivityLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(), result -> restartApplication());
protected void startSettingsActivity() {
_settingsActivityLauncher.launch(new Intent(this, SettingsActivity.class));
2021-10-09 12:16:12 +00:00
}
2022-07-17 19:48:19 +00:00
private final ActivityResultLauncher<Intent> _messagesActivityLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(), result -> {});
protected void startMessagesActivity() {
_messagesActivityLauncher.launch(new Intent(this, MessageGroupActivity.class));
}
protected boolean requestPermissions() {
2021-10-09 17:42:40 +00:00
List<String> permissionsToRequest = new LinkedList<>();
2022-07-04 19:18:49 +00:00
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
String permission = Manifest.permission.FOREGROUND_SERVICE;
if (ContextCompat.checkSelfPermission(MainActivity.this, permission) == PackageManager.PERMISSION_DENIED) {
permissionsToRequest.add(permission);
}
}
for (String permission : _requiredPermissions) {
if (ContextCompat.checkSelfPermission(MainActivity.this, permission) == PackageManager.PERMISSION_DENIED) {
permissionsToRequest.add(permission);
}
}
if (permissionsToRequest.size() > 0) {
ActivityCompat.requestPermissions(
MainActivity.this,
permissionsToRequest.toArray(new String[0]),
REQUEST_PERMISSIONS);
return false;
}
return true;
}
2022-07-05 06:57:31 +00:00
private void bindAppService() {
2022-07-19 10:00:40 +00:00
if (!bindService(new Intent(this, AppService.class), this, Context.BIND_AUTO_CREATE)) {
2022-07-05 06:57:31 +00:00
Log.e(TAG, "Service does not exists or no access");
}
}
private void unbindAppService() {
2022-07-19 10:00:40 +00:00
unbindService(this);
2022-07-05 06:57:31 +00:00
}
private void startAppService(TransportFactory.TransportType transportType) {
Log.i(TAG, "Starting app service processing: " + transportType.toString());
ProtocolFactory.ProtocolType protocolType = ProtocolFactory.getBaseProtocolType(getApplicationContext());
_btnPtt.setEnabled(protocolType != ProtocolFactory.ProtocolType.KISS_PARROT);
2022-07-08 10:54:40 +00:00
updateStatusText(protocolType);
2022-07-05 06:57:31 +00:00
Intent serviceIntent = new Intent(this, AppService.class);
serviceIntent.putExtra("transportType", transportType);
serviceIntent.putExtra("callback", new Messenger(onAppServiceStateChanged));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
startForegroundService(serviceIntent);
else
startService(serviceIntent);
bindAppService();
2022-07-05 06:57:31 +00:00
}
private void stopAppService() {
stopService(new Intent(this, AppService.class));
}
2022-07-08 10:54:40 +00:00
private void updateStatusText(ProtocolFactory.ProtocolType protocolType) {
2022-07-05 06:57:31 +00:00
// protocol
String status = "";
// recording
boolean recordingEnabled = _sharedPreferences.getBoolean(PreferenceKeys.CODEC2_RECORDING_ENABLED, false);
if (recordingEnabled) {
status += getString(R.string.recorder_status_label);
}
// scrambling
boolean scramblingEnabled = _sharedPreferences.getBoolean(PreferenceKeys.KISS_SCRAMBLING_ENABLED, false);
if (scramblingEnabled) {
status += getString(R.string.kiss_scrambler_label);
}
2022-08-06 18:20:44 +00:00
// rig CAT control
String rigName = _sharedPreferences.getString(PreferenceKeys.PORTS_SOUND_MODEM_RIG, "Disabled");
2022-08-06 18:29:01 +00:00
if (!rigName.equals("Disabled") && _isRigCtlUsbConnected) {
2022-08-06 18:20:44 +00:00
status += getString(R.string.ports_sound_modem_rig_label);
}
2022-07-05 06:57:31 +00:00
// aprs
2022-08-11 13:46:31 +00:00
boolean aprsEnabled = SettingsWrapper.isAprsEnabled(_sharedPreferences);
2022-07-05 06:57:31 +00:00
if (aprsEnabled) {
status += getString(R.string.aprs_label);
// VoAX25
2022-08-14 19:22:04 +00:00
boolean voax25Enabled = SettingsWrapper.isVoax25Enabled(_sharedPreferences);
2022-07-05 06:57:31 +00:00
if (voax25Enabled) {
status += getString(R.string.voax25_label);
}
2022-07-09 13:45:07 +00:00
2023-04-18 19:01:58 +00:00
// Lora aprs text packets
boolean textPacketsEnabled = SettingsWrapper.isTextPacketsEnabled(_sharedPreferences);
if (textPacketsEnabled) {
status += getString(R.string.text_packets_label);
}
2022-07-09 13:45:07 +00:00
// Digirepeater
2022-07-25 20:29:34 +00:00
boolean isDigirepeaterEnabled = _sharedPreferences.getBoolean(PreferenceKeys.AX25_DIGIREPEATER_ENABLED, false);
2022-07-09 13:45:07 +00:00
if (isDigirepeaterEnabled) {
status += getString(R.string.digirepeater_label);
}
2022-08-19 18:00:10 +00:00
2023-04-18 19:01:58 +00:00
// APRSIS
2022-08-19 18:00:10 +00:00
boolean aprsisEnabled = SettingsWrapper.isAprsIsEnabled(_sharedPreferences);
if (aprsisEnabled) {
status += getString(R.string.aprsis_label);
}
2022-07-05 06:57:31 +00:00
}
2022-07-08 10:54:40 +00:00
if (_appService != null) {
boolean isTracking = _appService.isTracking();
if (isTracking) {
status += getString(R.string.tracking_label);
}
2022-07-05 06:57:31 +00:00
}
2022-07-08 10:54:40 +00:00
status = status.length() == 0 ? protocolType.toString() : protocolType.toString() + " " + status;
2023-12-09 17:53:49 +00:00
String statusLine = AudioTools.getSpeedStatusText(_sharedPreferences, getResources()) + ", " + status;
2022-07-08 10:54:40 +00:00
_textCodecMode.setText(statusLine);
2022-07-05 06:57:31 +00:00
}
private final BroadcastReceiver onBluetoothDisconnected = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
2022-07-19 10:00:40 +00:00
if (_appService != null && BluetoothSocketHandler.getSocket() != null && !_isTestMode) {
Toast.makeText(MainActivity.this, R.string.bt_disconnected, Toast.LENGTH_LONG).show();
_appService.stopRunning();
}
}
2020-12-12 15:21:07 +00:00
};
private final BroadcastReceiver onUsbDetached = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
2022-07-19 10:00:40 +00:00
if (_appService != null && UsbPortHandler.getPort() != null && !_isTestMode) {
Toast.makeText(MainActivity.this, R.string.usb_detached, Toast.LENGTH_LONG).show();
_appService.stopRunning();
}
}
};
2022-06-30 20:48:30 +00:00
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
2022-08-11 13:46:31 +00:00
boolean isAprsEnabled = SettingsWrapper.isAprsEnabled(_sharedPreferences);
2022-06-30 20:48:30 +00:00
menu.setGroupVisible(R.id.group_aprs, isAprsEnabled);
return true;
}
2021-01-24 13:01:54 +00:00
@Override
public boolean onCreateOptionsMenu(Menu menu) {
2021-10-09 17:37:31 +00:00
MenuCompat.setGroupDividerEnabled(menu, true);
2021-01-24 13:01:54 +00:00
getMenuInflater().inflate(R.menu.main_menu, menu);
_menu = menu;
updateMenuItemsAndStatusText();
return true;
}
private void updateMenuItemsAndStatusText() {
if (AppService.isRunning & _menu != null && _appService != null) {
MenuItem item = _menu.findItem(R.id.start_tracking);
if (_appService.isTracking()) {
item.setTitle(R.string.menu_stop_tracking);
} else {
item.setTitle(R.string.menu_start_tracking);
}
updateStatusText(ProtocolFactory.getBaseProtocolType(getApplicationContext()));
}
2021-01-24 13:01:54 +00:00
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
int itemId = item.getItemId();
if (itemId == R.id.preferences) {
2022-07-11 12:28:08 +00:00
if (_appService != null && _appService.isTracking())
_appService.stopTracking();
2022-07-05 12:36:05 +00:00
startSettingsActivity();
2021-01-24 13:01:54 +00:00
return true;
}
2021-10-11 06:41:11 +00:00
if (itemId == R.id.recorder) {
2021-10-11 06:38:45 +00:00
startRecorderActivity();
2021-10-09 12:16:12 +00:00
return true;
}
2021-10-11 06:41:11 +00:00
if (itemId == R.id.reconnect) {
2022-07-04 19:18:49 +00:00
if (_appService != null) {
_appService.stopRunning();
2021-10-11 06:41:11 +00:00
}
return true;
}
2021-01-25 18:16:08 +00:00
else if (itemId == R.id.exit) {
2022-07-05 06:57:31 +00:00
exitApplication();
2021-01-25 18:16:08 +00:00
return true;
}
2022-06-30 20:52:47 +00:00
else if (itemId == R.id.send_position) {
2022-07-04 19:18:49 +00:00
_appService.sendPosition();
2022-06-30 20:52:47 +00:00
return true;
}
else if (itemId == R.id.start_tracking) {
2022-07-04 19:18:49 +00:00
if (_appService.isTracking()) {
_appService.stopTracking();
2022-07-03 12:19:07 +00:00
item.setTitle(R.string.menu_start_tracking);
} else {
2022-07-04 19:18:49 +00:00
_appService.startTracking();
2022-07-03 12:19:07 +00:00
item.setTitle(R.string.menu_stop_tracking);
}
2022-06-30 20:52:47 +00:00
return true;
}
else if (itemId == R.id.messages) {
2022-07-17 19:48:19 +00:00
startMessagesActivity();
2022-06-30 20:52:47 +00:00
return true;
}
else if (itemId == R.id.aprs_log) {
startLogViewActivity();
return true;
2022-08-26 13:03:51 +00:00
}
else if (itemId == R.id.aprs_map) {
startMapViewActivity();
return true;
}
2021-01-24 13:01:54 +00:00
return super.onOptionsItemSelected(item);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
// headset hardware ptt cannot be used for long press
case KeyEvent.KEYCODE_HEADSETHOOK:
if (_btnPtt.isPressed()) {
_btnPtt.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 0, 0, 0));
} else {
_btnPtt.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 0, 0, 0));
}
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
2021-02-10 17:03:49 +00:00
if (_sharedPreferences.getBoolean(PreferenceKeys.APP_VOLUME_PTT, false)) {
2021-02-10 15:49:33 +00:00
_btnPtt.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 0, 0, 0));
return true;
}
break;
case KeyEvent.KEYCODE_TV_DATA_SERVICE:
_btnPtt.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 0, 0, 0));
return true;
}
return super.onKeyDown(keyCode, event);
}
2021-10-24 15:47:33 +00:00
@Override
public void onBackPressed() {
2022-07-04 19:18:49 +00:00
if (_backPressedTimestamp + BACK_EXIT_MS_DELAY > System.currentTimeMillis()) {
2022-08-15 09:29:05 +00:00
//super.onBackPressed();
2022-07-05 06:57:31 +00:00
exitApplication();
2021-10-24 15:47:33 +00:00
} else {
Toast.makeText(getBaseContext(), "Press back again to exit", Toast.LENGTH_SHORT).show();
}
2022-07-04 19:18:49 +00:00
_backPressedTimestamp = System.currentTimeMillis();
2021-10-24 15:47:33 +00:00
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
2021-02-10 17:03:49 +00:00
if (_sharedPreferences.getBoolean(PreferenceKeys.APP_VOLUME_PTT, false)) {
2021-02-10 15:49:33 +00:00
_btnPtt.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 0, 0, 0));
return true;
}
break;
case KeyEvent.KEYCODE_TV_DATA_SERVICE:
_btnPtt.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 0, 0, 0));
return true;
}
return super.onKeyUp(keyCode, event);
}
2020-11-29 15:03:14 +00:00
private final View.OnTouchListener onBtnPttTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
2022-07-04 19:18:49 +00:00
if (_appService != null)
2022-07-05 07:47:58 +00:00
_appService.startTransmit();
2020-11-29 15:03:14 +00:00
break;
case MotionEvent.ACTION_UP:
v.performClick();
2022-07-04 19:18:49 +00:00
if (_appService != null)
2022-07-05 07:47:58 +00:00
_appService.startReceive();
2020-11-29 15:03:14 +00:00
break;
}
return false;
}
};
@Override
2021-10-09 17:42:40 +00:00
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSIONS) {
boolean allGranted = true;
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
allGranted = false;
break;
}
}
if (allGranted) {
2021-10-12 13:53:01 +00:00
Toast.makeText(MainActivity.this, R.string.permissions_granted, Toast.LENGTH_SHORT).show();
2020-12-08 11:20:30 +00:00
startUsbConnectActivity();
} else {
2021-10-12 13:53:01 +00:00
Toast.makeText(MainActivity.this, R.string.permissions_denied, Toast.LENGTH_SHORT).show();
2022-07-05 06:57:31 +00:00
exitApplication();
}
}
}
2022-07-19 10:00:40 +00:00
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
Log.i(TAG, "Connected to app service");
_appService = ((AppService.AppServiceBinder)service).getService();
if (AppService.isRunning) {
_textConnInfo.setText(_appService.getTransportName());
updateMenuItemsAndStatusText();
2022-07-04 19:18:49 +00:00
}
2022-07-19 10:00:40 +00:00
}
2022-07-04 19:18:49 +00:00
2022-07-19 10:00:40 +00:00
@Override
public void onServiceDisconnected(ComponentName className) {
Log.i(TAG, "Disconnected from app service");
_appService = null;
}
2022-07-04 19:18:49 +00:00
2022-07-05 06:57:31 +00:00
private final Handler onAppServiceStateChanged = new Handler(Looper.getMainLooper()) {
2020-12-03 13:25:02 +00:00
@Override
public void handleMessage(Message msg) {
2022-07-05 11:59:15 +00:00
switch (AppMessage.values()[msg.what]) {
case EV_CONNECTED:
Log.i(TAG, "EV_CONNECTED");
updateMenuItemsAndStatusText();
_isConnecting = false;
_btnPtt.setEnabled(true);
2021-10-12 13:53:01 +00:00
Toast.makeText(getBaseContext(), R.string.processor_connected, Toast.LENGTH_SHORT).show();
2021-01-28 07:24:14 +00:00
break;
2022-07-05 11:59:15 +00:00
case EV_DISCONNECTED:
Log.i(TAG, "EV_DISCONNECTED");
updateMenuItemsAndStatusText();
2022-08-17 18:46:16 +00:00
_btnPtt.setImageResource(R.drawable.btn_ptt_stop);
_btnPtt.setEnabled(false);
// app restart, stop app service and restart ourselves
2022-07-05 06:57:31 +00:00
if (_isAppRestart) {
2022-08-15 09:29:05 +00:00
Log.i(TAG, "App restart");
unbindAppService();
stopAppService();
2022-07-05 07:03:39 +00:00
finish();
2022-07-05 06:57:31 +00:00
startActivity(getIntent());
// app exit, stop app service and finish
2022-07-05 07:03:39 +00:00
} else if (_isAppExit) {
2022-08-15 09:29:05 +00:00
Log.i(TAG, "App exit");
unbindAppService();
stopAppService();
2022-07-05 07:03:39 +00:00
finish();
// otherwise just reconnect if app is not on pause
} else if (!isPaused) {
2022-08-15 09:29:05 +00:00
Log.i(TAG, "App restart transport");
Toast.makeText(getBaseContext(), R.string.processor_disconnected, Toast.LENGTH_SHORT).show();
2022-07-05 06:57:31 +00:00
startTransportConnection();
}
2021-01-27 10:52:54 +00:00
break;
2022-07-05 11:59:15 +00:00
case EV_LISTENING:
2022-08-17 18:46:16 +00:00
_btnPtt.setImageResource(R.drawable.btn_ptt_touch);
2022-07-01 12:18:38 +00:00
_textStatus.setText("");
2021-01-27 10:52:54 +00:00
break;
2022-07-10 16:22:29 +00:00
case EV_TRANSMITTED_VOICE:
2022-07-01 14:18:37 +00:00
if (msg.obj != null) {
_textStatus.setText((String) msg.obj);
}
2022-08-17 18:46:16 +00:00
_btnPtt.setImageResource(R.drawable.btn_ptt_mic);
2021-01-27 10:52:54 +00:00
break;
2022-07-05 11:59:15 +00:00
case EV_RECEIVING:
2022-08-17 18:46:16 +00:00
_btnPtt.setImageResource(R.drawable.btn_ptt_listen);
2021-01-27 10:52:54 +00:00
break;
2022-07-18 20:08:05 +00:00
case EV_TEXT_MESSAGE_RECEIVED:
2022-07-10 16:22:29 +00:00
case EV_DATA_RECEIVED:
2022-07-24 14:00:56 +00:00
case EV_POSITION_RECEIVED:
2022-07-01 12:18:38 +00:00
if (msg.obj != null) {
2022-07-19 13:53:15 +00:00
String note = (String)msg.obj;
_textStatus.setText(note.split(":")[0]);
2022-07-01 12:18:38 +00:00
}
2022-08-17 18:46:16 +00:00
_btnPtt.setImageResource(R.drawable.btn_ptt_letter);
2022-07-10 16:22:29 +00:00
break;
case EV_VOICE_RECEIVED:
if (msg.obj != null) {
_textStatus.setText((String) msg.obj);
}
2022-08-17 18:46:16 +00:00
//_btnPtt.setText(R.string.main_status_voice_received);
_btnPtt.setImageResource(R.drawable.btn_ptt_listen);
2021-01-30 19:32:25 +00:00
break;
2022-07-05 11:59:15 +00:00
case EV_RX_RADIO_LEVEL:
if (msg.arg1 == 0 && msg.arg2 == 0) {
2021-02-06 11:45:09 +00:00
_textRssi.setText("");
_progressRssi.getProgressDrawable().setColorFilter(new PorterDuffColorFilter(Color.GRAY, PorterDuff.Mode.SRC_IN));
_progressRssi.setProgress(0);
} else if (msg.arg1 == 0) {
double snr = (double)msg.arg2 / 100.0;
_textRssi.setText(String.format(Locale.getDefault(), "%2.2f", (double)msg.arg2 / 100.0));
_progressRssi.getProgressDrawable().setColorFilter(new PorterDuffColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN));
_progressRssi.setProgress((int) ((-110.0 + snr) - S_METER_S0_VALUE_DB));
2021-02-06 11:45:09 +00:00
} else {
2021-02-06 13:52:58 +00:00
_textRssi.setText(String.format(Locale.getDefault(), "%3d dBm, %2.2f", msg.arg1, (double)msg.arg2 / 100.0));
_progressRssi.getProgressDrawable().setColorFilter(new PorterDuffColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN));
_progressRssi.setProgress(msg.arg1 - S_METER_S0_VALUE_DB);
2021-02-06 11:45:09 +00:00
}
break;
case EV_TELEMETRY:
if (msg.arg1 > 0) {
// NOTE, reuse status indicator for voltage
_textTelemetry.setText(String.format(Locale.getDefault(), "%2.2fV", (double)msg.arg1 / 100.0));
}
break;
2021-01-27 10:52:54 +00:00
// same progress bar is reused for rx and tx levels
2022-07-05 11:59:15 +00:00
case EV_RX_LEVEL:
case EV_TX_LEVEL:
2021-10-12 13:53:01 +00:00
_progressAudioLevel.getProgressDrawable().setColorFilter(new PorterDuffColorFilter(AudioTools.colorFromAudioLevel(msg.arg1), PorterDuff.Mode.SRC_IN));
_progressAudioLevel.setProgress(msg.arg1 - AppWorker.getAudioMinLevel());
2021-01-27 10:52:54 +00:00
break;
2022-07-05 11:59:15 +00:00
case EV_RX_ERROR:
2022-08-17 18:46:16 +00:00
_btnPtt.setImageResource(R.drawable.btn_ptt_err_rx);
2021-01-28 14:12:16 +00:00
break;
2022-07-05 11:59:15 +00:00
case EV_TX_ERROR:
2022-08-17 18:46:16 +00:00
_btnPtt.setImageResource(R.drawable.btn_ptt_err_tx);
break;
2022-07-09 09:06:19 +00:00
case EV_STARTED_TRACKING:
case EV_STOPPED_TRACKING:
updateStatusText(ProtocolFactory.getBaseProtocolType(getApplicationContext()));
break;
2020-12-09 17:10:01 +00:00
}
2020-12-03 13:25:02 +00:00
}
};
2020-11-28 14:47:52 +00:00
}