FT8CN/ft8CN/app/src/main/java/com/bg7yoz/ft8cn/MainActivity.java

660 wiersze
26 KiB
Java
Czysty Zwykły widok Historia

package com.bg7yoz.ft8cn;
/**
* FT8CNActivityAPPFragmentFragment
* ----2022.5.6-----
*
* 1.MainViewModelMainViewModel
* 2.
* 3.Fragment
* 4.USB
* @author BG7YOZ
* @date 2022.5.6
*/
import android.Manifest;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.AnimationUtils;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.Observer;
import androidx.navigation.NavController;
import androidx.navigation.fragment.NavHostFragment;
import androidx.navigation.ui.NavigationUI;
import com.bg7yoz.ft8cn.bluetooth.BluetoothStateBroadcastReceive;
import com.bg7yoz.ft8cn.callsign.CallsignDatabase;
import com.bg7yoz.ft8cn.connector.CableSerialPort;
import com.bg7yoz.ft8cn.database.DatabaseOpr;
import com.bg7yoz.ft8cn.database.OnAfterQueryConfig;
import com.bg7yoz.ft8cn.database.OperationBand;
import com.bg7yoz.ft8cn.databinding.MainActivityBinding;
import com.bg7yoz.ft8cn.floatview.FloatView;
import com.bg7yoz.ft8cn.floatview.FloatViewButton;
import com.bg7yoz.ft8cn.grid_tracker.GridTrackerMainActivity;
import com.bg7yoz.ft8cn.maidenhead.MaidenheadGrid;
import com.bg7yoz.ft8cn.timer.UtcTimer;
import com.bg7yoz.ft8cn.ui.FreqDialog;
import com.bg7yoz.ft8cn.ui.SetVolumeDialog;
import com.bg7yoz.ft8cn.ui.ToastMessage;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private BluetoothStateBroadcastReceive mReceive;
private static final String TAG = "MainActivity";
private MainViewModel mainViewModel;
private NavController navController;
private static boolean animatorRunned = false;
//private boolean animationEnd = false;
private MainActivityBinding binding;
private FloatView floatView;
String[] permissions = new String[]{Manifest.permission.RECORD_AUDIO
, Manifest.permission.ACCESS_COARSE_LOCATION
, Manifest.permission.ACCESS_WIFI_STATE
, Manifest.permission.BLUETOOTH
, Manifest.permission.BLUETOOTH_ADMIN
, Manifest.permission.MODIFY_AUDIO_SETTINGS
, Manifest.permission.WAKE_LOCK
, Manifest.permission.ACCESS_FINE_LOCATION};
List<String> mPermissionList = new ArrayList<>();
private static final int PERMISSION_REQUEST = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
permissions = new String[]{Manifest.permission.RECORD_AUDIO
, Manifest.permission.ACCESS_COARSE_LOCATION
, Manifest.permission.ACCESS_WIFI_STATE
, Manifest.permission.BLUETOOTH
, Manifest.permission.BLUETOOTH_ADMIN
, Manifest.permission.BLUETOOTH_CONNECT
, Manifest.permission.MODIFY_AUDIO_SETTINGS
, Manifest.permission.WAKE_LOCK
, Manifest.permission.ACCESS_FINE_LOCATION};
}
checkPermission();
//全屏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
, WindowManager.LayoutParams.FLAG_FULLSCREEN);
//禁止休眠
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
super.onCreate(savedInstanceState);
GeneralVariables.getInstance().setMainContext(getApplicationContext());
//判断是不是简体中文
GeneralVariables.isTraditionalChinese =
getResources().getConfiguration().locale.getDisplayCountry().equals("中國");
//确定是不是中国、香港、澳门、台湾
GeneralVariables.isChina = (getResources().getConfiguration().locale
.getLanguage().toUpperCase().startsWith("ZH"));
mainViewModel = MainViewModel.getInstance(this);
binding = MainActivityBinding.inflate(getLayoutInflater());
binding.initDataLayout.setVisibility(View.VISIBLE);//显示LOG页面
setContentView(binding.getRoot());
ToastMessage.getInstance();
registerBluetoothReceiver();//注册蓝牙动作改变的广播
if (mainViewModel.isBTConnected()) {
mainViewModel.setBlueToothOn();
}
//观察DEBUG信息
GeneralVariables.mutableDebugMessage.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
if (s.length() > 1) {
binding.debugLayout.setVisibility(View.VISIBLE);
} else {
binding.debugLayout.setVisibility(View.GONE);
}
binding.debugMessageTextView.setText(s);
}
});
binding.debugLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
binding.debugLayout.setVisibility(View.GONE);
}
});
mainViewModel.mutableIsRecording.observe(this, new Observer<Boolean>() {
@Override
public void onChanged(Boolean aBoolean) {
if (aBoolean) {
binding.utcProgressBar.setVisibility(View.VISIBLE);
} else {
binding.utcProgressBar.setVisibility(View.GONE);
}
}
});
//观察时钟的变化,显示进度条
mainViewModel.timerSec.observe(this, new Observer<Long>() {
@Override
public void onChanged(Long aLong) {
if (mainViewModel.ft8TransmitSignal.sequential == UtcTimer.getNowSequential()
&& mainViewModel.ft8TransmitSignal.isActivated()) {
binding.utcProgressBar.setBackgroundColor(getColor(R.color.calling_list_isMyCall_color));
} else {
binding.utcProgressBar.setBackgroundColor(getColor(R.color.progresss_bar_back_color));
}
binding.utcProgressBar.setProgress((int) ((aLong / 1000) % 15));
}
});
//添加点击发射消息提示窗口点击关闭动作
binding.transmittingLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
binding.transmittingLayout.setVisibility(View.GONE);
}
});
//清空缓存中的文件
//deleteFolderFile(this.getCacheDir().getPath());
//Log.e(TAG, this.getCacheDir().getPath());
//用于Fragment的导航。
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView);
assert navHostFragment != null;//断言不为空
navController = navHostFragment.getNavController();
NavigationUI.setupWithNavController(binding.navView, navController);
//此处增加回调是因为当APP主动navigation后无法回到解码的界面
binding.navView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
//Log.e(TAG, "onNavigationItemSelected: "+item.toString() );
navController.navigate(item.getItemId());
//binding.navView.setLabelFor(item.getItemId());
return true;
}
});
//FT8CN Ver %s\nBG7YOZ\n%s
binding.welcomTextView.setText(String.format(getString(R.string.version_info)
, GeneralVariables.VERSION, GeneralVariables.BUILD_DATE));
floatView = new FloatView(this, 32);
if (!animatorRunned) {
animationImage();
animatorRunned = true;
} else {
binding.initDataLayout.setVisibility(View.GONE);
InitFloatView();
}
//初始化数据
InitData();
//观察是不是flex radio
mainViewModel.mutableIsFlexRadio.observe(this, new Observer<Boolean>() {
@Override
public void onChanged(Boolean aBoolean) {
//if (floatView==null) return;
if (aBoolean) {
//添加flex配置按钮
floatView.addButton(R.id.flex_radio, "flex_radio", R.drawable.flex_icon
, new View.OnClickListener() {
@Override
public void onClick(View view) {
navController.navigate(R.id.flexRadioInfoFragment);
// if (mainViewModel.baseRig != null) {
// if (mainViewModel.baseRig.isConnected()) {
// ToastMessage.show("flex connected");
// }else {
// ToastMessage.show("flex disconnected");
// }
// }else {
// ToastMessage.show("rig is null");
// }
}
});
} else {//删除flex配置按钮
floatView.deleteButtonByName("flex_radio");
}
}
});
//关闭串口设备列表按钮
binding.closeSelectSerialPortImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
binding.selectSerialPortLayout.setVisibility(View.GONE);
}
});
//观察串口设备列表的变化
mainViewModel.mutableSerialPorts.observe(this, new Observer<ArrayList<CableSerialPort.SerialPort>>() {
@Override
public void onChanged(ArrayList<CableSerialPort.SerialPort> serialPorts) {
setSelectUsbDevice();
}
});
//列USB设备列表
mainViewModel.getUsbDevice();
//设置发射消息框的动画
binding.transmittingMessageTextView.setAnimation(AnimationUtils.loadAnimation(this
, R.anim.view_blink));
//观察发射的状态
mainViewModel.ft8TransmitSignal.mutableIsTransmitting.observe(this,
new Observer<Boolean>() {
@Override
public void onChanged(Boolean aBoolean) {
if (aBoolean) {
binding.transmittingLayout.setVisibility(View.VISIBLE);
} else {
binding.transmittingLayout.setVisibility(View.GONE);
}
}
});
//观察发射内容的变化
mainViewModel.ft8TransmitSignal.mutableTransmittingMessage.observe(this,
new Observer<String>() {
@Override
public void onChanged(String s) {
binding.transmittingMessageTextView.setText(s);
}
});
}
/**
*
*/
private void InitFloatView() {
//floatView = new FloatView(this, 32);
binding.container.addView(floatView);
floatView.setButtonMargin(0);
floatView.setFloatBoard(FloatView.FLOAT_BOARD.RIGHT);
floatView.setButtonBackgroundResourceId(R.drawable.float_button_style);
//动态添加按钮建议使用静态的ID静态ID在VALUES/FLOAT_BUTTON_IDS.XML中设置
floatView.addButton(R.id.float_nav, "float_nav", R.drawable.ic_baseline_fullscreen_24
, new View.OnClickListener() {
@Override
public void onClick(View view) {
FloatViewButton button = floatView.getButtonByName("float_nav");
if (binding.navView.getVisibility() == View.VISIBLE) {
binding.navView.setVisibility(View.GONE);
if (button != null) {
button.setImageResource(R.drawable.ic_baseline_fullscreen_exit_24);
}
} else {
binding.navView.setVisibility(View.VISIBLE);
if (button != null) {
button.setImageResource(R.drawable.ic_baseline_fullscreen_24);
}
}
}
});
floatView.addButton(R.id.float_freq, "float_freq", R.drawable.ic_baseline_freq_24
, new View.OnClickListener() {
@Override
public void onClick(View view) {
new FreqDialog(binding.container.getContext(), mainViewModel).show();
}
});
floatView.addButton(R.id.set_volume, "set_volume", R.drawable.ic_baseline_volume_up_24
, new View.OnClickListener() {
@Override
public void onClick(View view) {
new SetVolumeDialog(binding.container.getContext(), mainViewModel).show();
}
});
//打开网格追踪
floatView.addButton(R.id.grid_tracker, "grid_tracker", R.drawable.ic_baseline_grid_tracker_24
, new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(), GridTrackerMainActivity.class);
startActivity(intent);
}
});
// floatView.addButton(R.id.flex_radio, "flex_radio", R.drawable.flex_icon
// , new View.OnClickListener() {
// @Override
// public void onClick(View view) {
// navController.navigate(R.id.flexRadioInfoFragment);
// }
// });
floatView.initLocation();
}
/**
*
*/
private void InitData() {
if (mainViewModel.configIsLoaded) return;//如果数据已经读取一遍了,就不用再读取了。
//读取波段数据
if (mainViewModel.operationBand == null) {
mainViewModel.operationBand = OperationBand.getInstance(getBaseContext());
}
mainViewModel.databaseOpr.getQslDxccToMap();
//获取所有的配置参数
mainViewModel.databaseOpr.getAllConfigParameter(new OnAfterQueryConfig() {
@Override
public void doOnBeforeQueryConfig(String KeyName) {
}
@Override
public void doOnAfterQueryConfig(String KeyName, String Value) {
mainViewModel.configIsLoaded = true;
//此处梅登海德已经通过数据库得到了但是如果GPS能获取到还是用GPS的
String grid = MaidenheadGrid.getMyMaidenheadGrid(getApplicationContext());
if (!grid.equals("")) {//说明获取到了GPS数据
GeneralVariables.setMyMaidenheadGrid(grid);
//写到数据库中
mainViewModel.databaseOpr.writeConfig("grid", grid, null);
}
mainViewModel.ft8TransmitSignal.setTimer_sec(GeneralVariables.transmitDelay);
//如果呼号、网格为空,就进入设置界面
if (GeneralVariables.getMyMaidenheadGrid().equals("")
|| GeneralVariables.myCallsign.equals("")) {
runOnUiThread(new Runnable() {
@Override
public void run() {//导航到设置页面
navController.navigate(R.id.menu_nav_config);
}
});
}
}
});
//把历史中通联成功的呼号与网格的对应关系
new DatabaseOpr.GetCallsignMapGrid(mainViewModel.databaseOpr.getDb()).execute();
mainViewModel.getFollowCallsignsFromDataBase();
//打开呼号位置信息的数据库,目前是以内存数据库方式。
if (GeneralVariables.callsignDatabase == null) {
GeneralVariables.callsignDatabase = CallsignDatabase.getInstance(getBaseContext(), null, 1);
}
}
/**
*
*/
private void checkPermission() {
mPermissionList.clear();
//判断哪些权限未授予
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
mPermissionList.add(permission);
}
}
//判断是否为空
if (!mPermissionList.isEmpty()) {//请求权限方法
String[] permissions = mPermissionList.toArray(new String[mPermissionList.size()]);//将List转为数组
ActivityCompat.requestPermissions(MainActivity.this, permissions, PERMISSION_REQUEST);
}
}
/**
*
*
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode != PERMISSION_REQUEST) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
/**
*
*/
public void setSelectUsbDevice() {
ArrayList<CableSerialPort.SerialPort> ports = mainViewModel.mutableSerialPorts.getValue();
binding.selectSerialPortLinearLayout.removeAllViews();
for (int i = 0; i < ports.size(); i++) {//动态添加串口设备列表
View layout = LayoutInflater.from(getApplicationContext())
.inflate(R.layout.select_serial_port_list_view_item, null);
layout.setId(i);
TextView textView = layout.findViewById(R.id.selectSerialPortListViewItemTextView);
textView.setText(ports.get(i).information());
binding.selectSerialPortLinearLayout.addView(layout);
layout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//连接电台并做电台的频率设置等操作
mainViewModel.connectCableRig(getApplicationContext(), ports.get(view.getId()));
binding.selectSerialPortLayout.setVisibility(View.GONE);
}
});
}
//选择串口设备弹框
if ((ports.size() >= 1) && (!mainViewModel.isRigConnected())) {
binding.selectSerialPortLayout.setVisibility(View.VISIBLE);
} else {//说明没有可以识别的驱动,不显示设备弹框
binding.selectSerialPortLayout.setVisibility(View.GONE);
}
}
/**
*
*
* @param filePath
*/
public static void deleteFolderFile(String filePath) {
try {
File file = new File(filePath);//获取SD卡指定路径
File[] files = file.listFiles();//获取SD卡指定路径下的文件或者文件夹
for (int i = 0; i < files.length; i++) {
if (files[i].isFile()) {//如果是文件直接删除
File tempFile = new File(files[i].getPath());
tempFile.delete();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void animationImage() {
ObjectAnimator navigationAnimator = ObjectAnimator.ofFloat(binding.navView, "translationY", 200);
navigationAnimator.setDuration(3000);
navigationAnimator.setFloatValues(200, 200, 200, 0);
ObjectAnimator hideLogoAnimator = ObjectAnimator.ofFloat(binding.initDataLayout, "alpha", 1f, 1f, 1f, 0);
hideLogoAnimator.setDuration(3000);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(navigationAnimator, hideLogoAnimator);
//animatorSet.playTogether(initPositionStrAnimator, logoAnimator, navigationAnimator, hideLogoAnimator);
animatorSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
//animationEnd = true;
binding.initDataLayout.setVisibility(View.GONE);
binding.utcProgressBar.setVisibility(View.VISIBLE);
InitFloatView();//显示浮窗
//binding.floatView.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
animatorSet.start();
}
//此方法只有在android:launchMode="singleTask"模式下起作用
@Override
protected void onNewIntent(Intent intent) {
if ("android.hardware.usb.action.USB_DEVICE_ATTACHED".equals(intent.getAction())) {
mainViewModel.getUsbDevice();
}
super.onNewIntent(intent);
}
@Override
public void onBackPressed() {
if (navController.getGraph().getStartDestination() == navController.getCurrentDestination().getId()) {//说明是到最后一个页面了
AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setMessage(getString(R.string.exit_confirmation))
.setPositiveButton(getString(R.string.exit)
, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if (mainViewModel.ft8TransmitSignal.isActivated()) {
mainViewModel.ft8TransmitSignal.setActivated(false);
}
closeThisApp();//退出APP
}
}).setNegativeButton(getString(R.string.cancel)
, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
builder.create().show();
} else {//退出activity堆栈
navController.navigateUp();
//setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
}
}
private void closeThisApp() {
mainViewModel.ft8TransmitSignal.setActivated(false);
if (mainViewModel.baseRig != null) {
if (mainViewModel.baseRig.getConnector() != null) {
mainViewModel.baseRig.getConnector().disconnect();
}
}
mainViewModel.ft8SignalListener.stopListen();
mainViewModel = null;
System.exit(0);
}
/**
* 广
*/
private void registerBluetoothReceiver() {
if (mReceive == null) {
mReceive = new BluetoothStateBroadcastReceive(getApplicationContext(), mainViewModel);
}
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
intentFilter.addAction(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE);
intentFilter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
intentFilter.addAction(AudioManager.EXTRA_SCO_AUDIO_STATE);
intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
intentFilter.addAction(BluetoothAdapter.EXTRA_CONNECTION_STATE);
intentFilter.addAction(BluetoothAdapter.EXTRA_STATE);
intentFilter.addAction("android.bluetooth.BluetoothAdapter.STATE_OFF");
intentFilter.addAction("android.bluetooth.BluetoothAdapter.STATE_ON");
registerReceiver(mReceive, intentFilter);
}
/**
* 广
*/
private void unregisterBluetoothReceiver() {
if (mReceive != null) {
unregisterReceiver(mReceive);
mReceive = null;
}
}
@Override
protected void onDestroy() {
unregisterBluetoothReceiver();
super.onDestroy();
}
}