0

I have made an app in compatibility mode which supports Android 4.4 up to Android 2.2 (Foroyo). Well I am testing it on Android 4.0.4 and Android 2.2 (real devices). My app crashes on Android 2.2.

Let me explain my scenario. I have an activity with 11 fragments in tabbed mode. What I am doing is I'm executing a Google Street view from a fragment via intent, like this:

Intent streetView = new Intent(android.content.Intent.ACTION_VIEW,
Uri.parse("google.streetview:cbll=" + 40.720032 + ","+ -73.988354 + &cbp=1,99.56,,1,-5.27&mz=21"));
startActivity(streetView);

Here is my MainActivity code. Please see my onCreate(), onStart(), onPause(), onResume(), and onDestroy() method:

public class MainActivity extends SherlockFragmentActivity {

private ArrayList<Class> classes = new ArrayList<Class>();
private Intent intent;

@SuppressWarnings("unchecked")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    classes.add(OverView.class);
    classes.add(LifeStyle.class);
    classes.add(RealState.class);
    classes.add(Events.class);
    classes.add(Deals.class);
    classes.add(Popular.class);
    classes.add(MetroBusStops.class);
    classes.add(Schools.class);
    classes.add(Libraries.class);
    classes.add(Parks.class);
    classes.add(PublicSafety.class);

    // Set up the action bar.
    final com.actionbarsherlock.app.ActionBar actionBar = getSupportActionBar();

    actionBar.setDisplayShowHomeEnabled(false);
    actionBar.setDisplayShowTitleEnabled(false);

    Tab tab = null;

    for (int i = 0; i < classes.size(); i++) {

        tab = actionBar
                .newTab()
                .setText(
                        getResources().getStringArray(R.array.tabs_names)[i])
                .setTabListener(
                        new TabListener<SherlockFragment>(this, "Tab" + i,
                                (Class<SherlockFragment>) classes.get(i)));
        actionBar.addTab(tab);
    }
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    Log.e("onCreate Activty", "Called");

}

@Override
protected void onStart() {

    Log.e("onStart Activty", "Called");

    super.onStart();
}

@Override
protected void onResume() {

    Log.e("onResume Activty", "Called");

    super.onResume();
}

@Override
protected void onPause() {

    Log.e("onPause Activty", "Called");

    super.onPause();
}

@Override
protected void onDestroy() {

    Log.e("onDestroy Activty", "Called");

    super.onDestroy();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getSupportMenuInflater().inflate(R.menu.main, menu);
    return true;
}

public static class TabListener<T extends SherlockFragment> implements
        ActionBar.TabListener {
    private SherlockFragment mFragment;
    private final SherlockFragmentActivity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    /**
     * Constructor used each time a new tab is created.
     * 
     * @param activity
     *            The host Activity, used to instantiate the fragment
     * @param tag
     *            The identifier tag for the fragment
     * @param clz
     *            The fragment's Class, used to instantiate the fragment
     */
    public TabListener(SherlockFragmentActivity activity, String tag,
            Class<T> clz) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
    }

    /* The following are each of the ActionBar.TabListener callbacks */

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        // Check if the fragment is already initialized
        if (mFragment == null) {
            // If not, instantiate and add it to the activity
            mFragment = (SherlockFragment) SherlockFragment.instantiate(
                    mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment, mTag);
        } else {
            // If it exists, simply attach it in order to show it
            ft.attach(mFragment);
        }
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        if (mFragment != null) {
            // Detach the fragment, because another one is being attached
            ft.detach(mFragment);
        }
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // User selected the already selected tab. Usually do nothing.
    }
}

@Override
public void onBackPressed() {
    finish();
    overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);
}

}

Testing on Android 4.0.4

It's working just fine. Here is my activity life cycle's Log of MainActivity in which I'm making tabs and fragments.

While starting my activity for the first time:

onCreate Activty Called
onStart Activty Called
onResume Activty Called

Started Google StreetView via intent from certain fragment

onPause Activty Called

After closing the street view by BackKey Press

onStart Activty Called
onResume Activty Called

Testing on Android 2.2

I'm doing same thing here in Android 2.2 but here the life cycle of activity is some different. Here is my activity life cycle's Log

While starting my activity for the first time.

onCreate Activty Called
onStart Activty Called
onResume Activty Called

Started Google StreetView via intent from certain fragment

onPause Activty Called

After closing the street view by BackKey Press

onCreate Activty Called   (Look this. Why is it called here again? This is Odd behaviour)
onStart Activty Called
onResume Activty Called

It's also re-creating my whole activity including Tabs and fragments. It looks restarted my app. And now If I click on any tab its just crash and gives null pointer exception.

Here is the logcat

