Matthew Vedua
Matthew Vedua

Reputation: 63

Changing to Landscape crashes my Android app

I am developing an app and want users to be able to use their phones horizontally or vertically, however, if I start in portrait and switch to landscape, the app crashes. It also crashes if I start landscape and switch to portrait.

Here is my 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>

I have already tried this this, but then the app cannot go to landscape as described here.

Here is the activity that it crashed in (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());
}
}

And the error that i get is here. It is a link to a .txt file as it brings the question over the character limit.

Upvotes: 0

Views: 806

Answers (1)

g7pro
g7pro

Reputation: 837

Hii for working in landscape and portrait mode, you have to use saved instance and restore saved instance or else your application values googleApiClient,lastLocation,zip,user values may have null value and causes this issue

@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", "");
}

The Bundle is essentially a way of storing a NVP ("Name-Value Pair") map, and it will get passed in to onCreate() and also onRestoreInstanceState() where you'd extract the values like this:

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

Upvotes: 3

Related Questions