从Google街景视图恢复到我的应用程序在Android 2.2上崩溃

时间:2014-01-17 07:57:52

标签: android android-fragments actionbarsherlock

我在兼容模式下制作了一个应用程序,支持Android 4.4到Android 2.2(Foroyo)。我正在Android 4.0.4和Android 2.2(真实设备)上测试它。我的应用在Android 2.2上崩溃。

让我解释一下我的情景。我在标签模式下有11个片段的活动。我正在做的是我正在通过意图从片段执行Google街景视图,如下所示:

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);

这是我的MainActivity代码。请参阅我的onCreate()onStart()onPause()onResume()onDestroy()方法:

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);
}

}

在Android 4.0.4上进行测试

它运作得很好。这是我的活动生命周期的主要活动日志,我正在制作标签和片段。

第一次开始我的活动时:

onCreate Activty Called
onStart Activty Called
onResume Activty Called

通过特定片段的意图启动Google StreetView

onPause Activty Called

BackKey Press关闭街景后

onStart Activty Called
onResume Activty Called

在Android 2.2上进行测试

我在Android 2.2中做同样的事情,但这里活动的生命周期有些不同。这是我的活动生命周期的日志

第一次开始我的活动。

onCreate Activty Called
onStart Activty Called
onResume Activty Called

通过特定片段的意图启动Google StreetView

onPause Activty Called

BackKey Press关闭街景后

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

它还重新创建了我的整个活动,包括标签和片段。它看起来重新启动我的应用程序现在,如果我点击任何标签,它只是崩溃并给出空指针异常。

这是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)

以下是我片段的代码:

 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);

}

}

我的片段onCreateView()中是否有错误。如果是这样,为什么它在Android 4.0.4上运行良好?

1 个答案:

答案 0 :(得分:1)

嗯..!表示活动重启。所以这个问题的解决方案可能与此处描述的相同:onDestroy gets called each time the screen goes on

听起来您的活动因配置更改而重新启动,请参阅http://developer.android.com/guide/topics/resources/runtime-changes.html。最常见的是当您的应用处于横向模式(如大多数游戏)时,然后通过点击电源按钮启用屏幕锁定。屏幕锁定处于纵向模式,因此会触发方向更改,从而触发重新启动的活动。

可以通过添加以下内容来覆盖此行为:

android:configChanges="orientation|keyboardHidden"
如果您的API级别低于13,则

...到您的清单文件。或者

android:configChanges="orientation|keyboardHidden|screenSize"

...如果您的API级别大于13。

请注意,您可能需要转到project->properties并更新项目构建目标。如果您的构建目标小于13,则无法识别“screenSize”。

可能是一个不同的配置更改导致活动被重置。以下链接提供了可能的配置更改列表:http://developer.android.com/guide/topics/manifest/activity-element.html#config