更改为横向会使我的 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 应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章
为啥大型本地数组会使我的程序崩溃,而全局数组却不会? [复制]