I'm making a app GuessTheCelebrity. So the problem is I need celebrity names and their imageUrls outside the response method so i use callback method but its not working. First i fetch data in CelebDataService class and then in Main activity i used Matcher and Pattern to get the desired response. I use Singleton Class for adding requests to requestQueue.
Here's my code:
Volley Request Class
public class CelebDataService {
Context context;
String response;
String url = "https://www.imdb.com/list/ls052283250/";
public CelebDataService(Context context) {
this.context = context;
}
public interface CallBack {
void onResponse(String response);
void onError(String error);
}
public interface MatchListAsyncResponse {
void processFinish(List<String> list);
}
public void getResponse(CallBack callBack)
{
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
System.out.println(response);
callBack.onResponse(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
callBack.onError(error.getMessage());
}
});
MySingleton.getInstance(context).addToRequestQueue(stringRequest);
}
}
Main Activity Class
public class MainActivity extends AppCompatActivity {
ArrayList<String> urls = new ArrayList<>();
ArrayList<String> names = new ArrayList<>();
int cs = 0;
TextView textView;
ImageView imageView;
ImageRequest imageRequest;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main)
textView = findViewById(R.id.textView);
imageView = findViewById(R.id.imageView);
CelebDataService celebDataService = new CelebDataService(MainActivity.this);
celebDataService.getResponse(new CelebDataService.CallBack() {
#Override
public void onResponse(String response) {
Log.i("hello", "onResponse: " + response);
String[] result = response.split("<div id=\"sidebar\">");
Pattern p = Pattern.compile("src=\"(.*?)\"");
Matcher m = p.matcher(result[0]);
while (m.find())
{
urls.add(m.group(1));
}
p = Pattern.compile("alt=\"(.*?)\"");
m = p.matcher(result[0]);
while (m.find())
{
names.add(m.group(1));
}
}
#Override
public void onError(String error) {
textView.setText(error);
}
});
Random random = new Random();
cs = random.nextInt(urls.size());
imageRequest = new ImageRequest(urls.get(cs), new Response.Listener<Bitmap>() {
#Override
public void onResponse(Bitmap response) {
imageView.setImageBitmap(response);
requestQueue.stop();
}
}, 0, 0, ImageView.ScaleType.CENTER_CROP,null, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
textView.setText("Error");
error.printStackTrace();
}
});
MySingleton.getInstance(context).addToRequestQueue(imageRequest);
}
}
The app got crash on start because urls arraylist is empty.
Related
my code is like this, i don't know why it's getting an empty array even though i added the elements to the array during request.
public class MainActivity extends AppCompatActivity {
private List<Question> questionList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
questionList = new QuestionBank().getQuestions();
Log.d("Main", "processFinished: " + questionList);
}
// the request
public class QuestionBank {
ArrayList<Question> questionArrayList = new ArrayList<>();
private String url = "https://raw.githubusercontent.com/curiousily/simple-quiz/master/script/statements-data.json";
public List<Question> getQuestions() {
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, url, null,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
for (int i = 0; i < response.length(); i++) {
try {
Question question = new Question();
question.setAnswer(response.getJSONArray(i).get(0).toString());
question.setAnswerTrue(response.getJSONArray(i).getBoolean(1));
questionArrayList.add(question);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
AppController.getInstance().addToRequestQueue(jsonArrayRequest);
return questionArrayList;
}
}
// Log result
D/Main: processFinished: []
You can pass a callback as following ways
step 1:
Create an Intercafe
public interface TestCallBack {
void callBack(List<Question> response) ;
}
Step 2:
create anonymous objects
TestCallBack testCallBack=new TestCallBack() {
#Override
public void callBack(List<Question> response) {
// here you will get a response after success
}
};
and pass this reference to
questionList = new QuestionBank().getQuestions(testCallBack);
Log.d("Main", "processFinished: " + questionList);
Step 3:
call this method from after the response from the server
public List<Question> getQuestions(TestCallBack testCallBack) {
public void onResponse(JSONArray response) {
testCallBack.callBack(questionArrayList); // pass your array list here
}
}
It is empty because you are populating it asynchronously. you should add a callback as a parameter, call it in onResponse.
I'm writing a class with requests to rest API (Yandex disk). I use volley, but I do have some problems with getting a response from it. You can check the rest API here.
I use volley and I can get a response in the debugger, but not in my Activity.
Here is my Requests class
class Requests {
private String response_of_server, token;
private String url = "https://cloud-api.yandex.net/v1/disk";
private Context context;
Requests (String token, Context context) {
this.token = token;
this.context = context;
}
private void set_response_of_server(String response) {
this.response_of_server = response;
}
String get_response() {
return response_of_server;
}
void get_metadata_of_user() {
try {
/*Request*/
RequestQueue queue = Volley.newRequestQueue(this.context);
Response.ErrorListener error_listener = new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
};
Response.Listener<String> response_listener = new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
set_response_of_server(response);
}
};
StringRequest getRequest = new StringRequest(Request.Method.GET, url+"?fields=user", response_listener, error_listener) {
#Override
public Map<String, String> getHeaders() {
Map<String, String> params = new HashMap<>();
params.put("Host", "cloud-api.yandex.net");
params.put("Authorization", token);
return params;
}
};
queue.add(getRequest);
/*Request end*/
} catch (Exception e) {
e.printStackTrace();
}
}
}
And the MainActivity where I want my response.
public class MainActivity extends AppCompatActivity {
private final String ID_OF_APP = "Your token of app";
private final String URL_FOR_CODE_QUERY = "https://oauth.yandex.com/authorize?response_type=token&client_id=" + ID_OF_APP;
private String SAVED_TOKEN = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_get_code = findViewById(R.id.btn_get_code); // send to get code page (yandex)
btn_get_code.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(URL_FOR_CODE_QUERY));
startActivity(i);
}
});
Button btn_sign_in = findViewById(R.id.btn_sign_in);
btn_sign_in.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText code_field = findViewById(R.id.code_field);
String token = code_field.getText().toString();
save_token(token);
try {
if(check_token()) {
//Toast.makeText(MainActivity.this, "You are successfully signed in", Toast.LENGTH_SHORT).show();
// TODO change activity
}
else {}
} catch (InterruptedException e) {
e.printStackTrace();
}
//Toast.makeText(MainActivity.this, "Something went wrong. Please, check your connection and try again later", Toast.LENGTH_SHORT).show();
}
});
}
private void save_token(String token) {
SharedPreferences sPref = getPreferences(MODE_PRIVATE);
SharedPreferences.Editor ed = sPref.edit();
ed.putString(SAVED_TOKEN, token);
ed.apply();
}
private String load_token() {
SharedPreferences sPref = getPreferences(MODE_PRIVATE);
return sPref.getString(SAVED_TOKEN, "");
}
private boolean check_token() throws InterruptedException {
String token = load_token();
String result;
Requests request = new Requests(token, this);
request.get_metadata_of_user();
result = request.get_response();
Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
return !(result.equals("-1"));
}
}
check_token() function at the moment should just make a toast with a response of the server. However, I cannot get the Toast or any response coming back from the server.
You have a Requests class which has the function to call the server API which is Asynchronous. Hence, you will not get the result immediately after calling the request.get_metadata_of_user(); in your check_token() function.
Hence I would like to suggest you modify your Request class like the following.
public class Requests {
private String response_of_server, token;
private String url = "https://cloud-api.yandex.net/v1/disk";
private Context context;
private HttpListener listener; // Add a listener to get the callback functionality
Requests (String token, Context context, HttpListener listener) {
this.token = token;
this.context = context;
this.listener = listener; // initialize the listener here
}
private void set_response_of_server(String response) {
this.response_of_server = response;
listener.onResponseReceived(response); // Send the response back to the calling class
}
String get_response() {
return response_of_server;
}
void get_metadata_of_user() {
try {
RequestQueue queue = Volley.newRequestQueue(this.context);
Response.ErrorListener error_listener = new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
};
Response.Listener<String> response_listener = new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
set_response_of_server(response);
}
};
StringRequest getRequest = new StringRequest(Request.Method.GET, url+"?fields=user", response_listener, error_listener) {
#Override
public Map<String, String> getHeaders() {
Map<String, String> params = new HashMap<>();
params.put("Host", "cloud-api.yandex.net");
params.put("Authorization", token);
return params;
}
};
queue.add(getRequest);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Now the HttpListener class might look like the following. Create HttpListener.java and add the following code to create this as an interface.
public interface HttpListener {
public void onResponseReceived();
}
Hence you need to implement this interface in your MainActivity like the following.
public class MainActivity extends AppCompatActivity implements HttpListener {
private final String ID_OF_APP = "Your token of app";
// I fixed this part too. Please change if that is not useful
private final String URL_FOR_CODE_QUERY = "https://oauth.yandex.com/authorize?response_type=" + SAVED_TOKEN + "&client_id=" + ID_OF_APP;
private String SAVED_TOKEN = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ... I omitted some code
Button btn_sign_in = findViewById(R.id.btn_sign_in);
btn_sign_in.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText code_field = findViewById(R.id.code_field);
String token = code_field.getText().toString();
save_token(token);
try {
// if(check_token()) {
// The check_token function call is Async. This will not return immediately. Hence you might consider removing this if part. Simply just call the function and listen to the callback function when the response is received
// }
check_token(); // Simply call the function here
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
private void save_token(String token) {
SharedPreferences sPref = getPreferences(MODE_PRIVATE);
SharedPreferences.Editor ed = sPref.edit();
ed.putString(SAVED_TOKEN, token);
ed.apply();
}
private String load_token() {
SharedPreferences sPref = getPreferences(MODE_PRIVATE);
return sPref.getString(SAVED_TOKEN, "");
}
// I changed the return type as this is not returning anything.
private void check_token() throws InterruptedException {
String token = load_token();
String result;
Requests request = new Requests(token, this);
request.get_metadata_of_user();
// You will not get the response immediately here. So omit these codes.
// result = request.get_response();
// Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
// return !(result.equals("-1"));
}
#Override
public void onResponseReceived(String response) {
// Here is your response. Now you can use your response
// and can perform the next action here.
}
}
Please note that, the code is not tested. Please modify as per your requirement. I hope that helps you to understand the problem.
I am making a volley String request from a separate class and return the result to main activity
public class FetchFlages {
Context context;
String
placeurl="https://maps.googleapis.com/maps/api/place/textsearch/json
query=";
String myapi = "&key=AIzaSyBuI5wpF733jBS8s7HzjybE1rYAp1hA5tA";
RequestQueue requestQueue;
String abc=null;
public FetchFlages(Context context) {
this.context = context;
requestQueue = Volley.newRequestQueue(context);
}
public String getPhotoReference(){
String url = placeurl +"China"+myapi;
StringRequest objectRequest = new StringRequest(Request.Method.GET, url,
new Listener<String>() {
#Override
public void onResponse(String response) {
abc = response;
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Volly Error",error.toString());
}
});
requestQueue.add(objectRequest);
return abc;
}
}
and in main Class
FetchFlages fetchFlages = new FetchFlages(this);
flag = fetchFlages.getPhotoReference();
String g = flag;
But i can't get any value from that...the value of abc always return null
and
When i run debugger then debugger not comes neither on Volley on Response Listener method and nor on Error Listener Method...Please help me..
This is because as soon as getPhotoReference() is called, its returning the value. The network call is still running. Create a listener and call the listener method on onRespose
Sample pseudo code:
CustomListener.java
public interface CustomListener{
void onVolleyResponse(String response);
}
FetchFlages.java
public class FetchFlages {
Context context;
String placeurl="https://maps.googleapis.com/maps/api/place/textsearch/jsonquery=";
String myapi = "&key=AIzaSyBuI5wpF733jBS8s7HzjybE1rYAp1hA5tA";
RequestQueue requestQueue;
CustomListener listener = null; //Your listener instance
public FetchFlages(Context context, CustomListener listener) {
this.context = context;
this.listener = listener;
requestQueue = Volley.newRequestQueue(context);
}
public void getPhotoReference(){
String url = placeurl +"China"+myapi;
StringRequest objectRequest = new StringRequest(Request.Method.GET, url,
new Listener<String>() {
#Override
public void onResponse(String response) {
listener.onVolleyResponse(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Volly Error",error.toString());
}
});
requestQueue.add(objectRequest);
}
}
Now in your main activity,
FetchFlages fetchFlages = new FetchFlages(this, new CustomListener() {
#Override
public void onVolleyResponse(String response) {
//response is your response
}
});
fetchFlages.getPhotoReference()
Use interface Method like:
public class FetchFlages {
Context context;
String placeurl = "https://maps.googleapis.com/maps/api/place/textsearch/json?query=";
String myapi = "&key=AIzaSyBuI5wpF733jBS8s7HzjybE1rYAp1hA5tA";
RequestQueue requestQueue;
IResult result;
public FetchFlages(Context context, IResult result) {
this.context = context;
requestQueue = Volley.newRequestQueue(context);
this.result = result;
}
public void getPhotoReference() {
String url = placeurl + "China" + myapi;
StringRequest objectRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
result.notifySuccess(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Volly Error", error.toString());
result.notifyError(error);
}
});
requestQueue.add(objectRequest);
}
public interface IResult {
public void notifySuccess(String response);
public void notifyError(VolleyError error);
}
and call it:
FetchFlages fetchFlages = new FetchFlages(this, new IResult() {
#Override
public void notifySuccess(String response) {
//response here
Log.e("responce",response);
}
#Override
public void notifyError(VolleyError error) {
//error here
}
});
fetchFlages.getPhotoReference()
I want to move GET method inside (if) that located inside onResponse of POST request without calling URL again because once the user post edittext php file will echo json result that will show up inside listview in activity so if call URL again in other method nothing will show up, how can I do that please?
public class supportActivity extends AppCompatActivity implements View.OnClickListener{
private EditText ticketsupport;
private Button button;
private List<supportContent> con = new ArrayList<supportContent>();
private ListView supportlist;
private supportAdapter adapter;
private String ticketinput;
private String url = "http://10.0.3.2/aalm/getticket.php";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_support);
ticketsupport = (EditText)findViewById(R.id.insertticketnumber);
supportlist = (ListView)findViewById(R.id.supportlistview);
adapter = new supportAdapter(this, con);
supportlist.setAdapter(adapter);
button = (Button)findViewById(R.id.buttonsupprt);
button.setOnClickListener(this);
}
private void inquiry() {
ticketinput = ticketsupport.getText().toString().trim();
StringRequest stringRequest1 = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if (response.trim().equals("responseticket")) {
showTicket();
} else {
Toast.makeText(supportActivity.this, "Check the number please", Toast.LENGTH_SHORT).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(supportActivity.this, "something wrong" , Toast.LENGTH_SHORT).show();
}
}) {
#Override
protected Map<String,String> getParams() throws AuthFailureError{
Map<String,String> map = new HashMap<String,String>();
map.put("ticknumber", ticketinput);
return map;
}
};
RequestQueue requestQueue1 = Volley.newRequestQueue(getApplicationContext());
requestQueue1.add(stringRequest1);
}
private void showTicket(){
RequestQueue requestQueue2 = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray("responseticket");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject ticket = jsonArray.getJSONObject(i);
supportContent support = new supportContent();
support.setTicketnumber(ticket.getString("ticketnumber"));
support.setSubject(ticket.getString("subject"));
support.setResponse(ticket.getString("response"));
con.add(support);
}
} catch (JSONException e) {
e.printStackTrace();
}
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("error", "Volley");
}
}
);
requestQueue2.add(jsonObjectRequest);
}
#Override
public void onDestroy(){
super.onDestroy();
}
#Override
public void onClick(View view){
inquiry();
}
}
I am trying to display a ProgressDialog while my app is getting data from a web service. I also would like to call a method in MapsActivity (main activity) when DataController is done adding objects from parsing web service.
In my code nothing happens (i.e. no ProgressDialog appears) and I'm stuck on how to let MapsActivity know that the objects have been created.
As you can see I've tried to make the ProgressDialog appear with
pd.show(context, "text", "text")
MapsActivity.java
public class MapsActivity extends FragmentActivity {
private DataController controller = new DataController(MapsActivity.this);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
setUpMapIfNeeded();
sharedPref = new SharedPreference(MapsActivity.this);
storedLikes = controller.readLike(sharedPref);
//This runs getLikedPos() in DataController
/Lots of code....
DataController.Java
public class DataController {
// Fields
public DataController(MapsActivity mapsActivity) {
this.context = mapsActivity;
}
public void getLikedPos() {
this.url = getUrl();
JsonObjectRequest jrequest = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
ProgressDialog pd = ProgressDialog.show(context, "In progress", "Loading");
int success = response.getInt("success");
if (success == 1) {
JSONArray ja = response.getJSONArray("spots");
for (int i=0; i < ja.length(); i++) {
JSONObject spot = ja.getJSONObject(i);
Location location = new Location("");
location.setLatitude(spot.getDouble(LIKE_LAT));
location.setLongitude(spot.getDouble(LIKE_LONG));
int id = spot.getInt(LIKE_ID);
String time = spot.getString(LIKE_TIMESTAMP);
Calendar parsedTime = convertDate(time);
likeArr.add(new Like(location, id, parsedTime));
}
System.out.println("Size of LikeArr ArrayList after parsing: " + likeArr.size());
pd.dismiss();
//context.updateMap(); ??
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});