Related
I´m newbie on Android and need help.
I have a JSON that looks like this:
{
"Id": 1,
"Name": "user",
"userId": 4,
"active": true,
"ProfileId": 1,
"Tema": "green",
"Language": "english",
"success": true,
"error": false
}
Json 2:
{"message":"no user or password","success":false,"erroAplicacao":false}
This is my code:
public class MainActivity extends AppCompatActivity {
EditText usernameWidget;
EditText passwordWidget;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().hide();
usernameWidget = (EditText) findViewById(R.id.tv_username);
passwordWidget = (EditText) findViewById(R.id.tv_password);
}// END ON CREATE
public class DownloadTask extends AsyncTask<String, Void, String> {
String message = "message";
String loginSuccess;
String Id = "Id";
#Override
protected String doInBackground(String... urls) {
String result = "";
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL(urls[0]);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream);
int data = reader.read();
while (data != -1){
char current = (char) data; // each time creates a char current
result += current;
data = reader.read();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
} // END doInBackground
//Method called when the doInBack is complete
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
try {
JSONObject jsonObject = new JSONObject(result);
Log.i("***JSON ITSELF***", result);
loginSuccess = jsonObject.getString("success");
Log.i("*****LOGIN SUCCESS*****", loginSuccess);
message = jsonObject.getString("message");
Log.i("*****MESSAGE*****", message);
Id = jsonObject.getString("Id");
Log.i("*****ID*****", pessoaFisicaId);
}catch(JSONException e) {
e.printStackTrace();
}// END CATCH
if (loginSuccess.contains("true")){
Intent intent = new Intent(getApplicationContext(), SecondActivity.class);
startActivity(intent);
}else if (loginSuccess.contains("false")){
Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
}
}// END POST EXECUTE
}// END Download Task
public void login(View view) {
String user = usernameWidget.getText().toString();
String pass = passwordWidget.getText().toString();
String stringJSON = "*URL*login=" + user + "&senha=" + pass;
DownloadTask task = new DownloadTask();
task.execute(stringJSON);
Log.i("*****JSON URL*****", stringJSON);
}// END LOGIN
}// END MAIN
In this order:
loginSuccess = jsonObject.getString("success");
message = jsonObject.getString("message");
Id = jsonObject.getString("Id");
I get the message ("no user or password") from json2 (different url) as a Toast.
If I change the order, lets say, to:
loginSuccess = jsonObject.getString("success");
Id = jsonObject.getString("Id");
message = jsonObject.getString("message");
I don´t get a message. In fact I get the value "message" from the String message at the start of the DownloadTask class.
It seems that the json is only getting two values, the first ones I ask for.
One thing though is that only when the user or password is wrong is that the json has a message (json2):
{"message":"no user or password","success":false,"erroAplicacao":false}
Since my json cant be transformed into an array json (I tried and got error saying this), what should I do?
When you call jsonObject.getString("your_string"), this will throw a JSONException if your string cannot be found. Therefore, the remaining lines in of code in the method will not be executed. Change your LogCat settings to verbose and you should be able to see what's going on.
More info on the getString() method here:
https://developer.android.com/reference/org/json/JSONObject.html#getString(java.lang.String)
Use GSON
public class User{
private int Id;
private String Name;
}
Parse
User user = GSON.fromJSON(jsonString, User.class);
I have a JSOUP Login program that logs into a website and grabs info from the page. It works well, but it takes ~3 seconds for the information to be parsed into ArrayLists as JSOUP takes a while.
I also have a check to see if the correct page is loaded correctly. (It's just checking the ArrayLists to see if they are empty meaning the page isn't loaded)
public void onClick(View v) {
SourcePage sp = new SourcePage(user.getText().toString(), pass.getText().toString());
if(sp.isConnected()) { //Refer to the bottom of the next code box
Toast.makeText(getApplicationContext(), sp.getGradeLetters().get(0), Toast.LENGTH_SHORT).show();
startActivity(new Intent(MainActivity.this, gradepage.class));
}else {
Toast.makeText(getApplicationContext(), "Login Failed", Toast.LENGTH_SHORT).show();
}
}
private void login() {
Thread th = new Thread() {
public void run() {
try {
HashMap<String, String> cookies = new HashMap<>();
HashMap<String, String> formData = new HashMap<>();
Connection.Response loginForm = Jsoup.connect(URL)
.method(Connection.Method.GET)
.userAgent(userAgent)
.execute();
Document loginDoc = loginForm.parse();
String pstoken = loginDoc.select("#LoginForm > input[type=\"hidden\"]:nth-child(1)").first().attr("value");
String contextData = loginDoc.select("#contextData").first().attr("value");
String dbpw = loginDoc.select("#LoginForm > input[type=\"hidden\"]:nth-child(3)").first().attr("value");
String serviceName = "PS Parent Portal";
String credentialType = "User Id and Password Credential";
cookies.putAll(loginForm.cookies());
//Inserting all hidden form data things
formData.put("pstoken", pstoken);
formData.put("contextData", contextData);
formData.put("dbpw", dbpw);
formData.put("serviceName", serviceName);
formData.put("credentialType", credentialType);
formData.put("Account", USERNAME);
formData.put("ldappassword", PASSWORD);
formData.put("pw", PASSWORD);
Connection.Response homePage = Jsoup.connect(POST_URL)
.cookies(cookies)
.data(formData)
.method(Connection.Method.POST)
.userAgent(userAgent)
.execute();
mainDoc = Jsoup.parse(homePage.parse().html());
//Get persons name
NAME = mainDoc.select("div#sps-stdemo-non-conf").select("h1").first().text();
//Getting Grades for Semester 2
Elements grades = mainDoc.select("td.colorMyGrade").select("[href*='fg=S2']");
System.out.println(grades);
for (Element j : grades)
{
if (!j.text().equals("--")) {
String gradeText = j.text();
gradeLetter.add(gradeText.substring(0, gradeText.indexOf(" ")));
gradeNumber.add(Double.parseDouble(gradeText.substring(gradeText.indexOf(" ") + 1)));
}
}
Elements teachers = mainDoc.select("td[align='left']");
for (int i = 1; i < teachers.size(); i += 2)
{
String fullText = teachers.get(i).text().replaceAll("//s+", ".");
teacherList.add(fullText);
}
}catch (IOException e) {
System.out.println(e);
}
}
};
th.start();
}
public boolean isConnected() {
return (!(gradeLetter.isEmpty() || gradeNumber.isEmpty() || teacherList.isEmpty()));
}
The big problem is that the program (onClick) is giving the Toast "Login Failed" because the isConnected method doesn't wait for the page to load. How can I fix this?
http://www.androidhive.info/2014/10/android-building-group-chat-app-using-sockets-part-2/
Hi,
This is a tutorial about building a group chat app using socket programming. This app allows us to chat between multiple devices like android mobiles and web.
I want to send more than one "String" at a time to the server. I'm having trouble figuring that out.
The link to the tutorial where I downloaded the code is pasted above. I've already made the dynamic web page and I have it hosted on eapps.com At the very bottom of the this email is the edited code for the app. If you click the link above, you can see how I changed it.
The way it works is..
A web socket is created using WebSocketClient class and it has all the callback methods like onConnect, onMessage and onDisconnect.
In onMessage method parseMessage() is called to parse the JSON received from the socket server.
In parseMessage() method, the purpose of JSON is identified by reading the flag value.
When a new message is received, the message is added to list view data source and adapter.notifyDataSetChanged() is called to update the chat list.
sendMessageToServer() method is used to send the message from android device to socket server.
playBeep() method is called to play device’s default notification sound whenever a new message is received.
When you click the btnSend. it uses this method from the UtilsXd class. I've changed it a little in an attempt to pass an extra value.
public String getSendMessageJSONXD(String message, String whichPicIndex) {
String json = null;
try {
JSONObject jObj = new JSONObject();
jObj.put("flag", FLAG_MESSAGE);
jObj.put("sessionId", getSessionId());
jObj.put("message", message);
jObj.put("id", id);
json = jObj.toString();
} catch (JSONException e) {
e.printStackTrace();
}
return json;
}
First of all, what I still don't understand is, where did the values for
String sessionId = jObj.getString("sessionId");
and
String onlineCount = jObj.getString("onlineCount");
from this method
private void parseMessage(final String msg, String idINDEX) {
come from.
They were't added in the JSON object created in the UtilsXD class so how are they created?
That's not the problem I'm having. This is.
superString is the value I want to pass to dictate which picture to show.
superString = (sharedPrefs.getString("prefSyncAvatar", "1"));
You can change your picture in from the settings.
When a message is received, a switch/case statement changes the picture of/ for the message received according to the value passed by superString.
I should be able to sit there and just receive messages, and whatever number the user passes, the profilePicture should be set according to that number.
Here's where the problem begins.
This constructer builds a message based of the message that's just been parsed.
// Message m = new Message(fromName, message, isSelf);
Message m = new Message(fromName, message, isSelf, id, name,
image, status, profilePic, timeStamp, url);
In this method.
private void parseMessage(final String msg, String idINDEX) {
I can pass an value to the string "id" excluding the JSON I need it to.
String id = idINDEX;
this works,
String id = "0";
this works,
String id = utils.getPictureId();
this works,
String id = jObj.getString("id");
This doesn't work.
This is the error I'm getting.
org.json.JSONException: No value for id (this is the issue)
I've added the key/value pair
jObj.put("id", id);
in
public String getSendMessageJSONXD(String message, String whichPicIndex) {
but it's not coming though to the message.
Here's where I think the problem is.
The method onMessage, isn't can't take an extra parameter because it's from a library project. And I can't find that method to make a new constructor.
#Override
public void onMessage(String message) {
Log.d(TAG, String.format("Got string message! %s", message));
parseMessage(message, superString);
}
#Override
public void onMessage(byte[] data) {
Log.d(TAG, String.format("Got binary message! %s",
bytesToHex(data)));
String hello = "99";
parseMessage(bytesToHex(data), superString);
}
/////// Here's the final code below ////////
// JSON flags to identify the kind of JSON response
private static final String TAG_SELF = "self", TAG_NEW = "new",
TAG_MESSAGE = "message", TAG_ID = "id", TAG_EXIT = "exit";
#SuppressWarnings("deprecation")
#SuppressLint({ "NewApi", "CutPasteId" })
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_chat);
showUserSettings();
getActionBar().setTitle("City Chat - Beta 1.3");
superString = (sharedPrefs.getString("prefSyncAvatar", "1"));
listView = (ListView) findViewById(R.id.list_view_messages);
feedItems = new ArrayList<FeedItem>();
// We first check for cached request
vollewStuff();
//
//
// THis is where this fun begins
btnSend = (Button) findViewById(R.id.btnSend);
inputMsg = (EditText) findViewById(R.id.inputMsg);
listViewMessages = (ListView) findViewById(R.id.list_view_messages);
utils = new UtilsXD(getApplicationContext());
// Getting the person name from previous screen
Intent i = getIntent();
name = i.getStringExtra("name");
Integer.parseInt((sharedPrefs.getString("prefSyncAvatar", "1")));
btnSend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Sending message to web socket server
sendMessageToServer(utils.getSendMessageJSONXD(inputMsg
.getText().toString(), superString), superString);
utils.storePictureId((sharedPrefs.getString("prefSyncAvatar",
"1")));
// Clearing the input filed once message was sent
inputMsg.setText("");
}
});
listMessages = new ArrayList<Message>();
adapter = new MessagesListAdapter(this, listMessages, feedItems);
listViewMessages.setAdapter(adapter);
/**
* Creating web socket client. This will have callback methods
* */
client = new WebSocketClient(URI.create(WsConfig.URL_WEBSOCKET
+ URLEncoder.encode(name)), new WebSocketClient.Listener() {
#Override
public void onConnect() {
}
/**
* On receiving the message from web socket server
* */
#Override
public void onMessage(String message) {
Log.d(TAG, String.format("Got string message! %s", message));
parseMessage(message, superString);
// parseMessage(message,
// (sharedPrefs.getString("prefSyncAvatar", "1")));
}
#Override
public void onMessage(byte[] data) {
Log.d(TAG, String.format("Got binary message! %s",
bytesToHex(data)));
String hello = "99";
parseMessage(bytesToHex(data), superString);
// Message will be in JSON format
// parseMessage(bytesToHex(data),
// (sharedPrefs.getString("prefSyncAvatar", "1")));
}
/**
* Called when the connection is terminated
* */
#Override
public void onDisconnect(int code, String reason) {
String message = String.format(Locale.US,
"Disconnected! Code: %d Reason: %s", code, reason);
showToast(message);
//
// clear the session id from shared preferences
utils.storeSessionId(null);
}
#Override
public void onError(Exception error) {
Log.e(TAG, "Error! : " + error);
// showToast("Error! : " + error);
showToast("Are you sure you want to leave?");
}
}, null);
client.connect();
}
/**
* Method to send message to web socket server
* */
private void sendMessageToServer(String message, String id) {
if (client != null && client.isConnected()) {
client.send(message);
client.send(id);
}
}
/**
* Parsing the JSON message received from server The intent of message will
* be identified by JSON node 'flag'. flag = self, message belongs to the
* person. flag = new, a new person joined the conversation. flag = message,
* a new message received from server. flag = exit, somebody left the
* conversation.
* */
private void parseMessage(final String msg, String idINDEX) {
try {
jObj = new JSONObject(msg);
// JSON node 'flag'
String flag = jObj.getString("flag");
String id = idINDEX;
// if flag is 'self', this JSON contains session id
if (flag.equalsIgnoreCase(TAG_SELF)) {
String sessionId = jObj.getString("sessionId");
// Save the session id in shared preferences
utils.storeSessionId(sessionId);
Log.e(TAG, "Your session id: " + utils.getSessionId());
} else if (flag.equalsIgnoreCase(TAG_NEW)) {
// If the flag is 'new', new person joined the room
String name = jObj.getString("name");
String message = jObj.getString("message");
// number of people online
String onlineCount = jObj.getString("onlineCount");
showToast(name + message + ". Currently " + onlineCount
+ " people online!");
} else if (flag.equalsIgnoreCase(TAG_MESSAGE)) {
// if the flag is 'message', new message received
String fromName = name;
String message = jObj.getString("message");
String sessionId = jObj.getString("sessionId");
// switch (Integer.parseInt((sharedPrefs.getString(
// "prefSyncAvatar", "1"))))
boolean isSelf = true;
switch (Integer.parseInt(utils.getPictureId())) {
case 1:
profilePic = "http://clxxxii.vm-host.net/clxxxii/citychatlion.png";
break;
case 2:
profilePic = "http://clxxxii.vm-host.net/clxxxii/citychatmatt.png";
break;
case 3:
profilePic = "http://clxxxii.vm-host.net/clxxxii/citychatroboman.png";
break;
case 4:
profilePic = "http://clxxxii.vm-host.net/clxxxii/citychatalien.png";
break;
case 5:
profilePic = "http://clxxxii.vm-host.net/clxxxii/citychatkitty.png";
break;
case 10:
profilePic = "http://clxxxii.vm-host.net/clxxxii/citychatkitty.png";
break;
}
// Checking if the message was sent by you
if (!sessionId.equals(utils.getSessionId())) {
fromName = jObj.getString("name");
// profilePic = jObj.getString("profilePic");
//
//
//
//
jObj.getString("message");
isSelf = false;
profilePic = "http://clxxxii.vm-host.net/clxxxii/citychatalien.png";
}
// profilePic =
// "http://clxxxii.vm-host.net/clxxxii/citychatlion.png";
Integer.parseInt(utils.getPictureId());
String name = "clxxxii";
String image = "http://i.huffpost.com/gen/1716876/thumbs/o-ATLANTA-TRAFFIC-facebook.jpg";
String status = "status";
String timeStamp = "1403375851930";
String url = "url";
// Message m = new Message(fromName, message, isSelf);
Message m = new Message(fromName, message, isSelf, id, name,
image, status, profilePic, timeStamp, url);
// Appending the message to chat list
appendMessage(m);
} else if (flag.equalsIgnoreCase(TAG_EXIT)) {
// If the flag is 'exit', somebody left the conversation
String name = jObj.getString("name");
String message = jObj.getString("message");
showToast(name + message);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
///////// I've updated the socket server from the first project. /////// I've added the JSON value "id" successfully /// But I how do I change the value without having to type in "5" please see below..
//
This is the JSONutilty method I changed.
//
public String getSendAllMessageJson(String sessionId, String fromName,
String message, String photoId) {
String json = null;
try {
JSONObject jObj = new JSONObject();
jObj.put("flag", FLAG_MESSAGE);
jObj.put("sessionId", sessionId);
jObj.put("name", fromName);
jObj.put("message", message);
jObj.put("id", photoId);
json = jObj.toString();
} catch (JSONException e) {
e.printStackTrace();
}
return json;
}
}
This is the method that is being used by SocketServer. I can successfully send a message from this activity, to the utility method to send over the network.
// Normal chat conversation message
json = jsonUtils //
.getSendAllMessageJson(sessionId, name, message, "5");
How can I retrieve a value sent over the network to place in spot where I have "5" instead of hard coding it?
Thanks!!!
jobj doesn't have the value id. Example of the JSON object looks like this:
{
"message": " joined conversation!",
"flag": "new",
"sessionId": "4",
"name": "Ravi Tamada",
"onlineCount": 6
}
(as shown in the part1 of the same tutorial).
That solves the first issue of onlineCount and sessionId.
Thanks #miselking, you where correct, The server was missing the JSON string "id". To actually solve the problem of post.
"I want to send more than one "String" at a time to the server. I'm having trouble figuring that out."
This is how you do it.
Step 1)
Adding the string photoId to the method
public String getSendAllMessageJson(String sessionId, String fromName,
String message, String photoId) {
String json = null;
try {
JSONObject jObj = new JSONObject();
jObj.put("flag", FLAG_MESSAGE);
jObj.put("sessionId", sessionId);
jObj.put("name", fromName);
jObj.put("message", message);
jObj.put("id", photoId);
json = jObj.toString();
} catch (JSONException e) {
e.printStackTrace();
}
return json;
}
}
Step 2)
Add the string to the correct sting to the method.
String json = null;
json = jsonUtils
.getSendAllMessageJson(sessionId, name, message,
photoId);
Step 3) Parse the JSON
try {
JSONObject jObj = new JSONObject(message);
msg = jObj.getString("message");
photoId = jObj.getString("id");
} catch (JSONException e) {
e.printStackTrace();
}
I'm using Volley however I'm having some problems with the JSON parsed data most likely because volley doesn't implement something like AsyncTask's onPostExecute() and I'm getting some duplicated data on wrong list items.
Then I came across this: https://github.com/yakivmospan/volley-request-manager#custom-listener-implementation-
Has anyone use it? How can I add it to my current Volley code?
More details about my problem here Volley not sending correct data. How to implement an alternative to onPostExecute()?
UPDATE
As requested, some code. Here's a button that calls a method on another class that uses Volley to request some raw JSON data (NovaJSON) and then send the JSON to a parser class (NovaParser):
info.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String instanceDetail = NovaJSON.shared().receiveDetail(getId());
Dialog dialog = new Dialog(v.getContext());
dialog.setContentView(R.layout.instances_info);
TextView image = (TextView) dialog.findViewById(R.id.imageInstance);
TextView flavor = (TextView) dialog.findViewById(R.id.flavorInstance);
dialog.setTitle(name.getText() + " Details");
if (instanceDetail != null) {
image.setText(" \u2022 image : " + NovaParser.shared().parseImages(instanceDetail));
flavor.setText(" \u2022 flavor : " + NovaParser.shared().parseFlavor(instanceDetail));
}
dialog.show();
}
});
This is the method that does the Volley request on the NovaJSON class:
public void getJSONdetail() {
final String authToken = getAuth();
String novaURL = getNova();
novaURL = novaURL+"/servers/"+id;
JsonObjectRequest getRequest = new JsonObjectRequest(Request.Method.GET, novaURL, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("Nova on Response", response.toString());
setNovaJSONdetail(response.toString());
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("Nova on Error", "Error: " + error.getMessage());
setNovaJSONdetail(error.toString());
}
}
) {
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("X-Auth-Token", authToken);
params.put("User-Agent", "stackerz");
params.put("Accept", "application/json");
params.put("Content-Type", "application/json; charset=utf-8");
return params;
}
};
queue = VolleySingleton.getInstance(this).getRequestQueue();
queue.add(getRequest);
}
It then sends the JSON from the server as a string to be parsed using the following methods:
public static String parseImages(String imagesDetail){
ArrayList<HashMap<String, String>> imagesList = NovaParser.shared().getImagesList();
String temp = null;
JSONObject novaDetail = null;
try {
novaDetail = new JSONObject(imagesDetail);
JSONObject server = novaDetail.getJSONObject("server");
JSONObject image = server.getJSONObject("image");
if (imagesList !=null){
temp = image.getString("id");
for (Map<String,String> map : imagesList) {
if (map.containsValue(temp)) {
temp = map.get(NAME);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return temp;
}
public static String parseFlavor(String instanceDetail){
ArrayList<HashMap<String, String>> flavorList = NovaParser.shared().getFlavorList();
String temp = null;
JSONObject novaDetail = null;
try {
novaDetail = new JSONObject(instanceDetail);
JSONObject server = novaDetail.getJSONObject("server");
JSONObject flavor = server.getJSONObject("flavor");
if (flavorList !=null){
temp = flavor.getString("id");
for (Map<String,String> map : flavorList) {
if (map.containsValue(temp)) {
temp = map.get(NAME);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return temp;
}
When I press the button once the dialog is displayed with empty values. When I press it the second time I get the correct parsed data. Basically first time I click the button the instanceDetail string is null because Volley didn't finish doing its thing then I click the 2nd time it loads the values accordingly because it finally finished the 1st request.
I understand Volley is asynchronous, the requests happen in parallel and the responses sometimes are not immediate however I need some sort of progress bar or spinning wheel to give the user some feedback that the app is waiting for data. It could be done with AsyncTask however it doesn't seem to be possible with Volley.
I think your problem is not because of Volley.
Check the parameters you send and receive.
However if you need onPostExcecute you have Volley's callback:
Response.Listener<JSONObject> and Response.ErrorListener() which are called after the request.
About Volley request manager just switch all your volley calls with appropriate Volley request manager calls
I solved my problem by dumping Volley altogether and moving to Retrofit. I setup all the calls to be sync/blocking, worked out the exceptions/errors using try/catches and setup a short timeout on the OkHTTP client. Now it's working as I wanted.
I am trying to add a feature to my android app that allows users to "checkin" with other people tagged to the checkin.
I have the checkins method working no problem and can tag some one by adding the user ID as a parameter (see code below)
public void postLocationTagged(String msg, String tags, String placeID, Double lat, Double lon) {
Log.d("Tests", "Testing graph API location post");
String access_token = sharedPrefs.getString("access_token", "x");
try {
if (isSession()) {
String response = mFacebook.request("me");
Bundle parameters = new Bundle();
parameters.putString("access_token", access_token);
parameters.putString("place", placeID);
parameters.putString("Message",msg);
JSONObject coordinates = new JSONObject();
coordinates.put("latitude", lat);
coordinates.put("longitude", lon);
parameters.putString("coordinates",coordinates.toString());
parameters.putString("tags", tags);
response = mFacebook.request("me/checkins", parameters, "POST");
Toast display = Toast.makeText(this, "Checkin has been posted to Facebook.", Toast.LENGTH_SHORT);
display.show();
Log.d("Tests", "got response: " + response);
if (response == null || response.equals("") ||
response.equals("false")) {
Log.v("Error", "Blank response");
}
} else {
// no logged in, so relogin
Log.d(TAG, "sessionNOTValid, relogin");
mFacebook.authorize(this, PERMS, new LoginDialogListener());
}
} catch(Exception e) {
e.printStackTrace();
}
}
This works fine (I've posted it in case it is of help to anyone else!), the problem i am having is i am trying to create a list of the users friends so they can select the friends they want to tag. I have the method getFriends (see below) which i am then going to use to generate an AlertDialog that the user can select from which in turn will give me the id to use in the above "postLocationTagged" method.
public void getFriends(CharSequence[] charFriendsNames,CharSequence[] charFriendsID, ProgressBar progbar) {
pb = progbar;
try {
if (isSession()) {
String access_token = sharedPrefs.getString("access_token", "x");
friends = charFriendsNames;
friendsID = charFriendsID;
Log.d(TAG, "Getting Friends!");
String response = mFacebook.request("me");
Bundle parameters = new Bundle();
parameters.putString("access_token", access_token);
response = mFacebook.request("me/friends", parameters, "POST");
Log.d("Tests", "got response: " + response);
if (response == null || response.equals("") ||
response.equals("false")) {
Log.v("Error", "Blank response");
}
} else {
// no logged in, so relogin
Log.d(TAG, "sessionNOTValid, relogin");
mFacebook.authorize(this, PERMS, new LoginDialogListener());
}
} catch(Exception e) {
e.printStackTrace();
}
}
When i look at the response in the log it reads:
"got responce: {"error":{"type":"OAuthException", "message":"(#200) Permissions error"}}"
I have looked through the graphAPI documentation and searched for similar questions but to no avail! I'm not sure if i need to request extra permissions for the app or if this is something your just not allowed to do! Any help/suggestions would be greatly appreciated.
You might need the following permissions:
user_checkins
friends_checkins
read_friendlists
manage_friendlists
publish_checkins
Check the related ones from the API docs. Before that, make sure that which line causes this permission error and try to fix it.
The solution is to implement a RequestListener when making the request to the Facebook graph API. I have the new getFriends() method (see below) which uses the AsyncGacebookRunner to request the data.
public void getFriends(CharSequence[] charFriendsNames,String[] sFriendsID, ProgressBar progbar) {
try{
//Pass arrays to store data
friends = charFriendsNames;
friendsID = sFriendsID;
pb = progbar;
Log.d(TAG, "Getting Friends!");
//Create Request with Friends Request Listener
mAsyncRunner.request("me/friends", new FriendsRequestListener());
} catch (Exception e) {
Log.d(TAG, "Exception: " + e.getMessage());
}
}
The AsyncFacebookRunner makes the the request using the custom FriendsRequestListener (see below) which implements the RequestListener class;
private class FriendsRequestListener implements RequestListener {
String friendData;
//Method runs when request is complete
public void onComplete(String response, Object state) {
Log.d(TAG, "FriendListRequestONComplete");
//Create a copy of the response so i can be read in the run() method.
friendData = response;
//Create method to run on UI thread
FBConnectActivity.this.runOnUiThread(new Runnable() {
public void run() {
try {
//Parse JSON Data
JSONObject json;
json = Util.parseJson(friendData);
//Get the JSONArry from our response JSONObject
JSONArray friendArray = json.getJSONArray("data");
//Loop through our JSONArray
int friendCount = 0;
String fId, fNm;
JSONObject friend;
for (int i = 0;i<friendArray.length();i++){
//Get a JSONObject from the JSONArray
friend = friendArray.getJSONObject(i);
//Extract the strings from the JSONObject
fId = friend.getString("id");
fNm = friend.getString("name");
//Set the values to our arrays
friendsID[friendCount] = fId;
friends[friendCount] = fNm;
friendCount ++;
Log.d("TEST", "Friend Added: " + fNm);
}
//Remove Progress Bar
pb.setVisibility(ProgressBar.GONE);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FacebookError e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
Feel free to use any of this code in your own projects, or ask any questions about it.
You can private static final String[] PERMISSIONS = new String[] {"publish_stream","status_update",xxxx};xxx is premissions