遇到来自
的null对象的致命错误signInButton = (SignInButton) findViewById(R.id.sign_in_button);
虽然我相信在setSize
onCreate
之前已经实例化了
我完全没有想法,任何人都可以指出是什么导致了这个错误?
package artlvlup.how.to.draw;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.NavigationView;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.InterstitialAd;
import artlvlup.how.to.draw.drawer.MenuItemCallback;
import artlvlup.how.to.draw.drawer.NavItem;
import artlvlup.how.to.draw.drawer.SimpleMenu;
import artlvlup.how.to.draw.drawer.TabAdapter;
import artlvlup.how.to.draw.inherit.BackPressFragment;
import artlvlup.how.to.draw.inherit.CollapseControllingFragment;
import artlvlup.how.to.draw.inherit.PermissionsFragment;
import artlvlup.how.to.draw.providers.CustomIntent;
import artlvlup.how.to.draw.providers.fav.ui.FavFragment;
import artlvlup.how.to.draw.util.Log;
import artlvlup.how.to.draw.util.Helper;
import artlvlup.how.to.draw.util.layout.DisableableViewPager;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
/**
* This file is part of the Universal template
* For license information, please check the LICENSE
* file in the root of this project
*
* @author Sherdle
* Copyright 2016
*/
public class MainActivity extends AppCompatActivity implements
MenuItemCallback, ConfigParser.CallBack,
OnConnectionFailedListener, View.OnClickListener {
private Toolbar mToolbar;
private TabLayout tabLayout;
private DisableableViewPager viewPager;
private NavigationView navigationView;
private TabAdapter adapter;
private static SimpleMenu menu;
private DrawerLayout drawer;
private ActionBarDrawerToggle toggle;
private SignInButton signInButton;
private TextView sign_in_text_button;
private GoogleSignInOptions gso;
private GoogleApiClient mGoogleApiClient;
//Keep track of the interstitials we show
private int interstitialCount = -1;
//Data to pass to a fragment
public static String FRAGMENT_DATA = "transaction_data";
public static String FRAGMENT_CLASS = "transation_target";
public static boolean TABLET_LAYOUT = true;
//Permissions Queu
List<NavItem> queueItem;
MenuItem queueMenuItem;
@Override
public void configLoaded(boolean facedException) {
if (facedException || menu.getFirstMenuItem() == null){
if (Helper.isOnlineShowDialog(MainActivity.this))
Toast.makeText(this, artlvlup.how.to.draw.R.string.invalid_configuration, Toast.LENGTH_LONG).show();
} else {
//Load the first item (we assume the first item doesn't require purchase)
menuItemClicked(menu.getFirstMenuItem().getValue(), menu.getFirstMenuItem().getKey(), false);
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Google Sign-in
// Configure sign-in to request the user's ID, email address, and basic
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
//Initializing signinbutton
signInButton = (SignInButton) findViewById(R.id.sign_in_button);
signInButton.setSize(SignInButton.SIZE_WIDE);
signInButton.setOnClickListener(this);
// Build a GoogleApiClient with access to the Google Sign-In API and the
// options specified by gso.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
//Load the appropriate layout
if (useTabletMenu()){
setContentView(artlvlup.how.to.draw.R.layout.activity_main_tablet);
Helper.setStatusBarColor(MainActivity.this,
ContextCompat.getColor(this, artlvlup.how.to.draw.R.color.myPrimaryDarkColor));
} else {
setContentView(artlvlup.how.to.draw.R.layout.activity_main);
}
mToolbar = (Toolbar) findViewById(artlvlup.how.to.draw.R.id.toolbar);
setSupportActionBar(mToolbar);
if (!useTabletMenu())
getSupportActionBar().setDisplayShowHomeEnabled(true);
else {
getSupportActionBar().setDisplayShowHomeEnabled(false);
}
//Drawer
if (!useTabletMenu()) {
drawer = (DrawerLayout) findViewById(artlvlup.how.to.draw.R.id.drawer);
toggle = new ActionBarDrawerToggle(
this, drawer, mToolbar, artlvlup.how.to.draw.R.string.drawer_open, artlvlup.how.to.draw.R.string.drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
}
//Layouts
tabLayout = (TabLayout) findViewById(artlvlup.how.to.draw.R.id.tabs);
viewPager = (DisableableViewPager) findViewById(artlvlup.how.to.draw.R.id.viewpager);
//Check if we should open a fragment based on the arguments we have
if (getIntent().getExtras() != null && getIntent().getExtras().containsKey(FRAGMENT_CLASS)) {
try {
Class<? extends Fragment> fragmentClass = (Class<? extends Fragment>) getIntent().getExtras().getSerializable(FRAGMENT_CLASS);
if (fragmentClass != null) {
String[] extra = getIntent().getExtras().getStringArray(FRAGMENT_DATA);
HolderActivity.startActivity(this, fragmentClass, extra);
finish();
//Optionally, we can also point intents to holderactivity directly instead of MainAc.
}
} catch (Exception e) {
//If we come across any errors, just continue and open the default fragment
Log.printStackTrace(e);
}
}
//Menu items
navigationView = (NavigationView) findViewById(artlvlup.how.to.draw.R.id.nav_view);
menu = new SimpleMenu(navigationView.getMenu(), this);
if (Config.USE_HARDCODED_CONFIG) {
Config.configureMenu(menu, this);
} else if (!Config.CONFIG_URL.isEmpty() && Config.CONFIG_URL.contains("http"))
new ConfigParser(Config.CONFIG_URL, menu, this, this).execute();
else
new ConfigParser("config.json", menu, this, this).execute();
tabLayout.setupWithViewPager(viewPager);
if (!useTabletMenu()) {
drawer.setStatusBarBackgroundColor(
ContextCompat.getColor(this, artlvlup.how.to.draw.R.color.myPrimaryDarkColor));
}
applyDrawerLocks();
Helper.admobLoader(this, getResources(), findViewById(artlvlup.how.to.draw.R.id.adView));
Helper.updateAndroidSecurityProvider(this);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
public void onPageScrollStateChanged(int state) {}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
public void onPageSelected(int position) {
onTabBecomesActive(position);
}
});
}
@SuppressLint("NewApi")
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 1:
boolean foundfalse = false;
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
foundfalse = true;
}
}
if (!foundfalse){
//Retry to open the menu item
//(we can assume the item is 'purchased' otherwise a permission check would have not occured)
menuItemClicked(queueItem, queueMenuItem, false);
} else {
// Permission Denied
Toast.makeText(MainActivity.this, getResources().getString(artlvlup.how.to.draw.R.string.permissions_required), Toast.LENGTH_SHORT)
.show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
@Override
public void menuItemClicked(List<NavItem> actions, MenuItem item, boolean requiresPurchase) {
// Checking if the user would prefer to show the menu on start
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
boolean openOnStart = prefs.getBoolean("menuOpenOnStart", false);
if (drawer != null)
if (openOnStart && !useTabletMenu() && adapter == null) {
drawer.openDrawer(GravityCompat.START);
} else {
//Close the drawer
drawer.closeDrawer(GravityCompat.START);
}
//Check if the user is allowed to open item
if (requiresPurchase && !isPurchased()) return; //isPurchased will handle this.
if (!checkPermissionsHandleIfNeeded(actions, item)) return; //checkPermissions will handle.
if (isCustomIntent(actions)) return;
//Uncheck all other items, check the current item
if (item != null) {
for (MenuItem menuItem : menu.getMenuItems())
menuItem.setChecked(false);
item.setChecked(true);
}
//Load the new tabs
adapter = new TabAdapter(getSupportFragmentManager(), actions, this);
viewPager.setAdapter(adapter);
//Show or hide the tab bar depending on if we need it
if (actions.size() == 1) {
tabLayout.setVisibility(View.GONE);
viewPager.setPagingEnabled(false);
} else {
tabLayout.setVisibility(View.VISIBLE);
viewPager.setPagingEnabled(true);
}
//Show in interstitial
showInterstitial(false);
onTabBecomesActive(0);
}
private void onTabBecomesActive(int position){
Fragment fragment = adapter.getItem(position);
//If fragment does not support collapse, or if OS does not support collaps, disable collapsing toolbar
if ((fragment instanceof CollapseControllingFragment
&& !((CollapseControllingFragment) fragment).supportsCollapse())
||
(android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT))
lockAppBar();
else
unlockAppBar();
if (position != 0)
showInterstitial(true);
}
/**
* Show an interstitial ad
* @param fromPager if the showing is triggered from a swipe in the viewpager
*/
private void showInterstitial(boolean fromPager){
//if (fromPager) return;
if (getResources().getString(artlvlup.how.to.draw.R.string.admob_interstitial_id).length() == 0) return;
if (SettingsFragment.getIsPurchased(this)) return;
if (interstitialCount == (Config.INTERSTITIAL_INTERVAL - 1)) {
final InterstitialAd mInterstitialAd = new InterstitialAd(this);
mInterstitialAd.setAdUnitId(getResources().getString(artlvlup.how.to.draw.R.string.admob_interstitial_id));
AdRequest adRequestInter = new AdRequest.Builder().addTestDevice(AdRequest.DEVICE_ID_EMULATOR).build();
mInterstitialAd.setAdListener(new AdListener() {
@Override
public void onAdLoaded() {
mInterstitialAd.show();
}
});
mInterstitialAd.loadAd(adRequestInter);
interstitialCount = 0;
} else {
interstitialCount++;
}
}
/**
* Checks if the item is/contains a custom intent, and if that the case it will handle it.
* @param items List of NavigationItems
* @return True if the item is a custom intent, in that case
*/
private boolean isCustomIntent(List<NavItem> items){
NavItem customIntentItem = null;
for (NavItem item : items){
if (CustomIntent.class.isAssignableFrom(item.getFragment())){
customIntentItem = item;
}
}
if (customIntentItem == null) return false;
if (items.size() > 1) Log.e("INFO", "Custom Intent Item must be only child of menu item! Ignorning all other tabs");
CustomIntent.performIntent(MainActivity.this, customIntentItem.getData());
return true;
}
/**
* If the item can be opened because it either has been purchased or does not require a purchase to show.
* @return true if the app is purchased. False if the app hasn't been purchased, or if iaps are disabled
*/
private boolean isPurchased(){
String license = getResources().getString(artlvlup.how.to.draw.R.string.google_play_license);
// if item does not require purchase, or app has purchased, or license is null/empty (app has no in app purchases)
if (!SettingsFragment.getIsPurchased(this) && !license.equals("")) {
String[] extra = new String[] {SettingsFragment.SHOW_DIALOG};
HolderActivity.startActivity(this, SettingsFragment.class, extra);
return false;
}
return true;
}
/**
* Checks if the item can be opened because it has sufficient permissions.
* @param tabs The tabs to check
* @return true if the item is safe to open
*/
private boolean checkPermissionsHandleIfNeeded(List<NavItem> tabs, MenuItem item){
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) return true;
List<String> allPermissions = new ArrayList<>();
for (NavItem tab : tabs){
if (PermissionsFragment.class.isAssignableFrom(tab.getFragment())) {
try {
allPermissions.addAll(Arrays.asList(((PermissionsFragment) tab.getFragment().newInstance()).requiredPermissions()));
} catch (Exception e) {
//Don't really care
}
}
}
if (allPermissions.size() > 1) {
boolean allGranted = true;
for (String permission : allPermissions) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED)
allGranted = false;
}
if (!allGranted) {
//TODO An explaination before asking
requestPermissions(allPermissions.toArray(new String[0]), 1);
queueItem = tabs;
queueMenuItem = item;
return false;
}
return true;
}
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(artlvlup.how.to.draw.R.menu.settings_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case artlvlup.how.to.draw.R.id.settings:
HolderActivity.startActivity(this, SettingsFragment.class, null);
return true;
case artlvlup.how.to.draw.R.id.favorites:
HolderActivity.startActivity(this, FavFragment.class, null);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onBackPressed() {
Fragment activeFragment = null;
if (adapter != null)
activeFragment = adapter.getCurrentFragment();
if (drawer != null && drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else if (activeFragment instanceof BackPressFragment){
boolean handled = ((BackPressFragment) activeFragment).handleBackPress();
if (!handled){
super.onBackPressed();
}
} else {
super.onBackPressed();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null)
for (Fragment frag : fragments)
if (frag != null)
frag.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
getWindow().getDecorView().findViewById(android.R.id.content).invalidate();
}
//Check if we should adjust our layouts for tablets
public boolean useTabletMenu(){
return (getResources().getBoolean(artlvlup.how.to.draw.R.bool.isWideTablet) && TABLET_LAYOUT);
}
//Apply the appropiate locks to the drawer
public void applyDrawerLocks(){
if (drawer == null) {
if (Config.HIDE_DRAWER)
navigationView.setVisibility(View.GONE);
return;
}
if (Config.HIDE_DRAWER){
toggle.setDrawerIndicatorEnabled(false);
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
} else {
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
}
}
public void lockAppBar() {
AppBarLayout.LayoutParams params =
(AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
params.setScrollFlags(0);
}
public void unlockAppBar() {
AppBarLayout.LayoutParams params =
(AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
| AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// An unresolvable error has occurred and Google APIs (including Sign-In) will not
// be available.
}
private void updateUI(boolean signedIn) {
if (signedIn) {
findViewById(R.id.sign_in_button).setVisibility(View.GONE);
findViewById(R.id.sign_out_and_disconnect).setVisibility(View.VISIBLE);
} else {
findViewById(R.id.sign_in_button).setVisibility(View.VISIBLE);
findViewById(R.id.sign_out_and_disconnect).setVisibility(View.GONE);
}
}
private void signIn() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, 100);
}
private void signOut() {
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
// [START_EXCLUDE]
updateUI(false);
// [END_EXCLUDE]
}
});
}
private void revokeAccess() {
Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
// [START_EXCLUDE]
updateUI(false);
// [END_EXCLUDE]
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.sign_in_button:
signIn();
break;
case R.id.sign_out_button:
signOut();
break;
case R.id.disconnect_button:
revokeAccess();
break;
}
}
}
错误如下所示:
06-23 18:24:14.987 24144-24144/artlvlup.how.to.draw E/AndroidRuntime: FATAL EXCEPTION: main
Process: artlvlup.how.to.draw, PID: 24144
java.lang.RuntimeException: Unable to start activity ComponentInfo{artlvlup.how.to.draw/artlvlup.how.to.draw.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.common.SignInButton.setSize(int)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2356)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2418)
at android.app.ActivityThread.access$900(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5289)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:102)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.common.SignInButton.setSize(int)' on a null object reference
at artlvlup.how.to.draw.MainActivity.onCreate(MainActivity.java:126)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2309)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2418)
at android.app.ActivityThread.access$900(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5289)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:102)
答案 0 :(得分:4)
在访问布局中的项目之前,您需要调用setContentView
方法。
应该是第一个,
//Load the appropriate layout
if (useTabletMenu()){
setContentView(artlvlup.how.to.draw.R.layout.activity_main_tablet);
Helper.setStatusBarColor(MainActivity.this,
ContextCompat.getColor(this, artlvlup.how.to.draw.R.color.myPrimaryDarkColor));
} else {
setContentView(artlvlup.how.to.draw.R.layout.activity_main);
}
然后,
//Initializing signinbutton
signInButton = (SignInButton) findViewById(R.id.sign_in_button);
signInButton.setSize(SignInButton.SIZE_WIDE);
signInButton.setOnClickListener(this);
答案 1 :(得分:2)
在行onCreate
之后的super.onCreate...
中,您必须致电loc
并初步设置R.id.sign_in_button
的布局。