We are adding push notifications to an Android app using Parse backend.
It has standard initialisation code like this:
Parse.initialize(Parse.Configuration.Builder(this)
.applicationId("...")
.clientKey("...")
.server("...")
.build()
)
val installation = ParseInstallation.getCurrentInstallation()
installation.put("GCMSenderId", "...")
installation.saveInBackground()
When this changes go to production, we started seeing random "Object not found" error in the backend like this:
app/web.1 verbose: REQUEST for [GET]
/parse/classes/_Installation/null: {} method=GET,
url=/parse/classes/_Installation/null, host=..., connection=close,
x-parse-application-id=..., x-parse-app-build-version=...,
x-parse-app-display-version=..., x-parse-os-version=11,
user-agent=Parse Android SDK API Level 30,
x-parse-installation-id=..., x-parse-client-key=...,
accept-encoding=gzip, x-request-id=..., x-forwarded-for=...,
x-forwarded-proto=https, x-forwarded-port=443, via=1.1 vegur,
connect-time=0, x-request-start=1676010960572, total-route-time=0,
app/web.1 error: Object not found. message=Object not found.,
stack=Error: Object not found. at
/app/node_modules/parse-server/lib/Routers/ClassesRouter.js:70:15
This error appears to happen only on a small group of users. For all our test devices, push notifications work correctly.
It is unclear if these particular users will have problem in receiving push notifications eventually.
Why is Android app getting _Installation/null?
Related
I'm trying to get deferred deep links working on Android. I added a test device in the dashboard & reset the device data and made sure the app is uninstalled. When I click a branch.io link, it takes me to the play store as expected. I then launch the app from Android Studio onto the phone, then the logs say that Branch SDK sent a request to https://api2.branch.io/v1/install, but the problem is the response doesn't contain the original link, query params, or key value pairs I set in the dashboard. This is the JSONObject I'm receiving in onInitFinished:
{"+match_guaranteed":true,"link_click_id":"976953359423305632","+clicked_branch_link":true,"+click_timestamp":1634196720,"+is_first_session":true,"utm_source":"test-referrer"}
Where is all the other information? This doesn't include the original link, the key-value pairs, tags, etc.
For a comparison, this is what I receive in the iOS app:
["$ios_passive_deepview": "branch_passive_default", "source": "test-referrer", "+is_first_session": 1, "~channel": test-referrer, "$matching_ttl_s": 7200, "~id": 976763609660742721, "~creation_source": 1, "$one_time_use": 0, "~marketing": 1, "~referring_link": "https://myapp.test-app.link/test-referrer", "~feature": "test", "+click_timestamp": 1634249299, "+match_guaranteed": 0, "$og_description": "My app description", "$og_title": "MyApp", "+clicked_branch_link": 1, "$marketing_title": "Test Referral Link", "~tags": ["test-referrer"], "~campaign": "test"]
If I rotate the phone to recreate the Activity or reopen the app a single time, it then sends a request to https://api2.branch.io/v1/open and returns all the info I expected initially. How do I get the information after installing the app?
I'm currently testing with myapp.test-app.link, and I call Branch.enableTestMode() before Branch.getAutoInstance(this) in my custom Application class's onCreate(). I also tried with a live link and got the same result.
These are the libraries I'm using in build.grade:
implementation 'io.branch.sdk.android:library:5.0.13'
implementation 'com.google.firebase:firebase-appindexing:20.0.0'
implementation 'com.google.android.gms:play-services-ads-identifier:17.1.0'
implementation 'androidx.browser:browser:1.3.0'
I've also set up app links and the uri scheme in the dashboard as well as in the app. Using getFirstReferringParams() and getLatestReferringParams() on the first session after installing doesn't help either.
UPDATE:
Repeating the exact same testing process I described above, now the JSONObject that gets passed into onInitFinished has even less information and is claiming that I'm not clicking a branch link:
{"+clicked_branch_link":false,"+is_first_session":true}
And getFirstReferringParams() returns an empty json object.
I'm about to start looking for an alternative at this rate.
I fixed this issue by adding intent.putExtra("branch_force_new_session", true); right after this.activity.setIntent(intent); when initialising the intent. Something like this:
...
this.activity.setIntent(intent);
intent.putExtra("branch_force_new_session", true);
Branch
.sessionBuilder(this.activity)
.withCallback(branchReferralInitListener)
.reInit();
...
Look here for the branch_force_new_session reference.
The other reason for the missing data is the non-existent link alias, but it looks like it is not the case as soon as you tried with the same link in iOS.
I'm migrating my Android and iOS app from Parse.com to Parse Server. First I'm doing this migration with a test app to be sure everything is ok.
With iOS there has been no problem but with Android the updated app crashes each time the user enters in the app.
This is the Android code updated:
public static void initParse(Application app) {
ctxt = app.getApplicationContext();
Parse.enableLocalDatastore(app);
// Old version
//Parse.initialize(app, "<my app id>", "<my client key>");
// New version
Parse.initialize(new Parse.Configuration.Builder(ctxt)
.applicationId("<my app id>")
.clientKey(null)
.server("https://<my new server>/parse/")
.build()
);
ParseUser.enableRevocableSessionInBackground();
}
The crash returns a "com.parse.ParseException: java.lang.IllegalStateException: unable to encode an association with an unsaved ParseObject", and taking into account what I've read in Stackoverflow, this is because ParseUser.getCurrentUser() returns null (despite the user is logged in) and Parse methods fail.
In fact, if I take this same code, uncomment the old version of Parse.initialize, comment the new version of Parse.initialize, compile and launch the app, this is launched without problems and the user can use it properly.
But again, if I comment the old version of Parse.initialize, uncomment the new version of Parse.initialize, compile and launch the app, this crashes inmediately because ParseUser.getCurrentUser() returns null and Parse methods fail.
What am I missing here? Should I force my users to login again? This seems to me a bad UX, and anyway, in iOS I have no problems with the new version, what is the difference between both platforms?
EDIT 1:
Following Robert Rowntree advice I've changed the initialization to this:
public static void initParse(Application app) {
ctxt = app.getApplicationContext();
Parse.enableLocalDatastore(app);
// Old version
//Parse.initialize(app, "<my app id>", "<my client key>");
// New version
Parse.initialize(new Parse.Configuration.Builder(ctxt)
.applicationId("<my app id>")
.clientKey("<my client key>")
.server("https://<my new server>/parse/")
.build()
);
//Parse.setLogLevel(Parse.LOG_LEVEL_DEBUG);
Parse.setLogLevel(Parse.LOG_LEVEL_VERBOSE);
ParseUser.enableRevocableSessionInBackground();
}
Besides this I've checked that my Parse version is the last available, I have this in my gradle file:
compile 'com.parse.bolts:bolts-android:1.+'
compile 'com.parse:parse-android:1.+'
And the result is the same, the app crashes with "com.parse.ParseException: java.lang.IllegalStateException: unable to encode an association with an unsaved ParseObject" the first call I make to Parse.
Besides this, the unique log I can see related to parse is one related to GCM token, nothing else.
EDIT 2:
I've tried another thing, uninstall the app with the old initialization and install it with the new initialization and as I guessed the new version is now working.
But, of course this is not a solution to me, I can not tell my users to uninstall the app ans install it again.
But this is a hint: there is no problem with the new initialization but with how the old Parse "reacts" when opening the app with the new Parse Server, there must be any inconsistency in getCurrentUser or something like that.
Can you try initializing like this:
Parse.initialize(new Parse.Configuration.Builder(this)
.applicationId("APP_ID")
.clientKey("CLIENT_KEY")
.server("https://SERVER_URL/parse/") // The trailing slash is important.
.enableLocalDataStore()
.build()
);
notice the
.enableLocalDataStore()
is in the initilization. Remove this:
Parse.enableLocalDatastore(app);
Following the instructions on UrbanAirship documentation, I need to add a TagGroup to a namedUser with this lines of code on a demo App in Android
airship.getPushManager().getNamedUser().setId("123456");
airship.getPushManager().getNamedUser().editTagGroups().addTag("loyalty", "elite").apply();
But, the LogCat shows this error:
D/UrbanAirshipDemo - UALib﹕ Received a response for tag groups: Response: ResponseBody: ResponseHeaders: {null=[HTTP/1.1 400 Bad Request], Connection=[close, Transfer-Encoding], Content-Type=[application/vnd.urbanairship+json; version=3], Date=[Wed, 24 Jun 2015 20:02:06 GMT], Transfer-Encoding=[chunked], X-Android-Received-Millis=[1435176126629], X-Android-Response-Source=[NETWORK 400], X-Android-Sent-Millis=[1435176126427]} ResponseMessage: Bad Request Status: 400
E/UrbanAirshipDemo - UALib﹕ Update tag groups failed with status: 400
E/UrbanAirshipDemo - UALib﹕ Both add & remove fields are present and the intersection of the tags in these fields is not empty.
Is it something weird on their API? Instructions from here: http://docs.urbanairship.com/platform/android.html#named-user-tag-groups
Is just simple the implementation, but their API is returning 400. Push notifications are working fine
I was able to reproduce the same issue. The error message is incorrect, the real issue is the tag group does not exists yet. Groups can only be created through Go. Try creating the group following - http://docs.urbanairship.com/topic-guides/tag-groups-walkthrough.html#create-a-tag-group and try again.
The error message will be fixed in a future release.
I am first mobile application developing on Smartface App Studio. I have tho question.
1- I see this error: Access violation at address 00000000. Read of address 00000000 when add second Dataset. And does not run application on emulator or usb real phone until delete Dataset.
2- I read Local.Notifications guide but could not run notifications on phone screen. I saved dates to table but can not make them as reminder. Which page should i add the function block and how should i do this.
Thanks.
It seems a problem is occured when adding a Dataset. Did you try with a second project ? It seems working with the latest version of Smartface App Studio which downloadable via Account page.
Local Notifications are not added to the calendar/reminder. These are app specific notifications.
First off all, you should create a local notification.
For example;
var localNotification = new Notifications.LocalNotification({
id : id,
fireDate : new Date(),
alertTitle : "AlertTitle",
alertBody : "Alert Body",
smallIcon : "icon_notification_small.png",
launchImage : "icon_notification.png",
sound : "notifsound.mp3",
repeatInterval : Notifications.CalendarUnit.minute,
onReceivedNotification : function (e) {
alert("onReceived");
}
});
It creates a notification for you and it works at given date.
If you want to immaediately show the notification , you should run that code below;
Notifications.local.presentNotification(localNotification);
I found how to send push notification to Android device using Django here (here is the code).
So adopted that and my code looks like this:
def sendAndroidPushNotification(registration_id, collapse_key, a, b) :
try:
auth = getNewAndroidAuthorizationToken() # this works I'm fetching new token so this is up to date (its length is 267 characters)
push_request = urllib2.Request("https://android.apis.google.com/c2dm/send")
data = urllib.urlencode({'data.testA' : a,
'data.testB' : b,
'collapse_key' : collapse_key,
'registration_id': registration_id
})
push_request.add_data( data )
push_request.add_header('Authorization', 'GoogleLogin auth=' + auth)
push_request.add_header('Content-Type', 'application/x-www-form-urlencoded')
push_request.add_header('Content-Length', len(data))
urllib2.build_opener().open(push_request)
except urllib2.HTTPError as e:
print 'got exception during push notification'
print 'Reason: "{0}" code: {1}'.format(e.reason, e.code)
pass
this give me error: "Reason: "Unauthorized" code: 401" (at some point it was 403). Version which uses httplib.HTTPSConnection instead of urllib2.Request has same problem.
It looks almost the same as code shown here so I'm totally confused. What I'm doing wrong?
Edit:
Just in case, here is how I fetch authorization token (it looks like that it works fine), maybe my parsing is wrong:
def getNewAndroidAuthorizationToken() :
request = urllib2.Request("https://www.google.com/accounts/ClientLogin")
data = urllib.urlencode({'accountType' : 'HOSTED_OR_GOOGLE',
'Email' : 'someaccount#gmail.com',
'Passwd' : 'asdjsdfa',
'service' : 'ac2dm',
'source' : 'com.mycompany.mypackage',})
request.add_data(data)
content = urllib2.build_opener().open(request)
lines = content.readlines()
for line in lines :
if line.find("Auth=")==0 :
return line[5:]
return
C2DM is deprecated. Developers are encouraged to switch to GCM, C2DM will be supported for a short time. Simple API instead of ClientLogin and oAuth2 which are not supported.
http://developer.android.com/guide/google/gcm/index.html