I have an issue I have not been able to figure out and it is only happening on devices running <2.1. It works fine on android 2.2. I have ansynchronous task that displays a loading dialog while it loads all the tabs. Here is the code for the TabActivity:
public class OppTabsView extends TabActivity {
Dialog dialog;
String errorText;
boolean save;
final int OPP_SAVE = 0;
public static boolean edited;
public void onCreate(Bundle icicle) {
try {
super.onCreate(icicle);
new DoInBackground().execute();
} catch (Exception e) {
Toast.makeText(this, "Error occured. Please try again later.",
Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onPause() {
super.onPause();
}
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, OPP_SAVE, 0, "Test");
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case OPP_SAVE:
save = true;
new DoInBackground().execute();
return true;
}
return false;
}
public void LoadOpp() {
handler.sendEmptyMessage(0);
}
public void SaveOpp() {
DoStuff();
}
public void LoadLayout() {
setContentView(R.layout.view_opptabs);
/* TabHost will have Tabs */
TabHost tabHost = (TabHost) findViewById(android.R.id.tabhost);
/*
* TabSpec used to create a new tab. By using TabSpec only we can able
* to setContent to the tab. By using TabSpec setIndicator() we can set
* name to tab.
*/
/* tid1 is firstTabSpec Id. Its used to access outside. */
TabSpec firstTabSpec = tabHost.newTabSpec("tid1");
TabSpec secondTabSpec = tabHost.newTabSpec("tid1");
TabSpec thirdTabSpec = tabHost.newTabSpec("tid1");
/* TabSpec setIndicator() is used to set name for the tab. */
/* TabSpec setContent() is used to set content for a particular tab. */
firstTabSpec.setIndicator("General",
getResources().getDrawable(R.drawable.tab_moneybag))
.setContent(new Intent(this, OppTabGeneral.class));
secondTabSpec.setIndicator("Details",
getResources().getDrawable(R.drawable.tab_papers)).setContent(
new Intent(this, OppTabDetails.class));
thirdTabSpec.setIndicator("Contact",
getResources().getDrawable(R.drawable.tab_contact)).setContent(
new Intent(this, OppTabContact.class));
/* Add tabSpec to the TabHost to display. */
tabHost.addTab(firstTabSpec);
tabHost.addTab(secondTabSpec);
tabHost.addTab(thirdTabSpec);
}
private void do_update() {
if (save) {
SaveOpp();
} else {
LoadOpp();
}
}
Handler handler = new Handler() {
public void handleMessage(Message msg) {
LoadLayout();
}
};
private class DoInBackground extends AsyncTask<Void, Void, Void> implements
DialogInterface.OnCancelListener {
protected void onPreExecute() {
String verb = "Connecting";
if (save) {
verb = "Saving";
}
dialog = ProgressDialog.show(OppTabsView.this, "", verb
+ ". Please Wait...", true, true, this);
}
protected Void doInBackground(Void... v) {
do_update();
return null;
}
protected void onPostExecute(Void v) {
dialog.dismiss();
}
public void onCancel(DialogInterface dialog) {
cancel(true);
dialog.dismiss();
finish();
}
}
}
Here is the stack trace from the error:
java.lang.NullPointerException
at android.widget.TabWidget.dispatchDraw(TabWidget.java:206)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.View.draw(View.java:6538)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at android.view.ViewGroup.drawChild(ViewGroup.java:1531)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.View.draw(View.java:6538)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1830)
at android.view.ViewRoot.draw(ViewRoot.java:1349)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1114)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1633)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4363)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
at dalvik.system.NativeStart.main(Native Method)
I have tried stepping through it but the error seems to come out of no where, not at a specific line. Any help is greatly appreciated.
Are you allowed to use the same 'tag' for more than one TabSpec? I'd try setting those correctly and see if it fixes it.
EDIT: OK, so my suggestion didn't fix it but it makes sense to have unique tags anyway.
Try this to see if it helps. Add an option to set the currently selected tab at the end of your LoadLayout() method like so (see last line)...
EDIT2: I found the TabWidget.java source and line 206 (where the NullPointerException occurs) is...
mBottomLeftStrip.setState(selectedChild.getDrawableState());
...there are three possible causes of the exception that I can see.
selectedChild.getDrawableState()
is nullThe last seems to be the likely cause but I'm not sure what could cause it to return null.
Try Google for 'TabWidget.java source' - the second result points at grepcode.com which has line numbers and you can see what it's trying to do at the point of the exception.