01-17 12:53:18.968: E/AndroidRuntime(2596): FATAL EXCEPTION: main
01-17 12:53:18.968: E/AndroidRuntime(2596): java.lang.NullPointerException
01-17 12:53:18.968: E/AndroidRuntime(2596):     at fragment.populor.Popular.onCreateView(Popular.java:72)
01-17 12:53:18.968: E/AndroidRuntime(2596):     at android.support.v4.app.Fragment.performCreateView(Fragment.java:1500)
01-17 12:53:18.968: E/AndroidRuntime(2596):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:927)
01-17 12:53:18.968: E/AndroidRuntime(2596):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
01-17 12:53:18.968: E/AndroidRuntime(2596):     at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
01-17 12:53:18.968: E/AndroidRuntime(2596):     at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1467)
01-17 12:53:18.968: E/AndroidRuntime(2596):     at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:440)
01-17 12:53:18.968: E/AndroidRuntime(2596):     at android.os.Handler.handleCallback(Handler.java:587)
01-17 12:53:18.968: E/AndroidRuntime(2596):     at android.os.Handler.dispatchMessage(Handler.java:92)
01-17 12:53:18.968: E/AndroidRuntime(2596):     at android.os.Looper.loop(Looper.java:123)
01-17 12:53:18.968: E/AndroidRuntime(2596):     at android.app.ActivityThread.main(ActivityThread.java:4627)
01-17 12:53:18.968: E/AndroidRuntime(2596):     at java.lang.reflect.Method.invokeNative(Native Method)
01-17 12:53:18.968: E/AndroidRuntime(2596):     at java.lang.reflect.Method.invoke(Method.java:521)
01-17 12:53:18.968: E/AndroidRuntime(2596):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
01-17 12:53:18.968: E/AndroidRuntime(2596):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
01-17 12:53:18.968: E/AndroidRuntime(2596):     at dalvik.system.NativeStart.main(Native Method)

Here is the code of my fragment:

 public class Popular extends SherlockFragment implements OnClickListener,
    OnItemClickListener {

public Popular() {

}

private View v;
private ListView listView;

private RelativeLayout rel_list, rel_map;
private Button btnList, btnMap;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    if (v != null) {
        ViewGroup parent = (ViewGroup) v.getParent();
        if (parent != null)
            parent.removeView(v);
    }
    try {
        v = inflater.inflate(R.layout.populor_fragment, container, false);
    } catch (InflateException e) {

    }

    listView = (ListView) v.findViewById(R.id.listView1);

    rel_list = (RelativeLayout) v.findViewById(R.id.rel_list);
    rel_map = (RelativeLayout) v.findViewById(R.id.rel_map);
    btnList = (Button) v.findViewById(R.id.btnList);
    btnMap = (Button) v.findViewById(R.id.btnMap);

    listView.setAdapter(new MyListAdapter());

    return v;
}

@Override
public void onStart() {
    super.onStart();

    btnList.setOnClickListener(this);
    btnMap.setOnClickListener(this);

    listView.setOnItemClickListener(this);

}

private class MyListAdapter extends BaseAdapter {

    @Override
    public int getCount() {
        return listItems.size();
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater) getActivity()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View rowView = inflater.inflate(R.layout.populor_list_items,
                parent, false);

        TextView txtCategoryName = (TextView) rowView
                .findViewById(R.id.txtCategory);

        txtCategoryName.setText(listItems.get(position));

        return rowView;
    }

}

@Override
public void onItemClick(AdapterView<?> adapterView, View view, int arg2,
        long arg3) {

    // Clear All previous items colors
    for (int j = 0; j < adapterView.getChildCount(); j++)
        adapterView.getChildAt(j).setBackgroundColor(Color.TRANSPARENT);

    // change the background color of the selected element
    view.setBackgroundColor(Color.LTGRAY);

    showStreetView();

}

private void showStreetView() {

    Intent streetView = new Intent(android.content.Intent.ACTION_VIEW,
            Uri.parse("google.streetview:cbll=" + 40.720032 + ","
                    + -73.988354 + "&cbp=1,99.56,,1,-5.27&mz=21"));


    startActivity(streetView);

}

}

Did I have done something wrong in onCreateView() of my fragment. If so then why is it working fine on Android 4.0.4?

halfer
  • 19,824
  • 17
  • 99
  • 186
Qadir Hussain
  • 8,721
  • 13
  • 89
  • 124

1 Answers1

1

hmm..! means the activity restart. so the solution to this problem may be the same as that described here: onDestroy gets called each time the screen goes on

It sounds like your activity is being restarted due to configuration changes, see http://developer.android.com/guide/topics/resources/runtime-changes.html. The most common is when your app is in landscape mode (like most games) and then the screen lock is engaged by tapping the power button. The screen-lock is in portrait mode and therefore triggers a change in orientation which triggers the activity to be restarted.

This behaviour can be overridden by adding:

android:configChanges="orientation|keyboardHidden"

... to your manifest file if you are targeting API level less than 13. Or

android:configChanges="orientation|keyboardHidden|screenSize"

... if you are targeting API level greater than 13.

Note you may need to go project->properties and update your project build target. 'screenSize' will not be recognised if your build target is less than 13.

It may be a different configuration change that is causing the activity to be reset. The following link provides a list of the possible configuration changes: http://developer.android.com/guide/topics/manifest/activity-element.html#config

Community
  • 1
  • 1
Hamad
  • 5,096
  • 13
  • 37
  • 65