Android 在登录中未包含的函数上解析FB登录崩溃
我集成了Parse登录(v1.10.3),在集成FB登录(v4.8.2)之前,我从未遇到过这个问题。如果卸载并重新安装应用程序并启动,当应用程序启动时,我会收到登录后发生的活动的错误。我将MainActivity作为启动页面,它会检查当前用户。如果当前用户为空,则会重定向到LoginActivity。LoginActivity崩溃,在链接到从主适配器调用的片段的适配器中发生空指针异常错误。为什么要跳过我的登录活动 我的代码中有很多日志,因为我试图确定在某个点上是否存在当前用户值,或者是否执行了任何登录函数,这会导致它跳过登录,但没有执行任何一个,并且当前用户始终为Null(我预期) 登录活动Android 在登录中未包含的函数上解析FB登录崩溃,android,facebook,parse-platform,nullpointerexception,facebook-login,Android,Facebook,Parse Platform,Nullpointerexception,Facebook Login,我集成了Parse登录(v1.10.3),在集成FB登录(v4.8.2)之前,我从未遇到过这个问题。如果卸载并重新安装应用程序并启动,当应用程序启动时,我会收到登录后发生的活动的错误。我将MainActivity作为启动页面,它会检查当前用户。如果当前用户为空,则会重定向到LoginActivity。LoginActivity崩溃,在链接到从主适配器调用的片段的适配器中发生空指针异常错误。为什么要跳过我的登录活动 我的代码中有很多日志,因为我试图确定在某个点上是否存在当前用户值,或者是否执行了任
public static final List<String> mPermissions = new ArrayList<String>() {
{
add("public_profile");
add("email");
add("gender");
add("user_birthday");
}};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
//set and transition to signup page
mSignUpTextView = (TextView)findViewById(R.id.signupText);
mSignUpTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(LoginActivity.this, SignupActivity.class);
startActivity(intent);
}
});
//set and transition to reset password page
mResetPasswordText = (TextView)findViewById(R.id.login_ForgotPasswordText);
mResetPasswordText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(LoginActivity.this, ResetPasswordActivity.class);
startActivity(intent);
}
});
//set and handle all login tasks
mUsername = (EditText)findViewById(R.id.usernameField);
mPassword = (EditText)findViewById(R.id.passwordField);
mLoginButton = (Button)findViewById(R.id.loginButton);
//Facebook login
loginButton = (LoginButton) findViewById(R.id.login_button);
loginButton.setReadPermissions(Arrays.asList("public_profile, email, user_birthday, user_friends"));
callbackManager = CallbackManager.Factory.create();
mFbProfile = Profile.getCurrentProfile();
Log.d("Login FB", String.valueOf(mFbProfile));
// Other app specific specialization
// Callback registration
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ParseFacebookUtils.logInWithReadPermissionsInBackground(LoginActivity.this, mPermissions, new LogInCallback() {
@Override
public void done(ParseUser user, ParseException err) {
if (user == null) {
Log.d("Login", "Uh oh. The user cancelled the Facebook login.");
if (err != null) {
Log.d("ParseFacebookLogin", "Error: " + err.getLocalizedMessage());
}
}
else if (user.isNew()) {
Log.d("Login", "User signed up and logged in through Facebook!");
getUserDetailsFromFB();
//success
FlokkApp.updateParseInstallation(user);
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
Log.d("Login FB", "User logged in through Facebook!");
}
else {
Log.d("Login", "User logged in through Facebook!");
getUserDetailsFromParse();
//success
FlokkApp.updateParseInstallation(user);
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
}
});
}
});
//Regular Parse Login ----------------------------------------------------------
mLoginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String username = mUsername.getText().toString();
String password = mPassword.getText().toString();
username = username.trim();
password = password.trim();
//noinspection StatementWithEmptyBody
if (username.isEmpty() || password.isEmpty()){
// display message if field is blank
AlertDialog.Builder builder = new AlertDialog.Builder(LoginActivity.this);
builder.setMessage(R.string.login_error_message)
.setTitle(R.string.login_error_title)
.setPositiveButton(android.R.string.ok, null);
AlertDialog dialog = builder.create();
dialog.show();
}
else {
// login user
ParseUser.logInInBackground(username, password, new LogInCallback() {
public void done(ParseUser user, ParseException e) {
if (user != null) {
//success
FlokkApp.updateParseInstallation(user);
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
//Toast.makeText(LoginActivity.this, "Successful Login", Toast.LENGTH_SHORT).show();
}
else {
AlertDialog.Builder builder = new AlertDialog.Builder(LoginActivity.this);
builder.setMessage(e.getMessage())
.setTitle(R.string.login_error_title)
.setPositiveButton(android.R.string.ok, null);
AlertDialog dialog = builder.create();
dialog.show();
}
}
});
}
}
});
}
//Facebook login required below ------------------------------------
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d("Login", "on activity result");
super.onActivityResult(requestCode, resultCode, data);
ParseFacebookUtils.onActivityResult(requestCode, resultCode, data);
}
//Facebook save new user code -----------------------------------------------
private void saveNewUser() {
Log.d("Login", "Save new user");
parseUser = ParseUser.getCurrentUser();
parseUser.setUsername(name);
parseUser.setEmail(email);
//will need to update once I figure out how facebook sends the data
boolean genderValue;
if (gender == "Male") {
genderValue = true;
} else {
genderValue = false;
};
parseUser.put(ParseConstants.KEY_GENDERMALE, genderValue);
String searchtext = name.toLowerCase().trim();
parseUser.put(ParseConstants.KEY_SEARCHTEXT, searchtext);
//Saving profile photo as a ParseFile
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Bitmap bitmap = null; //((BitmapDrawable) mProfileImage.getDrawable()).getBitmap();
if (bitmap != null) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, stream);
byte[] data = stream.toByteArray();
String thumbName = parseUser.getUsername().replaceAll("\\s+", "");
final ParseFile parseFile = new ParseFile(thumbName + "_android_FBLogin.jpg", data);
parseFile.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
parseUser.put(ParseConstants.KEY_PROFILEPIC, parseFile);
//Finally save all the user details
parseUser.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
Toast.makeText(LoginActivity.this, "New user:" + name + " Signed up", Toast.LENGTH_SHORT).show();
}
});
}
});
}
}
private void getUserDetailsFromFB() {
Log.d("Login", "getUserDetails From FB");
// Suggested by https://disqus.com/by/dominiquecanlas/
Bundle parameters = new Bundle();
parameters.putString("fields", "email,name,gender,picture");
new GraphRequest(
AccessToken.getCurrentAccessToken(),
"/me",
parameters,
HttpMethod.GET,
new GraphRequest.Callback() {
public void onCompleted(GraphResponse response) {
/* handle the result */
try {
Log.d("Response", response.getRawResponse());
email = response.getJSONObject().getString("email");
//mEmailID.setText(email);
name = response.getJSONObject().getString("name");
mUsername.setText(name);
gender = response.getJSONObject().getString("gender");
JSONObject picture = response.getJSONObject().getJSONObject("picture");
JSONObject data = picture.getJSONObject("data");
// Returns a 50x50 profile picture
String pictureUrl = data.getString("url");
Log.d("Profile pic", "url: " + pictureUrl);
new ProfilePhotoAsync(pictureUrl).execute();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
).executeAsync();
}
private void getUserDetailsFromParse() {
Log.d(" Login", "getUserDetails From parse");
parseUser = ParseUser.getCurrentUser();
//Fetch profile photo
try {
ParseFile parseFile = parseUser.getParseFile(ParseConstants.KEY_PROFILEPIC);
byte[] data = parseFile.getData();
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
//mProfileImage.setImageBitmap(bitmap);
} catch (Exception e) {
e.printStackTrace();
}
//mEmailID.setText(parseUser.getEmail());
mUsername.setText(parseUser.getUsername());
//Toast.makeText(LoginActivity.this, "Welcome back " + mUsername.getText().toString(), Toast.LENGTH_SHORT).show();
}
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_login, menu);
return true;
}
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();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
//Required for facebook
class ProfilePhotoAsync extends AsyncTask<String, String, String> {
public Bitmap bitmap;
String url;
public ProfilePhotoAsync(String url) {
this.url = url;
}
@Override
protected String doInBackground(String... params) {
// Fetching data from URI and storing in bitmap
bitmap = DownloadImageBitmap(url);
return null;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
//mProfileImage.setImageBitmap(bitmap);
saveNewUser();
}
}
public static Bitmap DownloadImageBitmap(String url) {
Bitmap bm = null;
try {
URL aURL = new URL(url);
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
bm = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
} catch (IOException e) {
Log.e("IMAGE", "Error getting bitmap", e);
}
return bm;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ParseAnalytics.trackAppOpened(getIntent());
ParseUser currentUser = ParseUser.getCurrentUser();
if (currentUser == null) {
navigateToLogin();
Log.d("Login Check", String.valueOf(ParseUser.getCurrentUser()));
}
else {
}
toolbar = (Toolbar) findViewById(R.id.app_bar);
setSupportActionBar(toolbar);
mPager = (ViewPager) findViewById(R.id.pager);
mPager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
mTabs = (SlidingTabLayout) findViewById(R.id.tabs);
mTabs.setDistributeEvenly(true);
mTabs.setViewPager(mPager);
try {
PackageInfo info = getPackageManager().getPackageInfo(
"com.myflokk.testflokkd",
PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
}
} catch (PackageManager.NameNotFoundException e) {
} catch (NoSuchAlgorithmException e) {
}
}
//included onResume as a part of facebook integration
@Override
protected void onResume() {
super.onResume();
// Logs 'install' and 'app activate' App Events.
AppEventsLogger.activateApp(this);
}
//included onPause as a part of facebook integration
@Override
protected void onPause() {
super.onPause();
// Logs 'app deactivate' App Event.
AppEventsLogger.deactivateApp(this);
}
private void navigateToLogin() {
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
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();
//noinspection SimplifiableIfStatement
switch (id) {
case R.id.addEvent:
startActivity(new Intent(this, AddEventActivity.class));
break;
case R.id.editProfile:
startActivity(new Intent(this, UserProfileEditActivity.class));
break;
case R.id.action_logout:
ParseUser.logOut();
navigateToLogin();
break;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onStart() {
super.onStart();
ParseUser currentUser = ParseUser.getCurrentUser();
if (currentUser == null) {
navigateToLogin();
Log.d("Login Check 2", String.valueOf(ParseUser.getCurrentUser()));
}
else {
}
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client.connect();
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"Main Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app deep link URI is correct.
Uri.parse("android-app://com.myflokk.testflokkd/http/host/path")
);
AppIndex.AppIndexApi.start(client, viewAction);
}
@Override
public void onStop() {
super.onStop();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"Main Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app deep link URI is correct.
Uri.parse("android-app://com.myflokk.testflokkd/http/host/path")
);
AppIndex.AppIndexApi.end(client, viewAction);
client.disconnect();
}
class MyPagerAdapter extends FragmentPagerAdapter {
String[] tabs;
public MyPagerAdapter(FragmentManager fm) {
super(fm);
tabs = getResources().getStringArray(R.array.tabs);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new UserEventListFragment();
case 1:
return new UserSearchFragment();
case 2:
return new UserProfileActivityFragment();
}
return null;
}
@Override
public CharSequence getPageTitle(int position) {
return tabs[position];
}
@Override
public int getCount() {
return 3;
}
}
导致错误的事件适配器
protected Context mContext;
protected List<ParseObject> mEvents;
private SimpleDateFormat mFormat = new SimpleDateFormat("E, MMM d", Locale.US);
protected Date mDate;
protected List<Object> mLikeList = new ArrayList<>();
protected int mLikes = 0;
protected String Flokking = "I am flokking to this event!";
public EventAdapter(Context context, List<ParseObject> events) {
super(context, R.layout.row_event_list, events);
mContext = context;
mEvents = events;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.row_event_list, null);
holder = new ViewHolder();
holder.eventName = (TextView) convertView.findViewById(R.id.eventRow_TextEventName);
holder.eventLocation = (TextView) convertView.findViewById(R.id.eventRow_TextEventLocation);
holder.eventImage = (ImageView) convertView.findViewById(R.id.eventRow_EventImage);
holder.eventDate = (TextView) convertView.findViewById(R.id.eventRow_Date);
holder.eventNotLiked = (ImageView) convertView.findViewById(R.id.eventRow_ImageNotLiked);
holder.eventLiked = (ImageView) convertView.findViewById(R.id.eventRow_ImageLiked);
holder.eventFlokkingCount = (TextView) convertView.findViewById(R.id.eventRow_FlokkingCount);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
ParseObject event = mEvents.get(position);
ParseObject details = mEvents.get(position);
final String currentEvent = details.getObjectId();
//Log.d("EventAdapter", "This is the position --> " + position);
holder.eventName.setText(event.getString(ParseConstants.KEY_EVENTNAME));
holder.eventLocation.setText(event.getString(ParseConstants.KEY_EVENTVENUE));
holder.eventFlokkingCount.setText(event.getNumber(ParseConstants.EVENT_LIKECOUNT).toString());
//get the date and assign to mDate and then change the way the date is displayed
mDate = event.getDate(ParseConstants.KEY_EVENTDATE);
holder.eventDate.setText(mFormat.format(mDate));
mLikeList = event.getList(ParseConstants.EVENT_LIKES);
Log.d("Login Event Check", String.valueOf(ParseUser.getCurrentUser()));
if (mLikeList == null || mLikeList.isEmpty()) {
//this is false and the user has not liked the event
holder.eventLiked.setVisibility(View.INVISIBLE);
holder.eventNotLiked.setVisibility(View.VISIBLE);
}
else {
//if there are users in the list check for the current user
if (mLikeList.contains(ParseUser.getCurrentUser().getObjectId())) {
// true
holder.eventLiked.setVisibility(View.VISIBLE);
holder.eventNotLiked.setVisibility(View.INVISIBLE);
}
else {
holder.eventLiked.setVisibility(View.INVISIBLE);
holder.eventNotLiked.setVisibility(View.VISIBLE);
}
}
我不确定你是否意识到,但parse正在逐步减少他们的服务。这可以解释错误,但不能确定。查看他们的网站,他们还提供了一些过渡文档。@YoungCoconutCode感谢您的回复,但我知道这一点,不,这与我的错误无关。谢谢
02-01 19:05:28.800 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myflokk.testflokkd, PID: 1933
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.parse.ParseUser.getObjectId()' on a null object reference
at com.myflokk.testflokkd.Adapters.EventAdapter.getView(EventAdapter.java:98)