I have an android app which has been released on the Google Play store for some time. It runs fine for 99.9% of users. However, the Google Play Console tells me that a few users are suffering from a crash caused by a NullPointerException in the onCreate routine for an activity. The particular line in question is:
final Spinner choose_music = findViewById(R.id.music_list);
The routine never seems to crash with any other call to findViewById
in the routine, just the one for the spinner (and only very rarely). My layout file is listed below, although I doubt that it's relevant. I'm afraid I don't have any logcat output, since the Play Console doesn't provide that.
The onCreate
routine is called from within an activity, when that activity launches. I've included the complete onCreate
routine below, but the finding of the spinner is fairly early on.
Any ideas? Thanks
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="@color/light_grey"
tools:context=".PlayActivity" >
<RelativeLayout
android:id="@+id/main_canvas"
android:layout_weight="90"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/colorAccent">
</RelativeLayout>
<RelativeLayout
android:id="@+id/bottom_panel"
android:layout_weight="90"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="@+id/layout_choose"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/layout_volume"
android:layout_alignBottom="@id/layout_volume"
android:background="@color/mid_grey"
android:layout_alignParentLeft="true">
<TextView
android:id="@+id/choose_music"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="Music"
android:padding="5sp"
android:textSize="20sp"/>
<Spinner
android:id="@+id/music_list"
android:layout_alignParentLeft="true"
android:layout_width="wrap_content"
android:layout_below="@id/choose_music"
android:layout_height="wrap_content"></Spinner>
</RelativeLayout>
<TextView
android:id="@+id/padding_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/layout_choose"
android:text="."
android:textColor="@color/light_grey"
android:padding="2sp"
android:textSize="20sp"/>
<RelativeLayout
android:id="@+id/layout_volume"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/mid_grey"
android:layout_alignParentRight="true"
android:layout_toRightOf="@id/padding_text">
<TextView
android:id="@+id/choose_volume"
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:text="Relative volume"
android:padding="0sp"
android:textSize="20sp"/>
<TextView
android:id="@+id/volume_music"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/choose_volume"
android:layout_alignParentLeft="true"
android:text="Music"
android:padding="5sp"
android:textSize="20sp"/>
<TextView
android:id="@+id/volume_speech"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/choose_volume"
android:layout_alignParentRight="true"
android:text="Speech"
android:padding="5sp"
android:textSize="20sp"/>
<android.support.v7.widget.AppCompatSeekBar
android:id="@+id/relative_volume"
android:padding="10sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@id/volume_speech"/>
</RelativeLayout>
</RelativeLayout>
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_play);
my_view = (RelativeLayout) findViewById(R.id.main_canvas);
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels;
int width = displayMetrics.widthPixels;
view = new CircularMusicController(PlayActivity.this, height, width);
my_view.addView(view, new ActionBar.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
globals.crash_log("Layout dimensions before: " + String.valueOf(my_view.getWidth() + ", "
+ String.valueOf(my_view.getHeight())));
my_view.setLayoutParams(new LinearLayout.LayoutParams(view.get_width(), view.get_height()));
// Get ListView object from xml
final Spinner choose_music = findViewById(R.id.music_list);
int music_index = 0;
for (int i=0; i<globals.music_track_list.length; i+=1) {
if (globals.appState.get_music().equals(globals.music_track_list[i])) {
music_index = i;
}
}
chosen_music = music_index;
// ListView Item Click Listener
ArrayAdapter<CharSequence> music_adapter = new ArrayAdapter<CharSequence>(this, R.layout.activity_listview, globals.music_names);
choose_music.setAdapter(music_adapter);
choose_music.setSelection(music_index);
choose_music.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
globals.crash_log("I have chosen " + String.valueOf(i));
if (chosen_music > 0 && musicBound && musicSrv != null) {
musicSrv.halt();
}
chosen_music = i;
if (musicBound) {
if (i > 0) {
musicSrv.setSong(globals.music_locs[i]);
if (isPlaying()) {
musicSrv.playSong(isPlaying());
} else {
choice_while_paused = true;
}
}
}
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
globals.crash_log("Layout dimensions: " + String.valueOf(my_view.getWidth() + ", "
+ String.valueOf(my_view.getHeight())));
volume_control = findViewById(R.id.relative_volume);
volume_control.setProgress(globals.appState.get_volume());
volume_control.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int volume, boolean from_user) {
if (from_user) {
int focus_vol = globals.roc_function(volume);
try {
if (speechSrv != null) {
speechSrv.set_volume(focus_vol);
}
if (musicSrv != null) {
musicSrv.set_volume(100 - focus_vol);
}
} catch (Exception err) {
globals.crash_log("Failed to set volume");
globals.crash_exception(err);
}
}
globals.crash_log("SeekBar: new volume is " + String.valueOf(volume) + " " +
String.valueOf(from_user));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// Get any information passed down from the parent activity
Intent intent = getIntent();
track_name = intent.getStringExtra("name");
track_location = intent.getStringExtra("location");
res_location = intent.getIntExtra("res_location", 0);
activity_name = intent.getStringExtra("activity_name");
globals.crash_log("PlayActivity: onCreate: activity_name is " + activity_name);
globals.crash_log("PlayActivity: onCreate: track_name is " + track_name);
if ( ! (track_location == null) ) {
globals.crash_log("PlayActivity: onCreate: track_loc is " + track_location);
}
globals.crash_log("PlayActivity: onCreate: res_location is "+String.valueOf(res_location));
// Setup the action bar, and start the broadcast receiver.
ActionBar action_bar = getSupportActionBar();
action_bar.setTitle(track_name);
action_bar.setDisplayHomeAsUpEnabled(true);
IntentFilter filter = new IntentFilter("PLAY_ACTIVITY");
this.registerReceiver(_refreshReceiver, filter);
}