更改为横向会使我的 Android 应用程序崩溃

Posted

技术标签:

【中文标题】更改为横向会使我的 Android 应用程序崩溃【英文标题】:Changing to Landscape crashes my Android app 【发布时间】:2016-08-02 13:36:21 【问题描述】:

我正在开发一个应用程序,并希望用户能够水平或垂直使用他们的手机,但是,如果我从纵向开始并切换到横向,应用程序就会崩溃。如果我开始横向并切换到纵向,它也会崩溃。

这是我的 androidManifest.xml

<?xml version="1.0" encoding="utf-8"?>

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />


<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme.NoActionBar"
    android:screenOrientation="sensor">
    <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:theme="@style/AppTheme.NoActionBar"
        android:configChanges="screenSize|keyboardHidden">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name="net.sourceforge.zbar.android.CameraTest.CameraTestActivity" />
    <activity android:name="com.facebook.FacebookActivity"
        android:configChanges=
            "keyboard|keyboardHidden|screenLayout|screenSize|orientation"
        android:theme="@android:style/Theme.Translucent.NoTitleBar"
        android:label="@string/app_name" />
</application>

我已经尝试过这个this,但是应用程序无法按照here 的描述转到横向。

这是它在 (MainActivity) 中崩溃的活动:

public class MainActivity extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener, LocationListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, UserDelegate 

private static final int SCAN_COUPONS = 1;
public GoogleApiClient googleApiClient;
private Location lastLocation;
EditText zip;
public static User user;
public SharedPreferences sharedPreferences;
public static SQLiteDatabase database;

@Override
protected void onStart() 
    googleApiClient.connect();
    super.onStart();


@Override
protected void onStop() 
    googleApiClient.disconnect();
    super.onStop();


@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.nav_bar_container);

    /*
    ActionBar actionBar = getSupportActionBar();
    if (actionBar != null) 
        actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
        actionBar.setCustomView(R.layout.actionbar);
    
    */
    sharedPreferences = this.getPreferences(Context.MODE_PRIVATE);
    database = openOrCreateDatabase("CouponWallet", MODE_PRIVATE, null);

    /*Typeface iconFont = FontManager.getTypeface(getApplicationContext(), FontManager.FONTAWESOME);
    FontManager.markAsIconContainer(findViewById(R.id.content_main), iconFont);
    FontManager.markAsIconContainer(findViewById(R.id.drawer_layout), iconFont);
    //FontManager.markAsIconContainer(findViewById(R.id.nav_drawer), iconFont);
    FontManager.markAsIconContainer(findViewById(R.id.top_toolbar), iconFont);
    FontManager.markAsIconContainer(findViewById(R.id.bottom_toolbar), iconFont);*/

    FontIconTypefaceHolder.init(getAssets(), "fonts/FontAwesome.ttf"); //allows for icons

    // set up toolbar
    Toolbar toolbar = (Toolbar) findViewById(R.id.top_toolbar);
    setSupportActionBar(toolbar);
    toolbar.setTitle("Coupon Wallet");
    toolbar.hideOverflowMenu();
    FontManager.setFont(findViewById(R.id.top_toolbar), FontManager.getTypeface(this, FontManager.CANDY));

    googleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this).addOnConnectionFailedListener(this).addApi(LocationServices.API).build();
    Log.v("onCreate", "api client created");

    //set up drawer
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    new Thread(new Runnable() 
        @Override
        public void run()  // does ouside of ui thread
            setIcons();
        
    ).start();
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.addDrawerListener(toggle);
    toggle.syncState();

    /*if(sharedPreferences.getInt("user_id", 0) == 0)
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.content_frame, new LoginFragment());
        ft.addToBackStack(null);
        ft.commit();
        getSupportActionBar().setTitle("Login");
    */

    //user = new User(sharedPreferences.getInt("user_id", 1), database);

    //if (Functions.isOnline()) 
    Log.v("onCreate", "creating user " + sharedPreferences.getInt("user_id", 1));
    this.user = new User(1, this);
    //

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);


