Facebook Unity and handling app requests - android

I pulled my original question because I managed to figured it out through trail and error and a lot of deep searching.
So, I understand that using the latest Facebook SDK in Unity, you can pull all pending requests for a player using:
FB.API("/me/apprequests", HttpMethod.GET, RequestHandler)
Where RequestHandler is an IGraphResult, which you can then parse into a Dictionary, like so:
void RequestHandler(IGraphResult result){
if (result != null) {
Dictionary<string, object> reqResult = Json.Deserialize(result.RawResult) as Dictionary<string, object>;
}
}
The documentation explains how a singular request will be displayed in JSON format, and I've found a few examples of how to work with that information (I vaguely understand JSON's), however if pulling ALL requests for the player, how do I work with this information?
Out of the JSON, I'm just trying to pull the object ID and sender ID of each request, handle the request based on the object ID then delete the request from the graph by concatenating the two, which I think I've figured out already.
So my question is, for each request, how do I extract the object and sender ID's?

So after a LOT of trial and error and a lot of Log checks, I've figured out a really hacky way of doing it, for those that aren't sure:
public void TestRequests(){
FB.API("/me/apprequests", HttpMethod.GET, TestResponse);
}
public void TestResponse(IGraphResult result){
if (result.Error == null) {
//Grab all requests in the form of a dictionary.
Dictionary<string, object> reqResult = Json.Deserialize(result.RawResult) as Dictionary<string, object>;
//Grab 'data' and put it in a list of objects.
List<object> newObj = reqResult["data"] as List<object>;
//For every item in newObj is a separate request, so iterate on each of them separately.
for(int xx = 0; xx < newObj.Count; xx++){
Dictionary<string, object> reqConvert = newObj[0] as Dictionary<string, object>;
Dictionary<string, object> fromString = reqConvert["from"] as Dictionary<string, object>;
Dictionary<string, object> toString = reqConvert["to"] as Dictionary<string, object>;
string fromName = fromString["name"] as string;
string fromID = fromString["id"] as string;
string obID = reqConvert["id"] as string;
string message = reqConvert["message"] as string;
string toName = toString["name"] as string;
string toID = toString["id"] as string;
Debug.Log ("Object ID: " + obID);
Debug.Log ("Sender message: " + message);
Debug.Log ("Sender name: " + fromName);
Debug.Log ("Sender ID: " + fromID);
Debug.Log ("Recipient name: " + toName);
Debug.Log ("Recipient ID: " + toID);
}
}
else {
Debug.Log ("Something went wrong. " + result.Error);
}
}
Again, this is my first experience with using JSON, and I'm sure there's a much more efficient way of doing this, but basically after a lot of breaking down and converting, I've managed to extract the object ID, sender name and ID, the message attached and the recipient name and ID. The object ID comes concatenated with the recipient ID, so to operate on the object ID itself, this will need to be removed, however as is it will make it easier to pass the string on to remove the request from the Graph API.
If anyone can suggest to me a more efficient way of doing this, I'd be grateful! There's always more to learn, after all.

Related

Display JsonArray from api and sort

