问题:界面上有两个按钮,点击start执行timerTask,点击stop取消timertask,如果点击start按钮之后退出应用,再进入应用点击stop,timertask无法停止。为啥呢?
public class MainActivity extends AppCompatActivity {
private static final String[] PERMISSIONS = new String[]{
//写外部存储权限
Manifest.permission.WRITE_EXTERNAL_STORAGE,
};
private static final int REQUEST_CODE = 1;
private AppBarConfiguration appBarConfiguration;
private ActivityMainBinding binding;
private static final String TAG = "MainActivity";
private final int maxFiles = 10;
private String mFileName = "log.txt";
private static Timer mTimer;
private TimerTask mChangeFileNameTask;
private TimerTask mSaveLogTask;
private File mFolder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
binding.fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAnchorView(R.id.fab)
.setAction("Action", null).show();
}
});
mTimer = new Timer();
initView();
//初始获取权限
PermissionUtil.checkPermission(this,PERMISSIONS,REQUEST_CODE);
//saveLogs();
}
public class ChangeFileNameTask extends TimerTask {
@Override
public void run()
{
//如果运行过程中文件夹被删除了,要重新创建文件夹
if (mFolder == null) createLogFolder();
int length = mFolder.list().length;
SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd_HHmmss", Locale.CHINA);
String fileTime = sdf.format(new Date());
mFileName = "log"+ fileTime +".txt";
if (length >= maxFiles) {
deleteFirstFile(mFolder);
Log.d(TAG, "run文件个数达到了十个: length=" + length );
}
}
}
private void initView() {
Button btnStart = findViewById(R.id.btn_start);
Button btnStop = findViewById(R.id.btn_stop);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"开始保存日志",Toast.LENGTH_SHORT).show();
createLogFolder();
if (mTimer == null) {
mTimer = new Timer();
}
if (mChangeFileNameTask == null) {
mChangeFileNameTask = new ChangeFileNameTask();
}
if (mSaveLogTask == null) {
mSaveLogTask = new SaveLogTask();
}
mTimer.schedule(mChangeFileNameTask,100,2000);
mTimer.schedule(mSaveLogTask, 100,1000);
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"停止保存日志",Toast.LENGTH_SHORT).show();
if (mChangeFileNameTask != null){
Log.d(TAG, "onClick: mChangeFileNameTask!=null 取消任务");
mChangeFileNameTask.cancel();
mChangeFileNameTask = null;
}
if (mSaveLogTask != null){
Log.d(TAG, "onClick: mSaveLogTask!=null 取消任务");
mSaveLogTask.cancel();
mSaveLogTask = null;
}
if (mTimer != null){
Log.d(TAG, "onClick: mTimer!=null 取消定时器");
mTimer.cancel();
mTimer = null;
}
}
});
}
public void deleteFirstFile(File folder) {
File[] files = folder.listFiles();
if (files != null && files.length > 0) {
Arrays.sort(files, Comparator.comparingLong(File::lastModified));
File oldestFile = files[0];
if (oldestFile.delete()) {
// 文件删除成功的处理逻辑
Log.d(TAG, "Successfully deleted the oldest file: " + oldestFile.getName());
} else {
// 文件删除失败的处理逻辑
Log.d(TAG, "Failed to delete the oldest file: " + oldestFile.getName());
}
} else {
Log.d(TAG,"The folder is empty.");
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case REQUEST_CODE:
if (PermissionUtil.checkGrant(grantResults)){
Toast.makeText(this, "权限获取成功", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "权限获取失败", Toast.LENGTH_SHORT).show();
this.finish();
}
break;
}
}
private void writeToFile() {
new Thread(
new Runnable() {
@Override
public void run() {
SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd_HHmmss", Locale.CHINA);
String logFolderPath = Environment.getExternalStorageDirectory().getAbsolutePath();
File file = new File(logFolderPath + File.separator + "r" + sdf.format(new Date()) + ".txt");
file.setWritable(true);
try {
file.createNewFile();
} catch (IOException e) {
throw new RuntimeException(e);
}
Toast.makeText(MainActivity.this,"start",Toast.LENGTH_SHORT).show();
if (file.exists()){
try {
FileOutputStream fos = new FileOutputStream(file);
String logContent = "我要开始保存log了";
fos.write(logContent.getBytes());
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
Toast.makeText(MainActivity.this,"文件不存在",Toast.LENGTH_SHORT).show();
}
}
}
).run();
}
public void saveLog(String strLog, String fileName) {
File file = new File(Environment.getExternalStorageDirectory().getPath() + "/" + fileName);
if(file.exists()) Log.d(TAG, "saveLog: strLog exist is true");
FileOutputStream out = null;
try {
out = new FileOutputStream(file);
out.write(strLog.getBytes());
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
return NavigationUI.navigateUp(navController, appBarConfiguration)
|| super.onSupportNavigateUp();
}
public void createLogFolder() {
String folderPath = Environment.getExternalStorageDirectory().getPath() + "/asulog"; // 文件夹路径
mFolder = new File(folderPath);
if (!mFolder.exists()) { // 检查文件夹是否存在
if (mFolder.mkdirs()) { // 创建文件夹
Log.d(TAG, "createLogFolder: asulog文件夹已创建成功");
} else {
Log.d(TAG, "createLogFolder: asulog文件夹创建失败");
Toast.makeText(MainActivity.this,"asulog文件夹创建失败,无法保存日志",Toast.LENGTH_SHORT).show();
return;
}
} else {
Log.d(TAG, "createLogFolder: asulog文件夹已经存在");
// TODO: 2023/7/27 文件夹已经存在,需要清空所有文件
}
}
private void saveLogToFile(String logData, String fileName) {
File file = new File(Environment.getExternalStorageDirectory().getPath() +"/asulog/" + fileName);
FileWriter writer = null;
try {
writer = new FileWriter(file, true);
writer.write("\r\n");//换行
writer.write(logData);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private String generateLogData() {
SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd_HHmmss", Locale.CHINA);
String strLog = sdf.format(new Date());
// 生成日志数据的逻辑
return strLog;
}
public class SaveLogTask extends TimerTask {
@Override
public void run()
{
String logData = generateLogData(); // 生成日志数据
saveLogToFile(logData, mFileName); // 保存日志到文件
}
}
}