@Override
public void onBackPressed() 
    FragmentManager fm = getFragmentManager();
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) 
        drawer.closeDrawer(GravityCompat.START);
     else 
        if (fm.getBackStackEntryCount() > 0) 
            fm.popBackStack();
         else 
            super.onBackPressed();
        
    



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

    LayerDrawable layerDrawable = (LayerDrawable) menu.findItem(R.id.action_barcode).getIcon();
    layerDrawable.setDrawableByLayerId(R.id.main_icon, Functions.getFAIcons(this).get("barcode"));
    Functions.setBadgeCount(this, layerDrawable, 2, R.id.num_circle);

    return true;


@Override
public boolean onOptionsItemSelected(MenuItem item) 
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    if (id == R.id.action_barcode) 
        final AlertDialog dialog = new AlertDialog.Builder(this).setView(R.layout.redeem_code_layout).create();
        dialog.show();
        Toolbar toolbar = (Toolbar) dialog.findViewById(R.id.redeem_toolbar);
        toolbar.inflateMenu(R.menu.redeem_menu);
        toolbar.setTitle("Redeem Codes");
        toolbar.setNavigationIcon(Functions.getFAIcons(this).get("times"));
        toolbar.setNavigationOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                dialog.dismiss();
            
        );
        toolbar.inflateMenu(R.menu.redeem_menu);
        toolbar.hideOverflowMenu();
        toolbar.setTitleTextColor(getResources().getColor(R.color.colorBlack));
        FontManager.setFont(toolbar, FontManager.getTypeface(this, FontManager.CHAMPAGNE));
        MenuItem help = toolbar.getMenu().add("Help");
        help.setIcon(Functions.getFAIcons(this).get("question"));
        help.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() 
            @Override
            public boolean onMenuItemClick(MenuItem menuItem) 
                Toast.makeText(getApplicationContext(), "Help Clicked", Toast.LENGTH_LONG).show();
                return false;
            
        );
        final ImageView code = (ImageView) dialog.findViewById(R.id.redeem_code);
        code.setImageDrawable(user.barcode);
        Spinner spinner = (Spinner) dialog.findViewById(R.id.redeem_scan_type);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.spinner_item, new String[]"Barcode", "QR Code", "PDF417", "Aztec");
        spinner.setAdapter(adapter);
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() 
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) 
                switch (i) 
                    case 0:
                        code.setImageDrawable(user.barcode);
                        break;
                    case 1:
                        code.setImageDrawable(user.qr_code);
                        break;
                    case 2:
                        code.setImageDrawable(user.pdf417);
                        break;
                    case 3:
                        code.setImageDrawable(user.aztec);
                        break;
                

                /*for(int j = 0; j < 4; j++)
                    if (i != j) 
                        TextView item = ((TextView) adapterView.getChildAt(j));
                        item.setBackgroundColor(getResources().getColor(R.color.colorWhite));
                        item.setTextColor(getResources().getColor(R.color.colorGray));
                     else 
                        TextView item = ((TextView) adapterView.getChildAt(j));
                        item.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
                        item.setTextColor(getResources().getColor(R.color.colorWhite));
                    
                */
            

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) 
                code.setImageDrawable(user.barcode);
            
        );
        TextView textView = (TextView) dialog.findViewById(R.id.redeem_num);
        long uid = user.id;
        textView.setText(String.format(Locale.US, "%s%011d", "891", uid));
    

    return super.onOptionsItemSelected(item);


/**
 * @param item item selected in nav menu
 * @return if view switch was successful
 */