I am trying to display data from a rest api containing a Json Array and a list of Json objects. I tried following a tutorial and was able to display the data on textview. What I actually want to do is gather the data in a Hashmap in terms of key and value pair and sort them accordingly.
public void onResponse(Call<List<Post>> call, Response<List<Post>> response) {
if(!response.isSuccessful()){
textView.setText("Code: " +response.code());
return;
}
int j=0;
List<Post> posts = response.body();
Map<Integer,String> data = new HashMap<Integer, String>();
// Iterating through post and saving data in content variable
for(Post post: posts)
{
String content ="";
//String name = post.getName();
if(!(post.getName()==(null)) && !(post.getName().equals("")))
{
data.put(post.getListid(),post.getName()); //For inserting data into hashmap
content += "ListID: " + post.getListid() + "" + "\n";
content += "Name: " + post.getName() + "" + "\n";
}
textView.append(content);
}
The current code saves the data in a content variable and displays it in the text view.
I am relatively new to using hashmap and retrofit for displaying data. I would really appreciate if someone could explain me where I am going wrong with my code. I tried printing out the data but was only able to print the last line and not the rest.
This is my Json file that I want to sort and display the data
[{"listId":2,"name":null},{"listId":2,"name":"Item 990"},{"listId":2,"name":null},{"listId":2,"name":null},{"listId":2,"name":""},{"listId":4,"name":"Item 771"},{"listId":2,"name":""}]
This is the code that I am using to displaying all my json data in textview
for(Map.Entry entry: data.entrySet())
{ textView.append(entry.getKey()+ " Value:" +entry.getValue() +"\n");}
I if understand correctly, you have a List<Post> posts that you want to sort out ? Why don't you sort the posts as you need and save them accordingly? You could just remove the post from your list if their name are null or ""

how to upload unique message data on sever in android

I am trying upload some message data to server from my android app.it uploaded the server data well, But problem is, it is upload all message data every time when app started.I want to upload only those message data which would not uploaded previously.How to do this?
Here is my code of fetching and uploading the message data on server:
class SmsContent {
public List<SmsInfo> getSmsInfo() {
String[] projection = new String[] { "_id", "address", "person", "body", "date", "type" };
ContentResolver cr = activity.getContentResolver();
Cursor cursor = cr.query(uri, projection, "body"+" LIKE '%"+smsBuilder1+"%'or+" + "body"+" LIKE '%"+smsBuilder2+"%'", null, "date desc");
assert cursor != null;
int nameColumn = cursor.getColumnIndex("person");
smsbodyColumn = cursor.getColumnIndex("body");
int i = 0;
while (cursor.moveToNext() && i++ < 20) {
SmsInfo smsInfo = new SmsInfo();
smsInfo.setName(cursor.getString(nameColumn));
smsInfo.setSmsbody(cursor.getString(smsbodyColumn).trim());
per = (cursor.getString(smsbodyColumn));
smsInfo.setName(null == personName ? smsInfo.getPhoneNumber() : personName);
prepareListData(per);
infos.add(smsInfo);
}
cursor.close();
return infos;
}
private void prepareListData(final String per) {
// Volley's json array request object
StringRequest stringRequest = new StringRequest(Request.Method.POST, REGISTER_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
VolleyLog.d(TAG, "Error: " + response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
// hidePDialog();
}
}){
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put(VENDOR, "test");
params.put(ORGMESSAGE, per);
return params;
}
};
// Adding request to request queue
MyApplication.getInstance().addToRequestQueue(stringRequest);
}
}
If anyone want to know more info please ask.
Save recently received message date in SharedPreferences and have a condition in query so as to select the messages which are received after that date.
String dateFromSharedPreferences="2000-01-01";
try{
String dateFromSharedPreferences=getActivity().getPreferences(Context.MODE_PRIVATE);
dateFromSharedPreferences=sharedPref.getString("LastMsgDate", "2000-01-01");
catch(Exception ex){}
Cursor cursor = cr.query(uri, projection, "(body"+" LIKE '%"+smsBuilder1+"%'or+" + "body"+" LIKE '%"+smsBuilder2+"%') and date>'"+dateFromSharedPreferences+"'", null, "date desc");
Dont forget to save the current last received sms date in the same SharedPreferences
while (cursor.moveToNext() && i++ < 20) {
if(i==1) saveDateToSharedPreferences(cursor.getString(cursor.getColumnIndex("date")))
//other codes here
}
saveDateToSharedPreferences function will be as follows
function saveDateToSharedPreferences(String LastMsgDate){
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("LastMsgDate", LastMsgDate);
editor.commit();
}
Make another column in your table and store data like whether it's uploaded or not. And upload the data which are not uploaded.
So, what you're dealing with here is local cache, mind you that this answer will give you the flow of a way to handle it, the coding is up to you, by the code you posted it seems your up to the task, here are your options:
SharedPreferences.
Android's built in sqlite.
SharedPreferences is an option, but - it would be more suitable for single variables, or for example, an object serialized into a JSON string.
In your case, creating and maintaining a local (on the phone itself, client-side) database would probably be better - since you're maintaining a messaging record, which is big and might reach numbers in the tens, you mentioned that you're not creating a custom table - you should, and since your code suggests that there IS a db somewhere in there, this is generally how I would go about this:
create a new table, holding all the known values plus 2 new columns (e.g. is_sent, is_received).
think of two situations: msg sent, vs. msg received - you might have sent it, the other side (server) might not get it.
Pull the msgs using the cursor (like you did), save them in an ArrayList, and their info in your new table, marking them all as false on the sent and received columns.
Send that list to your server (marking all of them as sent = true in the table).
make sure your server response returns a confirmation (either per id, or just a general "success:true"), and then in the onResponse callback - update your table (use you local list for id comparison if you need to, marking what is relevant with received = true).
modify the method that sends stuff on startup to pull the messages, and first compare them to your table,only send the msgs that are marked as sent=false && received=false, if in doubt - check the id, if it's not in your table - you don't know about it, so send it and make sure your server knows to compare msg id's cross-referenced with user id's to avoid duplicates.
All this requires both client side work and server side work, and possibly some help from your server-side/db guy, and again - this is a possible flow similar to chat message caching, and probably could be greatly tweaked into efficiency when coding.
Hope this Helps.

Firebase , second push() in same method does not work

In my app , there is an activity which upon clicking the save button, 2 sets of data in 2 different places should be made by push(), Since in both places an unique id is needed.
I have followed the sample code in the Firebase guide and added the second push
String userId = auth.getCurrentUser().getUid().toString();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
DatabaseReference firstDatabaseRef = reference.child("first");
DatabaseReference secondDatabaseRef = reference.child("second").child(userId);
String key = firstDatabaseRef.child(userId).push().getKey();
First first = new First(firstAmount,key,firstName);
Map<String, Object> firstValues = first.toMap();
String keySecond = secondDatabaseRef.child(key).push().getKey();
Second second = new Second(secondName,secondAmount,keySecond,key);
Map<String, Object> secondValue = second.toMap();
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("/first/" + userId + "/" + key, firstValues);
childUpdates.put("/second/" + userId + "/" + key + "/" + keySecond, secondValue);
reference.updateChildren(childUpdates);
The result that i got for first was exactly as i expected but for second , instead of creating second/<userId>/<key>/<keySecond>/children, i get this :
"second" : {
//userId
"5TQLPlGf4mbcBRKesQwR30fH1L22" : {
//key
"-KL1030IywlNpkTGC7mU" : {
"secondAmount" : "147",
"Key" : "-KL1030IywlNpkTGC7mU",
"secondName" : "secondName",
"keySecond" : "-KL1030PZlHqD_asSR_8",
}
}
}
Instead of having the final children in another unique id, which by the way is recorded in the keySecond, they are all added directly to the key.
This cannot be accepted since every key must have many keySecond.
I hope that i explained my problem correctly.
Please tell me what am i doing wrong.
How should i modify my code or should i reconsider my data structure completely ?
This is a puzzle. I copy/pasted the code you posted and created stubs for First and Second. Running with Firebase 9.0.2 produced the result shown below, which I believe is what you are expecting. Are you running with a different Firebase version? Is it possible the JSON you posted was produced by a different version of the code you posted?
{
"first" : {
// userId
"ypx8RB3eglTBRPeUT7laQVQ1PZQ2" : {
// key
"-KL3rXeYrscFQNrVQnHb" : {
"firstAmount" : "FirstAmount",
"firstKey" : "-KL3rXeYrscFQNrVQnHb",
"firstName" : "FirstName"
}
}
},
"second" : {
// userId
"ypx8RB3eglTBRPeUT7laQVQ1PZQ2" : {
// key
"-KL3rXeYrscFQNrVQnHb" : {
// keySecond
"-KL3rXe_JyY9Vz2U-NES" : {
"Key" : "-KL3rXeYrscFQNrVQnHb",
"keySecond" : "-KL3rXe_JyY9Vz2U-NES",
"secondAmount" : "SecondAmount",
"secondName" : "SecondName"
}
}
}
}
}
When processing the updateChildren(), the Firebase Database loops over the children that you pass and for each key it essentially does a setValue() with the value you passed.
That means that if you have children with overlapping keys, the value of one of those keys will be written last. The order of these is undefined.
In your case it's fairly easy to merge the updates together:
String key = firstDatabaseRef.child(userId).push().getKey();
First first = new First(firstAmount,key,firstName);
Map<String, Object> firstValues = first.toMap();
String keySecond = secondDatabaseRef.child(key).push().getKey();
Second second = new Second(secondName,secondAmount,keySecond,key);
Map<String, Object> secondValue = trans.toMap();
firstValues.put(keySecond, secondValue); // This is the main change
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("/first/" + userId + "/" + key, firstValues);
reference.updateChildren(childUpdates);

How to know whether liked the post or not without doing searching in the list

I tried to use the fql query to get json response,I used this code for doing this
String postid=jsonObject.getString("id");
String query = "SELECT likes.user_likes FROM stream WHERE post_id = \'" + postid + "'";
Bundle params = new Bundle();
params.putString("method", "fql.query");
params.putString("query", query);
String fqlResponse = Utility.mFacebook.request(params);
System.out.println(fqlResponse);
But I am getting null pointer exception at Utility.mFacebook.request(params);
I am using the default class in Github
I personally find the Facebook Graph API a little inadequate at times. For example, in your current requirement, if you need to use just the Graph API, you will need to first, get a list of all Users who have liked a particular post. After you have a list, you will then have to check if the User ID matches that of the logged in User and then, based on the result, run a function or something.
Instead, FQL offers a simpler function. In my app, for the exact same function, I exclusively make use of FQL.
You can fire a simple query. For example:
SELECT likes.user_likes FROM stream WHERE post_id ='XXXXXXXXXXXXX_XXXXXXXXX'
Replace the X's with the Post's ID. Make sure you surround the Post ID with 'YOUR_POST_ID'
Try it like this in the Graph API Explorer: fql?q=SELECT likes.user_likes FROM stream WHERE post_id = 'ENTER_YOUR_POST_ID'
After running the query, you should get a result that looks this this:
{
"data": [
{
"likes": {
"user_likes": true
}
}
]
}
If the User likes the Post, the field user_likes will be true and false if the User has not liked the Post.
You can parse the result like this (pseudo code):
if (JOLikeStatus.has("likes")) {
JSONObject optLikes = JOLikeStatus.optJSONObject("likes");
if (optLikes.has("user_likes")) {
String getUserLikes = optLikes.getString("user_likes");
if (getUserLikes.equals("true")) {
String getLikeStatus = "true";
} else if (getUserLikes.equals("false")) {
String getLikeStatus = "false";
}
} else {
String getLikeStatus = null;
}
} else {
String getLikeStatus = null;
}
EDIT 2: To get the number (count) of total likes, modify the earlier query like this:
fql?q=SELECT likes.user_likes, likes.count FROM stream WHERE post_id = 'ENTER_YOUR_POST_ID'

Android getting the correct values from an arraylist

Okay I'll try describe this the best way I can.
I have a chat application and I am sending a request to receive a list of public channels.
The string that I receive back from the server is:
RESP_PUBLICCHANNELLIST, channelID 1, channelName 1, channelID 2, channelName 2
And when I add this list to my AlertDialog, it shows each channel and channel ID as a separate channel. I would like to just have the channel name in the AlertDialog and have the channel ID in a map with a key value to it. Is this possible?
Here is my current code I am having problems with:
public void ShowPublicChannelList(){
String PublicChannelsPost = "";
PublicChannelsPost = ExecuteCommand(_chatProtocol.ShowPublicChannelList());
System.out.println("Public Channels: " + PublicChannelsPost);
_publicChannels.add("New..");
List <String> responseList = Arrays.asList(PublicChannelsPost.split(","));
if (responseList.contains("RESP_PUBLICCHANNELLIST")){
for (int i = 1; i < responseList.size(); i++) {
_publicChannels.add(responseList.get(i));
System.out.println("Channels: " + _publicChannels);
}
SetPublicChannelList(_publicChannels);
}
Any help would be fantastic!
Thank you!
If I understand your question correctly, you're unsure about how to parse the server response into a mapping of a channel ID and name? You could simply step through your list of separated strings with steps of two and populate every pair into a single map entry. This does make the assumption that a channel id is always followed by a channel name (or vice versa: every name is preceded by an id).
if (responseList.contains("RESP_PUBLICCHANNELLIST")) {
Map<String, String> channelMap = new HashMap<String, String>();
for (int i=1; i<responseList.size(); i+=2) {
if (i+1 >= responseList.size()) break; // this only happens if not every id has name
channelMap.put(responseList.get(i), responseList.get(i+1));
}
// print values to check correct mapping
for (Map.Entry<String, String> channel : channelMap.entrySet()) System.out.println(channel.getKey() + " | " +channel.getValue());
}
As you can see, I simply break the loop if the length of the source list is 'unexpected'. you might want to consider implementing something more robust, unless you're absolutely sure the illegal case will never arise.

Categories

Resources