Я впервые сталкиваюсь с этой ошибкой, и, честно говоря, я до сих пор не совсем понимаю ее после прочтения темы nullpointerexception. Из того, что я искал, это происходит, когда что-то указывает на ноль и вызывает ошибку. Я не уверен, где я был не прав с моим кодом.
ошибка
03-31 21:40:34.841 31029-31029/com.sti.ravago.researchlayout E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.sti.ravago.researchlayout, PID: 31029
java.lang.NullPointerException
at com.sti.ravago.researchlayout.MainActivity.redirect(MainActivity.java:70)
at com.sti.ravago.researchlayout.ListFragment$1$1.onClick(ListFragment.java:93)
at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:169)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:828)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644)
at dalvik.system.NativeStart.main(Native Method)
Основная деятельность
public class MainActivity extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener {
private final Fragment mTimerFragment = new TimerFragment();
private final Fragment mListFragment = new ListFragment();
private final Fragment mReminderFragment = new RemindFragment();
private final TimerFragment timeFrag = (TimerFragment)getSupportFragmentManager().findFragmentByTag("TimerFragment");
private Fragment mActiveFragment = mTimerFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportFragmentManager().beginTransaction()
.add(R.id.fragContainer, mReminderFragment, "TimerFragment")
.hide(mReminderFragment)
.commit();
getSupportFragmentManager().beginTransaction()
.add(R.id.fragContainer, mListFragment, "ListFragment")
.hide(mListFragment)
.commit();
getSupportFragmentManager().beginTransaction()
.add(R.id.fragContainer, mTimerFragment, "ReminderFragment")
.commit();
BottomNavigationView navigation = findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(this);
}
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
getSupportFragmentManager().beginTransaction()
.hide(mActiveFragment)
.show(mTimerFragment)
.commit();
mActiveFragment = mTimerFragment;
return true;
case R.id.navigation_dashboard:
getSupportFragmentManager().beginTransaction()
.hide(mActiveFragment)
.show(mListFragment)
.commit();
mActiveFragment = mListFragment;
return true;
case R.id.navigation_notifications:
getSupportFragmentManager().beginTransaction()
.hide(mActiveFragment)
.show(mReminderFragment)
.commit();
mActiveFragment = mReminderFragment;
return true;
}
return false;
}
public void redirect(String app) {
timeFrag.startTime(app);
// Toast.makeText(this, "Test", Toast.LENGTH_SHORT).show();
// Toast.makeText(this, app, Toast.LENGTH_SHORT).show();
}
}
Это просто переключение фрагментов и метод вызова активности фрагмента.
ListActivity
public class ListFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frag_list,null);
ListView list1 = view.findViewById(R.id.listview1);
ActivityManager am = (ActivityManager)getActivity().getSystemService(Context.ACTIVITY_SERVICE);
PackageManager packageManager = getActivity().getPackageManager();
ArrayAdapter<String> aa;
List<ActivityManager.RunningAppProcessInfo> runningAppProcessInfo = am.getRunningAppProcesses();
final String pnArr[] = new String[runningAppProcessInfo.size()];
List<String> filteredApps = new ArrayList<>();
final List<String> filteredRunningApps = new ArrayList<>();
final List<String> appNames = new ArrayList<>();
//user-apps loop
List<PackageInfo> apps = getActivity().getPackageManager().getInstalledPackages(0);
for (int i = 0; i < apps.size(); i++){
if ((apps.get(i).applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 1){
filteredApps.add(apps.get(i).packageName);
}
}
//running apps + comparison loop
for (int i = 0; i < runningAppProcessInfo.size(); i++) {
pnArr[i] = runningAppProcessInfo.get(i).processName;
if (filteredApps.contains(runningAppProcessInfo.get(i).processName)) {
filteredRunningApps.add(runningAppProcessInfo.get(i).processName);
}
}
//package name -> app name conversion
for (int i = 0; i < filteredRunningApps.size();i++) {
ApplicationInfo ai = null;
try{
ai = packageManager.getApplicationInfo(filteredRunningApps.get(i),0);
}catch (PackageManager.NameNotFoundException e){}
String title = (String)((ai != null) ? packageManager.getApplicationLabel(ai) : "???");
appNames.add(title);
}
Toast.makeText(getActivity(), "Filtered Apps : " + filteredApps.size() + " | Running Apps : " + runningAppProcessInfo.size() + " | Filtered Running Apps : " + filteredRunningApps.size(), Toast.LENGTH_LONG).show();
ArrayList<String> pnList = new ArrayList<String>();
pnList.addAll(Arrays.asList(pnArr));
aa = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_1,appNames);
list1.setAdapter(aa);
aa.notifyDataSetChanged();
final MainActivity mA = (MainActivity)getActivity();
list1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
AlertDialog.Builder adb = new AlertDialog.Builder(getActivity());
adb.setTitle("Monitor " + appNames.get(position) + "?");
adb.setMessage("Track this application's usage time?");
adb.setPositiveButton("YES", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String app = appNames.get(position);
Toast.makeText(getActivity(), "Currently monitoring " + appNames.get(position) + ".", Toast.LENGTH_SHORT).show();
((MainActivity) getActivity()).redirect(app);
}
});
adb.setNegativeButton("NO", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//Toast.makeText(getActivity(), "test", Toast.LENGTH_SHORT).show();
}
});
adb.show();
}
});
return view;
}
}
Он сказал, что у меня есть ошибки в строке 70 MainActivity и строке 93 ListFragment, которые указывают на этот
timeFrag.startTime(app);
и
((MainActivity) getActivity()).redirect(app);
Если бы мне пришлось угадывать, это startTime
и redirect
указывают на нуль, но как они указывают на ноль и как я могу это исправить?
UPDATE
Итак, я переместил объявление фрагмента в метод, и оно больше не является исключением NullPointerException. Теперь это ClassCastException.
04-01 05:51:17.520 31117-31117/com.sti.ravago.researchlayout E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.sti.ravago.researchlayout, PID: 31117
java.lang.ClassCastException: com.sti.ravago.researchlayout.RemindFragment cannot be cast to com.sti.ravago.researchlayout.TimerFragment
at com.sti.ravago.researchlayout.MainActivity.redirect(MainActivity.java:69)
at com.sti.ravago.researchlayout.ListFragment$1$1.onClick(ListFragment.java:93)
at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:169)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:828)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644)
at dalvik.system.NativeStart.main(Native Method)
Что действительно странно, потому что у меня нет кода, который вызывает RemindFragment, кроме MainActivity. Код MainActivity можно найти выше, единственное изменение - я переместил объявление фрагмента в метод, чтобы избежать исключения NullPointerException. Вот код для TimerFragment и RemindFragment, хотя я не думаю, что они важны в этом случае, но, поскольку они упоминались в ошибках, я полагал, что они могут сыграть свою роль, но я не знаю, если честно.
RemindFragment
package com.sti.ravago.researchlayout;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class RemindFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frag_remind,null);
return view;
}
}
TimerFragment
public class TimerFragment extends Fragment {
Button btnMonitor;
Button btnRemind;
TimePicker tp;
CountDownTimer cdt;
TextView tvTimer, tvRemind;
long startTime = 0;
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
@Override
public void run() {
long millis = System.currentTimeMillis() - startTime;
int seconds = (int)(millis/1000);
int minutes = seconds / 60;
seconds = seconds % 60;
tvTimer.setText(String.format("%d:%02d", minutes, seconds));
timerHandler.postDelayed(this,500);
}
};
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frag_timer, null);
tp = (TimePicker)view.findViewById(R.id.timepick1);
tvTimer = (TextView)view.findViewById(R.id.tvTimer);
tvRemind = view.findViewById(R.id.textView3);
btnMonitor = (Button)view.findViewById(R.id.btn1);
btnRemind = (Button)view.findViewById(R.id.btn2);
btnRemind.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Calendar cal = Calendar.getInstance();
//current
Date c = cal.getTime();
long currentTime = c.getTime();
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy h:mm a");
//String d = sdf.format(c); //output 27/03/2019 3:05 AM
//timepicker time
String tpTime = String.valueOf(tp.getCurrentHour()) +":"+ String.valueOf(tp.getCurrentMinute());
int tpDateDay = cal.get(Calendar.DAY_OF_MONTH);
int tpDateMonth = cal.get(Calendar.MONTH);
int tpDateYear = cal.get(Calendar.YEAR);
Calendar c2 = Calendar.getInstance();
c2.set(tpDateYear,tpDateMonth,tpDateDay,tp.getCurrentHour(),tp.getCurrentMinute(),0);
long tpMillis = c2.getTimeInMillis();
long remaining = tpMillis - currentTime;
Toast.makeText(getActivity(),"Remaining time "+ remaining/1000, Toast.LENGTH_SHORT).show();
cdt = new CountDownTimer(remaining,1000) {
@Override
public void onTick(long millisUntilFinished) {
tvRemind.setText(" " + millisUntilFinished/1000 + " seconds");
}
@Override
public void onFinish() {
Intent intent = new Intent (getActivity(),MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(getActivity(),(int)System.currentTimeMillis(),intent,0);
Notification n = new Notification.Builder(getActivity())
.setContentTitle("Time is up!")
.setContentText("Consider stopping the application now.")
.setSmallIcon(R.drawable.ic_notifications_black_24dp)
.setContentIntent(pIntent)
.setAutoCancel(true)
.build();
NotificationManager nm = (NotificationManager)getActivity().getSystemService(getActivity().NOTIFICATION_SERVICE);
nm.notify(0,n);
tvRemind.setText("0");
}
}.start();
}
});
btnMonitor.setText("Start");
btnMonitor.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Button b = (Button) v;
if (b.getText().equals("Stop")){
timerHandler.removeCallbacks(timerRunnable);
b.setText("Start Monitoring");
}
else {
startTime = System.currentTimeMillis();
timerHandler.postDelayed(timerRunnable, 0);
b.setText("Stop");
Toast.makeText(getActivity(),"Monitoring started.",Toast.LENGTH_SHORT).show();
}
}
});
return view;
}
public void startTime(String app) {
btnMonitor.performClick();
Toast.makeText(getActivity(), "Monitoring for " + app + " started." , Toast.LENGTH_LONG).show();
}
}
Ошибки указывают на эти строки
final TimerFragment timeFrag = (TimerFragment)getSupportFragmentManager().findFragmentByTag("TimerFragment");
, что странно, потому что я поместил его в метод redirect
, чтобы решить исключение NullPointerException.
((MainActivity) getActivity()).redirect(app);
Не уверен, что здесь не так.
Как я могу это исправить?