//@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) 
    int id = item.getItemId();
    Fragment fragment = null;
    String title = "";
    Toolbar toolbar = (Toolbar) findViewById(R.id.bottom_toolbar);
    toolbar.getMenu().clear();
    switch (id)  //based on which section was selected
        case R.id.nav_search:
            title = "Search";
            fragment = new SearchFragment();
            toolbar.setVisibility(View.VISIBLE);
            toolbar.setNavigationIcon(Functions.getFAIcons(getApplicationContext()).get("gear"));
            toolbar.setNavigationOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View view) 
                    Log.v("bottom_toolbar", "horizontal clicked");
                
            );
            toolbar.inflateMenu(R.menu.my_wallet);
            MenuItem map1 = toolbar.getMenu().getItem(0); //only item in the menu
            map1.setIcon(Functions.getFAIcons(getApplicationContext()).get("map"));
            map1.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() 
                @Override
                public boolean onMenuItemClick(MenuItem menuItem) 
                    Log.v("bottom_toolbar", "map clicked");
                    return true;
                
            );
            break;
        case R.id.nav_profile:
            title = "Profile";
            break;
        case R.id.nav_notifications:
            title = "Notifications";
            break;
        case R.id.nav_categories:
            try 
                lastLocation = getLastKnownLocation();
                if (lastLocation != null) 
                    Log.v("categories", "Location accessed");
                    Bundle bundle2 = new Bundle();
                    bundle2.putDouble("lat", lastLocation.getLatitude());
                    bundle2.putDouble("lon", lastLocation.getLongitude());
                    bundle2.putString("type", "loc");
                    fragment = new CategoriesFragment();
                    fragment.setArguments(bundle2);
                    title = "Categories";
                    toolbar.setVisibility(View.VISIBLE);
                    toolbar.setNavigationIcon(Functions.getFAIcons(getApplicationContext()).get("gear"));
                    toolbar.setNavigationOnClickListener(new View.OnClickListener() 
                        @Override
                        public void onClick(View view) 
                            Log.v("bottom_toolbar", "horizontal clicked");
                        
                    );
                    toolbar.inflateMenu(R.menu.categories);
                    break;
                
             catch (SecurityException e)  // if can't get location go straight to search
            
            Log.v("categories", "Location not accessable");
            Toast.makeText(this, "Turn on location services get faster results", Toast.LENGTH_LONG).show();
            AlertDialog dialog2 = new AlertDialog.Builder(this).setView(R.layout.get_zip_dialog).setPositiveButton("Set", new DialogInterface.OnClickListener() 
                @Override
                public void onClick(DialogInterface dialogInterface, int i) 
                    dialogInterface.dismiss();
                
            ).setNegativeButton("Cancel", new DialogInterface.OnClickListener() 
                @Override
                public void onClick(DialogInterface dialogInterface, int i) 
                    dialogInterface.cancel();
                
            ).create();
            dialog2.setOnCancelListener(new DialogInterface.OnCancelListener() 
                @Override
                public void onCancel(DialogInterface dialogInterface) 
                    dialogInterface.dismiss();
                    Toast.makeText(getApplicationContext(), "Cannot get local categories without location", Toast.LENGTH_LONG).show();
                
            );
            zip = (EditText) findViewById(R.id.zip_code);
            dialog2.show();
            break;
        case R.id.nav_wallet:
            fragment = new MyWalletFragment(); //sets up view
            // setting up toolbars
            title = "My Wallet";
            toolbar.setVisibility(View.VISIBLE);
            toolbar.setNavigationIcon(Functions.getFAIcons(getApplicationContext()).get("columns"));
            toolbar.setNavigationOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View view) 
                    Log.v("bottom_toolbar", "horizontal clicked");
                
            );
            toolbar.inflateMenu(R.menu.my_wallet);
            MenuItem map = toolbar.getMenu().getItem(0); //only item in the menu
            map.setIcon(Functions.getFAIcons(getApplicationContext()).get("map"));
            map.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() 
                @Override
                public boolean onMenuItemClick(MenuItem menuItem) 
                    Log.v("bottom_toolbar", "map clicked");
                    return true;
                
            );

            //toolbar.setLogo(R.id.horizontal);
            break;
        case R.id.nav_scan:
            title = "Scan Coupons";
            Intent intent = new Intent(this, CameraTestActivity.class);
            startActivityForResult(intent, SCAN_COUPONS);
            break;
        case R.id.nav_map:
            title = "Map";
            break;
        case R.id.nav_settings:
            fragment = new SettingFragment(); //sets up view
            title = "Settings";
            break;
        case R.id.nav_help:
            title = "Help";
            // Assuming the Help in the nav bar is the same as the settings menu
            fragment = new HelpSettingsFragment();
            break;
    

    if (fragment != null) 
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.content_frame, fragment);
        ft.addToBackStack(null);
        ft.commit();
    

    FontManager.setFont(findViewById(R.id.content_frame), FontManager.getTypeface(this, FontManager.CHAMPAGNE));

    //noinspection ConstantConditions
    getSupportActionBar().setTitle(title);

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;


