当从另一个 class 调用但从 MainActivity.java 调用时函数崩溃应用程序
Function crashing app when called from another class but not when called from MainActivity.java
我遇到了一个奇怪的问题。
我创建了一个更新通知的函数("updateNotification" 在 MainActivity 中)。然而,奇怪的是我的更新通知功能从 MainActivity 调用没有问题但是当我从另一个 class (notificationSingleton 中的第 76 行)调用它时,我的应用程序立即崩溃。
MainActivity.java
public static TextView dateText;
private CountDownTimer countDownTimer;
private NotificationSingleton notificationSingleton;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// if first start
SharedPreferences prefs = getSharedPreferences("prefs", MODE_PRIVATE);
boolean firstStart = prefs.getBoolean("firstStart", true);
if(firstStart)
{
showStartDialog();
}
// set dateText to date_text
dateText = findViewById(R.id.date_text);
// show date picker when click on show_dialog button
findViewById(R.id.show_dialog).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showDatePickerDialog();
}
});
notificationSingleton = NotificationSingleton.getInstance();
startTimer();
}
private void showStartDialog()
{
new AlertDialog.Builder(this)
.setTitle("One Time Dialog")
.setMessage("This should only be shown once")
.setPositiveButton("ok", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
showDatePickerDialog();
}
})
.create().show();
SharedPreferences prefs = getSharedPreferences("prefs", MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("firstStart", false);
editor.apply();
}
private void showDatePickerDialog()
{
DatePickerDialog datePickerDialog = new DatePickerDialog(
this,
this,
Calendar.getInstance().get(Calendar.YEAR),
Calendar.getInstance().get(Calendar.MONTH),
Calendar.getInstance().get(Calendar.DAY_OF_MONTH)
);
datePickerDialog.show();
}
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth)
{
Date endDate = new Date((year-1900),month,dayOfMonth);
SharedPreferences prefs = getSharedPreferences("prefs", MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putLong("endDate", endDate.getTime());
editor.apply();
startTimer();
}
private void startTimer()
{
long difference = getRemainDays();
if(countDownTimer !=null)
{
countDownTimer.cancel();
countDownTimer = null;
}
countDownTimer = new CountDownTimer(difference,1000) // 1 second
{
@Override
public void onTick(long millisUntilFinished)
{
int days = (int)(millisUntilFinished/(1000*60*60*24));
int hours = (int)((millisUntilFinished/(1000*60*60))%24);
int mins = (int)((millisUntilFinished/(1000*60))%60);
int sec = (int)((millisUntilFinished/(1000))%60);
dateText.setText(String.format("%02d Days %d Hours %d Mins %d Sec",days,hours,mins,sec));
}
@Override
public void onFinish()
{
// Done
dateText.setText("Done");
}
}.start();
}
private long getRemainDays()
{
Date currentDate = new Date();
SharedPreferences prefs = getSharedPreferences("prefs", MODE_PRIVATE);
long endDate = prefs.getLong("endDate", currentDate.getTime());
return endDate - currentDate.getTime();
}
public void startService(View v){
String input = dateText.getText().toString();
Intent serviceIntent = new Intent(this, ExampleService.class);
serviceIntent.putExtra("inputExtra", input);
ContextCompat.startForegroundService(this,serviceIntent);
notificationSingleton.mNotificationRunnable.run();
}
public void stopService(View v){
Intent serviceIntent = new Intent(this,ExampleService.class);
stopService(serviceIntent);
notificationSingleton.stopService();
}
public TextView getDateText()
{
return dateText;
}
public void updateNotification() {
MainActivity mainActivity = new MainActivity();
String input = mainActivity.getDateText().getText().toString();
Intent notificationIntent = new Intent(this, NotificationSingleton.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Example Service")
.setContentText(input)
.setSmallIcon(R.drawable.ic_android)
.setContentIntent(pendingIntent)
.build();
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotificationManager.notify(1, notification);
}
NotificationSingleton.java
public Handler mHandler = new Handler();
MainActivity mainActivity = new MainActivity();
private static NotificationSingleton instance;
private NotificationSingleton()
{
//private to prevent any else from instantiating
}
public static synchronized NotificationSingleton getInstance()
{
if (instance == null){
instance = new NotificationSingleton();
}
return instance;
}
public void stopService()
{
mHandler.removeCallbacks(mNotificationRunnable);
}
public Runnable mNotificationRunnable = new Runnable()
{
@Override
public void run() {
mainActivity.updateNotification();
mHandler.postDelayed(this,1000);
}
};
Logcat
2020-04-13 13:36:28.705 8346-8346/com.example.countdownlockdown E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.countdownlockdown, PID: 8346
java.lang.IllegalStateException: Could not execute method for android:onClick
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:390)
at android.view.View.performClick(View.java:7350)
at android.view.View.performClickInternal(View.java:7327)
at android.view.View.access00(View.java:807)
at android.view.View$PerformClick.run(View.java:28166)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7464)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:955)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
at android.view.View.performClick(View.java:7350)
at android.view.View.performClickInternal(View.java:7327)
at android.view.View.access00(View.java:807)
at android.view.View$PerformClick.run(View.java:28166)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7464)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:955)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
at android.content.ContextWrapper.getPackageName(ContextWrapper.java:148)
at android.content.ComponentName.<init>(ComponentName.java:131)
at android.content.Intent.<init>(Intent.java:6860)
at com.example.countdownlockdown.MainActivity.updateNotification(MainActivity.java:176)
at com.example.countdownlockdown.NotificationSingleton.run(NotificationSingleton.java:76)
at com.example.countdownlockdown.MainActivity.startService(MainActivity.java:158)
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
at android.view.View.performClick(View.java:7350)
at android.view.View.performClickInternal(View.java:7327)
at android.view.View.access00(View.java:807)
at android.view.View$PerformClick.run(View.java:28166)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7464)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:955)
我不确定 MainActivity 是否真的扩展了 Activity component.If 所以 updateNotification 方法中的 MainActivity mainActivity = new MainActivity();
行是完全错误的。您不应该以这种方式创建 Activity 的实例。请删除它并尽可能使用 getContext() 来使用上下文。
我遇到了一个奇怪的问题。
我创建了一个更新通知的函数("updateNotification" 在 MainActivity 中)。然而,奇怪的是我的更新通知功能从 MainActivity 调用没有问题但是当我从另一个 class (notificationSingleton 中的第 76 行)调用它时,我的应用程序立即崩溃。
MainActivity.java
public static TextView dateText;
private CountDownTimer countDownTimer;
private NotificationSingleton notificationSingleton;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// if first start
SharedPreferences prefs = getSharedPreferences("prefs", MODE_PRIVATE);
boolean firstStart = prefs.getBoolean("firstStart", true);
if(firstStart)
{
showStartDialog();
}
// set dateText to date_text
dateText = findViewById(R.id.date_text);
// show date picker when click on show_dialog button
findViewById(R.id.show_dialog).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showDatePickerDialog();
}
});
notificationSingleton = NotificationSingleton.getInstance();
startTimer();
}
private void showStartDialog()
{
new AlertDialog.Builder(this)
.setTitle("One Time Dialog")
.setMessage("This should only be shown once")
.setPositiveButton("ok", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
showDatePickerDialog();
}
})
.create().show();
SharedPreferences prefs = getSharedPreferences("prefs", MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("firstStart", false);
editor.apply();
}
private void showDatePickerDialog()
{
DatePickerDialog datePickerDialog = new DatePickerDialog(
this,
this,
Calendar.getInstance().get(Calendar.YEAR),
Calendar.getInstance().get(Calendar.MONTH),
Calendar.getInstance().get(Calendar.DAY_OF_MONTH)
);
datePickerDialog.show();
}
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth)
{
Date endDate = new Date((year-1900),month,dayOfMonth);
SharedPreferences prefs = getSharedPreferences("prefs", MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putLong("endDate", endDate.getTime());
editor.apply();
startTimer();
}
private void startTimer()
{
long difference = getRemainDays();
if(countDownTimer !=null)
{
countDownTimer.cancel();
countDownTimer = null;
}
countDownTimer = new CountDownTimer(difference,1000) // 1 second
{
@Override
public void onTick(long millisUntilFinished)
{
int days = (int)(millisUntilFinished/(1000*60*60*24));
int hours = (int)((millisUntilFinished/(1000*60*60))%24);
int mins = (int)((millisUntilFinished/(1000*60))%60);
int sec = (int)((millisUntilFinished/(1000))%60);
dateText.setText(String.format("%02d Days %d Hours %d Mins %d Sec",days,hours,mins,sec));
}
@Override
public void onFinish()
{
// Done
dateText.setText("Done");
}
}.start();
}
private long getRemainDays()
{
Date currentDate = new Date();
SharedPreferences prefs = getSharedPreferences("prefs", MODE_PRIVATE);
long endDate = prefs.getLong("endDate", currentDate.getTime());
return endDate - currentDate.getTime();
}
public void startService(View v){
String input = dateText.getText().toString();
Intent serviceIntent = new Intent(this, ExampleService.class);
serviceIntent.putExtra("inputExtra", input);
ContextCompat.startForegroundService(this,serviceIntent);
notificationSingleton.mNotificationRunnable.run();
}
public void stopService(View v){
Intent serviceIntent = new Intent(this,ExampleService.class);
stopService(serviceIntent);
notificationSingleton.stopService();
}
public TextView getDateText()
{
return dateText;
}
public void updateNotification() {
MainActivity mainActivity = new MainActivity();
String input = mainActivity.getDateText().getText().toString();
Intent notificationIntent = new Intent(this, NotificationSingleton.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Example Service")
.setContentText(input)
.setSmallIcon(R.drawable.ic_android)
.setContentIntent(pendingIntent)
.build();
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotificationManager.notify(1, notification);
}
NotificationSingleton.java
public Handler mHandler = new Handler();
MainActivity mainActivity = new MainActivity();
private static NotificationSingleton instance;
private NotificationSingleton()
{
//private to prevent any else from instantiating
}
public static synchronized NotificationSingleton getInstance()
{
if (instance == null){
instance = new NotificationSingleton();
}
return instance;
}
public void stopService()
{
mHandler.removeCallbacks(mNotificationRunnable);
}
public Runnable mNotificationRunnable = new Runnable()
{
@Override
public void run() {
mainActivity.updateNotification();
mHandler.postDelayed(this,1000);
}
};
Logcat
2020-04-13 13:36:28.705 8346-8346/com.example.countdownlockdown E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.countdownlockdown, PID: 8346
java.lang.IllegalStateException: Could not execute method for android:onClick
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:390)
at android.view.View.performClick(View.java:7350)
at android.view.View.performClickInternal(View.java:7327)
at android.view.View.access00(View.java:807)
at android.view.View$PerformClick.run(View.java:28166)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7464)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:955)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
at android.view.View.performClick(View.java:7350)
at android.view.View.performClickInternal(View.java:7327)
at android.view.View.access00(View.java:807)
at android.view.View$PerformClick.run(View.java:28166)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7464)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:955)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
at android.content.ContextWrapper.getPackageName(ContextWrapper.java:148)
at android.content.ComponentName.<init>(ComponentName.java:131)
at android.content.Intent.<init>(Intent.java:6860)
at com.example.countdownlockdown.MainActivity.updateNotification(MainActivity.java:176)
at com.example.countdownlockdown.NotificationSingleton.run(NotificationSingleton.java:76)
at com.example.countdownlockdown.MainActivity.startService(MainActivity.java:158)
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
at android.view.View.performClick(View.java:7350)
at android.view.View.performClickInternal(View.java:7327)
at android.view.View.access00(View.java:807)
at android.view.View$PerformClick.run(View.java:28166)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7464)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:955)
我不确定 MainActivity 是否真的扩展了 Activity component.If 所以 updateNotification 方法中的 MainActivity mainActivity = new MainActivity();
行是完全错误的。您不应该以这种方式创建 Activity 的实例。请删除它并尽可能使用 getContext() 来使用上下文。