I have a quick question. I'm trying to enable automatic user creation in my app, so that when you open it for the first time, one and only one user is created. I read the User docs thoroughly, and found that Parse persists the user session on disk, and that once you save an object to that user, that user is saved on the cloud. However, I've noticed two problems with this:
1) When I save an object and create a pointer to the Owner User, the user object does not exist on the cloud.
2) If I check whether the current user is linked using ParseAnonUtils.isLinked(), this sometimes returns true, as in the current user is linked, or false, as in the current user is not linked, for the same exact ParseUser that was cached on session.
Here is the method I'm using to create and determine the user:
private void getUser() {
if (!ParseAnonymousUtils.isLinked(ParseUser.getCurrentUser())) {
Log.v("Miles", "new user");
ParseAnonymousUtils.logIn(new LogInCallback() {
#Override
public void done(final ParseUser user, ParseException e) {
if (e == null) {
user.setUsername(UUID.randomUUID().toString());
user.setPassword(UUID.randomUUID().toString());
user.signUpInBackground(new SignUpCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
user.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.v("Miles", "user saved");
} else {
Log.v("Miles", "user not saved " + String.valueOf(e.getCode()));
}
}
});
} else {
Log.v("Miles", "signup fail " + String.valueOf(e.getCode()));
}
}
});
} else {
Log.v("Miles", "anon login fail " + String.valueOf(e.getCode()));
}
}
});
}
}
Help would be greatly appreciated.
Related
Basically, if a user is located near a certain event, I want to update an attribute called "pending" to "yes". I'm using a for loop to iterate through all the users (this code is just for a demo purposes, there aren't that many users), and check their distance to the specified event. If they are <= 7000 away, then I want to update "pending" to "yes." However, none of the attributes are actually saving?
I have attached my whole code but the relevant snippet occurs after this comment:// ****** NOTIFICATIONS FOR USERS WHO LIVE IN THE NEIGHBOURHOOD ***********
THINGS I KNOW:
the first log statement I put "numUsers" returns how many users are in the query, for me to validate that all of the users are actually queried. It returns 7, which is true! So that works.
IN the for loop, it's successfully printing each users user name at each iteration, so I know it's properly iterating through the users.
lastly, at u.SaveInBackground(....) it's successfully printing out each users name, and "yes" if they are within the distance I specified, or "null" if not.
but when I check the server none of this information is actually stored?
And outside of this method if I try to get any user's "pending" attribute, it will tell me it's null.
I've been stuck on this for hours now!
public void onButtonClickDecision(final View view) {
ParseQuery<ParseObject> query = ParseQuery.getQuery("IncidentReports");
query.whereEqualTo("reference", intent.getStringExtra("reference"));
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(final List<ParseObject> objects, ParseException e) {
if (e == null) {
if (objects.size()>0) {
//if we clicked, decline -> update status to decline
if (view.getId() == R.id.decline) {
objects.get(0).put("status", "declined");
}
// if we clicked approve -> update status to approve
else if (view.getId() == R.id.approve) {
// update status
objects.get(0).put("status", "approved");
// ****** NOTIFICATIONS FOR USERS WHO LIVE IN THE NEIGHBOURHOOD ***********
ParseQuery<ParseUser> query3 = ParseUser.getQuery();
query3.findInBackground(new FindCallback<ParseUser>() {
#Override
public void done(List<ParseUser> users, ParseException e) {
Log.i("numUsers", Integer.toString(users.size()));
if ( e== null && users.size()>0) {
// COMPARE EACH USERS ADDRESS
for (final ParseUser u : users) {
Log.i("user name", u.getUsername());
String address = u.getString("address");
try {
// sets up users home as a Location
List<Address> list = geocoder.getFromLocationName(address, 1);
Address add = list.get(0);
Location home = new Location(LocationManager.GPS_PROVIDER);
home.setLatitude(add.getLatitude());
home.setLongitude(add.getLongitude());
// check if user is located in incident neighbourhood
if (home.distanceTo(incidentLoc) <= 7000) {
u.put("pending", "yes");
}
} catch (IOException ex) {
Log.i("ApprovedCheckingUsers", "failed");
System.out.println(ex.getMessage());
}
u.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
Log.i("Updated:", u.getUsername() + "," + u.getString("pending"));
}
});
}
}
}
});
}
// NOTIFY USER WHO POSTED
objects.get(0).put("notified", "false");
objects.get(0).put("reviewedby", ParseUser.getCurrentUser().getString("username"));
objects.get(0).saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
System.out.println("Saving status updates");
currentStatus.setText(objects.get(0).getString("status"));
Toast.makeText(ViewIndividualReport.this, "Status successfuly changed", Toast.LENGTH_SHORT).show();
} else {
System.out.println("Failed to save");
Toast.makeText(ViewIndividualReport.this, "Could not update status at this time. Try again later.", Toast.LENGTH_SHORT).show();
}
}
});
}
}
}
});
}
I want to get the data using twitter's fabric api but whenever i tend to verify credentials and use a callback it shows an error , specifically ,"The arguments differ in length"
void getUserData() {
Twitter.getApiClient(session).getAccountService()
.verifyCredentials(true, false, new Callback<User>() {
#Override
public void failure(TwitterException e) {
}
#Override
public void success(Result<User> userResult) {
User user = userResult.data;
String twitterImage = user.profileImageUrl;
try {
Log.d("imageurl", user.profileImageUrl);
Log.d("name", user.name);
Log.d("email",user.email);
Log.d("des", user.description);
Log.d("followers ", String.valueOf(user.followersCount));
Log.d("createdAt", user.createdAt);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
If you check the fabric documentation, it shows two version of the method, however when I tried to open the source code in Android Studio but it had only the version without the callback.
You can solve the isssue as follows:
//Getting the account service of the user logged in
Call<User> call = Twitter.getApiClient(session).getAccountService()
.verifyCredentials(true, false);
call.enqueue(new Callback<User>() {
#Override
public void failure(TwitterException e) {
//If any error occurs handle it here
}
#Override
public void success(Result<User> userResult) {
//If it succeeds creating a User object from userResult.data
User user = userResult.data;
String twitterImage = user.profileImageUrl;
try {
Log.d("imageurl", user.profileImageUrl);
Log.d("name", user.name);
Log.d("email",user.email);
Log.d("des", user.description);
Log.d("followers ", String.valueOf(user.followersCount));
Log.d("createdAt", user.createdAt);
} catch (Exception e) {
e.printStackTrace();
}
}
});
Source
Documentation
Just change the twitter dependency in your Build.Gradle
from
compile('com.twitter.sdk.android:twitter:2.0.0#aar') {
transitive = true;
}
to
compile('com.twitter.sdk.android:twitter:1.11.0#aar') {
transitive = true;
}
The new version of the .verifyCredentials() method doesn't accept a callback hence your error.
How do I auto increment a value stored in Firebase from an Android client?
Currently: I declare int id = 1. When I increment, I see the values 2, 3 etc. being stored. That's fine, but when I re-run the project, id is set equal to 1 again.
I want it to behave like a static variable, so I can create an id which will go from 1 to infinity without resetting.
UPDATED FAILED
I used the following to pass the Firebase reference and a string to the function incrementCounter.
if(language_chosen.equalsIgnoreCase("english"))
{
Firebase publRef = f.child("Language").child("English").child("Message");
Firebase newPublRef = publRef.push();
writeMsgActivity demo = new writeMsgActivity();
demo.incrementCounter(newPublRef,the_msg_enter);
}
Now I try to use the passed reference and string at public void incrementCounter(Firebase publref,String my_msg) in the oncomplete method but it gives me an error.
public void incrementCounter(Firebase publref,String my_msg) {
publref.runTransaction(new Transaction.Handler() {
#Override
public Transaction.Result doTransaction(final MutableData currentData) {
if (currentData.getValue() == null) {
currentData.setValue(1);
} else {
currentData.setValue((Long) currentData.getValue() + 1);
}
return Transaction.success(currentData);
}
public void onComplete(FirebaseError firebaseError, boolean committed, DataSnapshot currentData) {
if (firebaseError != null) {
System.out.println("Firebase counter increment failed.");
} else {
System.out.println("Firebase counter increment succeeded.");
Map<String, Object> publ = new HashMap<String, Object>();
publ.put("pubMsg", my_msg);
publ.put("id",currentData);
publref.setValue(publ);
}
}
});
}
UPDATED SOLVED
final Firebase upvoteref = new Firebase("https://shareurday.firebaseio.com/Message/"+msg_id+"/upvotes");
upvoteref.runTransaction(new Transaction.Handler() {
#Override
public Transaction.Result doTransaction(final MutableData currentData) {
if (currentData.getValue() == null) {
currentData.setValue(1);
} else {
currentData.setValue((Long) currentData.getValue() + 1);
}
return Transaction.success(currentData);
}
public void onComplete(FirebaseError firebaseError, boolean committed, DataSnapshot currentData) {
if (firebaseError != null) {
System.out.println("Firebase counter increment failed.");
} else {
System.out.println("Firebase counter increment succeeded.");
}
}
});
The variable msg_id is the random generated id from push.
Here's an example method that increments a single counter. The key idea is that you are either creating the entry (setting it equal to 1) or mutating the existing entry. Using a transaction here ensures that if multiple clients attempt to increment the counter at the same time, all requests will eventually succeed. From the Firebase documentation (emphasis mine):
Use our transactions feature when working with complex data that could be corrupted by concurrent updates
public void incrementCounter() {
firebase.runTransaction(new Transaction.Handler() {
#Override
public Transaction.Result doTransaction(final MutableData currentData) {
if (currentData.getValue() == null) {
currentData.setValue(1);
} else {
currentData.setValue((Long) currentData.getValue() + 1);
}
return Transaction.success(currentData);
}
#Override
public void onComplete(FirebaseError firebaseError, boolean committed, DataSnapshot currentData) {
if (firebaseError != null) {
Log.d("Firebase counter increment failed.");
} else {
Log.d("Firebase counter increment succeeded.");
}
}
});
}
A new feature is added to firestore to autoincrement values. As simple as
document("fitness_teams/Team_1").
updateData(["step_counter" : FieldValue.increment(500)])
refer link:
https://firebase.googleblog.com/2019/03/increment-server-side-cloud-firestore.html
Used below code in my project.
var firestore = Firestore.instance;
firestore.collection('student').document('attendance').updateData({'total_attendace': FieldValue.increment(1)});
I am trying to integrate GoogleDriveSDK
Here is my code
mGoogleClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(new ConnectionCallbacks()
{
#Override
public void onConnectionSuspended(int arg0) {
}
#Override
public void onConnected(Bundle bundle)
{
AccountManager am = AccountManager.get(AddAccountActivity.this);
am.getAuthToken(am.getAccounts()[0], "oauth2:" + DriveScopes.DRIVE, new Bundle(), AddAccountActivity.this,
new OnTokenAcquired(), null);
}
})
.addOnConnectionFailedListener(new OnConnectionFailedListener()
{
#Override
public void onConnectionFailed(ConnectionResult connectionResult)
{
if (connectionResult.hasResolution())
{
try {
connectionResult.startResolutionForResult(AddAccountActivity.this, ACTIVITY_RESULT_GOOGLE);
} catch (IntentSender.SendIntentException e)
{}
}
else
GooglePlayServicesUtil.getErrorDialog(connectionResult.getErrorCode(), AddAccountActivity.this, 0).show();
}
})
.build();
mGoogleClient.connect();
private class OnTokenAcquired implements AccountManagerCallback<Bundle>
{
#Override
public void run(AccountManagerFuture<Bundle> result)
{
try {
final String token = result.getResult().getString(AccountManager.KEY_AUTHTOKEN);
Intent launch = (Intent)result.getResult().get(AccountManager.KEY_INTENT);
if (launch != null) {
startActivityForResult(launch, 3025);
return; // Not sure why... I wrote it here for some reason. Might not actually be necessary.
}
} catch (OperationCanceledException e) {
// Handle it...
} catch (AuthenticatorException e) {
// Handle it...
} catch (IOException e) {
// Handle it...
}
}
}
Now the problem is,i am not sure how can i get RefreshToken from authToken and save it for later use.
Secondly how can i use this refreshtoken saved to initialise Drive?
Not sure how much this helps. But you can have a look at this code and see if it helps.
https://github.com/sDurgam/koszt/blob/master/sTestJSONTables/src/com/example/s_expensemanager/MainActivity.java
Google drive only returns a refresh token during the initial login exchanging the code for the OAuth token.
refresh_token (optional) This field is only present if access_type=offline is included in the authentication request. For details, see Refresh tokens.
See the Google API documentation. This talks about how to us http requests and not the java objects but I would think the objects could be used in the same manor.
Actually I programming a IM service (inherited google chat) by using smack API. But when i want to print buddy list and their presences, the compile mode show all presences unavailable, but in the debug mode it shows the real availability!
My code is ...
1- create connection
public boolean openConnection() {
ConnectionConfiguration connectionConfiguration = new ConnectionConfiguration("talk.google.com", 5222, "mail.google.com");
this.connection = new XMPPConnection(connectionConfiguration);
try {
this.connection.connect();
} catch (XMPPException e) {
// TODO: Send Error Information To Programmer's Email Address
}
if(this.connection.isConnected()) {
this.roster = this.connection.getRoster();
this.roster.addRosterListener(new RosterListener() {
public void entriesAdded(Collection<String> addresses) {}
public void entriesDeleted(Collection<String> addresses) {}
public void entriesUpdated(Collection<String> addresses) {}
public void presenceChanged(Presence presence) {}
});
return true;
}
return false;
}
2- login
public boolean login(String jid, String password) {
try {
this.connection.login(jid, password, "smack");
} catch (XMPPException e) {
// TODO: Send Error Information To Programmer's Email Address
}
if(this.connection.isAuthenticated()) return true;
return false;
}
3- buddy list
public void buddiesList() {
Collection<RosterEntry> rosterEntries = this.roster.getEntries();
for(RosterEntry rosterEntry: rosterEntries) {
System.out.println(rosterEntry.username() + " === " + this.roster.getPresence(rosterEntry.getUser()));
}
}
4- implementation
public static void main(String args[]) {
IMService imService = new IMService();
imService.openConnection();
imService.login("google account", "password");
imService.buddiesList();
}
Your RosterListener doesn't do anything. This is where you have to put code to update your roster when things like presence messages are received.
The presence you are retrieving is a snapshot in time of what the state was when it was created. To keep the state current, you have to actually code the RosterListener. This is clearly stated in the Javadoc for the getPresence() method.
Adding a Listener to your roster could be better:
https://www.igniterealtime.org/builds/smack/docs/latest/documentation/extensions/rosterexchange.html