@Override
public void onLocationChanged(Location location) 
    Log.v("onLocationChanged", "Location changed");
    lastLocation = location;


@Override
public void onConnected(@Nullable Bundle bundle) 
    Log.v("onConnected", "connected");
    try 
        lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
     catch (SecurityException e) 
        e.printStackTrace();
    


@Override
public void onConnectionSuspended(int i) 



@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) 



/**
 * Process a coupon scan
 *
 * @param requestCode Type of activity
 * @param resultCode  if result ok
 * @param data        the returned data
 */
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) 
    if (resultCode == RESULT_CANCELED) 
        Log.e("onActivityResult", "result canceled");
     else if (resultCode == RESULT_OK) 
        if (requestCode == SCAN_COUPONS) 
            String result = data.getStringExtra("result");
            Toast.makeText(this, result, Toast.LENGTH_LONG).show();
            Log.v("onActivityResult", result);
        
    


/**
 * Set the icons in the drawer
 */
private void setIcons() 
    Map<String, Drawable> map = Functions.getFAIcons(getApplicationContext());
    int[] sections = R.id.nav_search, R.id.nav_profile, R.id.nav_notifications, R.id.nav_categories, R.id.nav_wallet,
            R.id.nav_scan, R.id.nav_map, R.id.nav_settings, R.id.nav_help;
    Drawable[] icons = map.get("search"), map.get("user"), map.get("bookmark"), map.get("list"), map.get("barcode"),
            map.get("camera"), map.get("map_o"), map.get("gear"), map.get("question");
    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    Menu m = navigationView.getMenu();
    for (int i = 0; i < sections.length; i++) 
        MenuItem item = m.findItem(sections[i]);
        item.setIcon(icons[i]);
    


/**
 * Gets the last known Location
 *
 * @return The last known location
 * @throws SecurityException if proper permissions not given
 */
private Location getLastKnownLocation() throws SecurityException 
    LocationManager mLocationManager = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE);
    List<String> providers = mLocationManager.getProviders(true);
    Location bestLocation = null;
    Log.v("getLastKnownLocation", "looping through providers");
    for (String provider : providers) 
        Log.v("getLastKnownLocation", provider);
        Location l = mLocationManager.getLastKnownLocation(provider);
        if (l == null) 
            continue;
        
        if (bestLocation == null || l.getAccuracy() < bestLocation.getAccuracy()) 
            // Found best last known location: %s", l);
            bestLocation = l;
        
    
    return bestLocation;


public void settingOnClick(View v) 

    /*
    NotificationCompat.Builder mBuilder =
            new NotificationCompat.Builder(this)
                    .setSmallIcon(R.drawable.logo_shortcut)
                    .setContentTitle("My notification")
                    .setContentText("Hello World!");

    Intent resultIntent = new Intent(this, MainActivity.class);

    // Because clicking the notification opens a new ("special") activity, there's
    // no need to create an artificial back stack.
    PendingIntent resultPendingIntent =
            PendingIntent.getActivity(
                    this,
                    0,
                    resultIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT
            );
    mBuilder.setContentIntent(resultPendingIntent);

    // Sets an ID for the notification
    int mNotificationId = 001;
    // Gets an instance of the NotificationManager service
    NotificationManager mNotifyMgr =
            (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    // Builds the notification and issues it.
    mBuilder.setAutoCancel(true);
    mNotifyMgr.notify(mNotificationId, mBuilder.build());
    */


    Fragment fragment = null;
    switch (v.getId()) 
        case R.id.setting_account:
        case R.id.setting_userIcon:
            fragment = new AccountSettingsFragment();
            break;
        case R.id.setting_location:
        case R.id.setting_locationArrow:
            fragment = new LocationSettingsFragment();
            break;
        case R.id.setting_notifications:
        case R.id.setting_notificationIcon:
            fragment = new NotificationSettingsFragment();
            break;
        case R.id.setting_help:
        case R.id.setting_helpIcon:
            fragment = new HelpSettingsFragment();
            break;
        case R.id.setting_contact:
        case R.id.setting_contactIcon:
            fragment = new ContactUsSettingsFragment();
            break;
        case R.id.setting_privacy:
        case R.id.setting_privacyIcon:
            fragment = new PrivacyPolicySettingsFragment();
            break;
        case R.id.setting_about:
        case R.id.setting_aboutIcon:
            fragment = new AboutSettingsFragment();
            break;
        case R.id.tutorial_loc_enterAnotherLocation:
            fragment = new EnterAnotherLocation();
            break;
        case R.id.tutorial_1_saving:
        case R.id.tutorial_2_saving:
        case R.id.tutorial_3_saving:
            fragment = new FirstTimeLocation();
            break;
    
    if (fragment != null) 
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.replace(R.id.content_frame, fragment);
        ft.addToBackStack(null);
        ft.commit();
    



@Override
public void userFinished(User user) 
    this.user = user;
    Log.v("UserFinished", user.toString());


我得到的错误是here。它是一个 .txt 文件的链接,因为它使问题超出了字符限制。

【问题讨论】:

您需要向我们展示它崩溃的活动以及崩溃的堆栈跟踪 崩溃的堆栈跟踪是什么。 您能否添加崩溃时的堆栈跟踪以及您的 Activity 的 Java 代码 + 应用程序的其余部分。 我也会说“Stacktrace 或者它没有发生”。如果有多个布局,它们的元素是否具有相同的 id? 整个应用程序的代码太多太张贴了。是的,它们的元素具有相同的 ID。很抱歉这篇文章有任何问题,我是新手。 【参考方案1】:

对于在横向和纵向模式下工作,您必须使用保存的实例并恢复保存的实例,否则您的应用程序值 googleApiClient,lastLocation,zip,user 值可能为空值并导致此问题

@Override
public void onSaveInstanceState(Bundle savedInstanceState) 
  super.onSaveInstanceState(savedInstanceState);
  // Save UI state changes to the savedInstanceState.
  // This bundle will be passed to onCreate if the process is
  // killed and restarted.
  savedInstanceState.putBoolean("MyBoolean", true);
  savedInstanceState.putDouble("myDouble", 1.9);
  savedInstanceState.putInt("MyInt", 1);
  savedInstanceState.putString("MyString", "Welcome back to Android");
  savedInstanceState.putParcelable("parcelable", "");
  savedInstanceState.putSerializable("serializable", "");

Bundle 本质上是一种存储 NVP(“名称-值对”)映射的方式,它会传递给 onCreate() 和 onRestoreInstanceState(),您可以在其中提取如下值:

 @Override
public void onRestoreInstanceState(Bundle savedInstanceState) 
  super.onRestoreInstanceState(savedInstanceState);
  // Restore UI state from the savedInstanceState.
  // This bundle has also been passed to onCreate.
  boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
  double myDouble = savedInstanceState.getDouble("myDouble");
  int myInt = savedInstanceState.getInt("MyInt");
  String myString = savedInstanceState.getString("MyString");

【讨论】:

我如何将除基元以外的对象放入savedInstanceState 位置和用户可以添加为可打包或可序列化,具体取决于您如何扩展用户类并将 zip 转换为字符串广告另存为原始文件

以上是关于更改为横向会使我的 Android 应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 unwind segue 会使我的应用程序崩溃?

输入 UISearchBar 会使我的应用程序崩溃

为啥大型本地数组会使我的程序崩溃,而全局数组却不会? [复制]

为啥 ntdll.dll 会使我的 c++ 可执行文件崩溃?

为啥 __inbyte 会使我的软件崩溃?

激活 iPhone 相机操作会使我的应用程序崩溃 [重复]