I am trying to implement method callback using relection but it is not calling the desired method.Here is my main activity
public class MainActivity extends AppCompatActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RetrofitCalls retrofitCalls = new RetrofitCalls();
retrofitCalls.requestAccesstoken();
retrofitCalls.requestDataFromServer(MainActivity.this,"onCountryListReceived");
}
public void onCountryListReceived(JsonObject jsonObject)
{
String temp = "hello";
}
}
and here is the requestDataServer method
public void requestDataFromServer(final Activity activity, final String callBackMethod){
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new HeaderInterceptor())
.build();
retrofit = new Retrofit.Builder()
.baseUrl(Constants.ROOT_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build();
Api api = retrofit.create(Api.class);
Call<JsonObject> call = api.getDataFromServer(Constants.COUNTRY_LIST);
call.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
if(response.errorBody() != null){
try {
String j1 = response.errorBody().string();
String temp = "hello";
} catch (IOException e) {
e.printStackTrace();
}
}else if(response.body() != null) {
JsonObject jsonObject = response.body();
JsonArray jsonArray = jsonObject.getAsJsonArray("Data");
String temp = "hello";
try {
String x = activity.getClass().toString();
Method method = activity.getClass().getDeclaredMethod(callBackMethod.trim(),Object.class);
method.invoke(activity,jsonObject);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
String temp = "hello";
}
});
}
why the onCountryListReceived is not invoked? It is giving NoSuchMethodException. What's the problem?
Instead of Object.class i passed JsonObject.class in getDeclaredMethod as it is the parameter of the method to be called.
getDeclaredMethod accepts two parameters 1.callback method name 2.parameters of that method.
Related
I have two activities, When I will move from activity A to B, B keeps restarting or "refreshing", when i go back from B to A, it also keeps restarting. The code is very big, here I am posting area where I think problem causes :
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
deviceStatus();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.start();
this is deviceStatus();
public void deviceStatus(){
try {
RequestQueue requestQueue = Volley.newRequestQueue(InActivate.this);
String URL = "http://gickuwait-dev.com/electionapi/api/DeviceStatus";
JSONObject jsonBody = new JSONObject();
jsonBody.put("device_PK", device_ID2);
final String requestBody = jsonBody.toString();
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if(response.equals("true")){
Intent intent = new Intent(InActivate.this, Vote.class);
startActivity(intent);
finish();
}else if(response.equals("false")) {
}
// Toast.makeText(getApplicationContext(), response.toString(), Toast.LENGTH_SHORT).show();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("VOLLEY", error.toString());
}
}) {
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
#Override
public byte[] getBody() throws AuthFailureError {
try {
return requestBody == null ? null : requestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
return null;
}
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String responseString;
String json = null;
try {
json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
responseString = String.valueOf(json).trim();
ArrayList<DeviceStatusResponse> list = new ArrayList<DeviceStatusResponse>();
Type listType = new TypeToken<List<DeviceStatusResponse>>() {}.getType();
list = new Gson().fromJson(responseString, listType);
device_Status = list.get(0).getIsActive().toString();
// Toast.makeText(getApplicationContext(), ""+device_Status+" null ", Toast.LENGTH_LONG).show();
return Response.success(device_Status, HttpHeaderParser.parseCacheHeaders(response));
}
};
requestQueue.add(stringRequest);
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
in Activity B, i have the same code to check the device status from the database, any help would be appreciated
You can use Handle to check the repeated task.
private Handler delayHandler = new Handler();
private Runnable runnable = new Runnable() {
#Override
public void run() {
deviceStatus();
driverDelayHandler.postDelayed(runnable, 1000);
}
};
Don't forgot to cancel on onStop method.
delayHandler.removeCallbacks(runnable);
I'm new to android development but I'm stuck on why I can make calls to my API, but it doesn't populate my class in time for the recycler view to populate. I get IndexOutOfBoundsException because the mData.getDataFeeds() returns null. If I debug this application and walk through it slowly, it works.
ListFeedAdapter listFeedAdapter = new ListFeedAdapter(mData.getDataFeeds());
I have an Activity that gets a Fragment.
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_list, container, false);
RecyclerView recyclerView = view.findViewById(R.id.listRecyclerView);
try {
login();
getFeed();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
ListFeedAdapter listFeedAdapter = new ListFeedAdapter(mData.getDataFeeds());
recyclerView.setAdapter(listFeedAdapter);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
return view;
}
Then I call login()
private void login() throws IOException {
String user = "user";
String password = "pass";
String loginUrl = getString(R.string.jsonLogin);
OkHttpClient client = new OkHttpClient.Builder()
.build();
JSONObject credentials = new JSONObject();
JSONObject session = new JSONObject();
try {
credentials.put("email", user);
credentials.put("password", password);
session.put("session", credentials);
} catch (JSONException e) {
e.printStackTrace();
}
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, session.toString());
Request request = new Request.Builder()
.url(loginUrl)
.post(body)
.addHeader("Content-Type", mediaType.toString())
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
String jsonData = response.body().string();
String jsonHead = response.headers("Set-Cookie").toString();
if(response.isSuccessful()) {
for (String setCookie : response.headers("Set-Cookie")) {
cookies.add(Cookie.parse(response.request().url(), setCookie));
}
}
}
});
The getFeed()
private void getFeed() throws IOException, JSONException {
String loginUrl = "http://testurlhere";
OkHttpClient client = new OkHttpClient.Builder()
.build();
MediaType mediaType = MediaType.parse("application/json");
Request request = new Request.Builder()
.url(loginUrl)
.get()
.addHeader("Content-Type", mediaType.toString())
.addHeader("_session", cookies.get(0).toString())
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
try {
String jsonData = response.body().string();
String jsonHead = response.headers("Set-Cookie").toString();
Log.v(TAG, jsonData);
if (response.isSuccessful()) {
mData = parseDataFeed(jsonData);
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
updateDisplay();
}
});
}
}
catch (IOException e) {
Log.e(TAG, "Exception caught: ", e);
}
catch (JSONException e) {
Log.e(TAG, "Exception caught: ", e);
}
}
});
}
okhttp is an asynchronous operation, and you should use mData after onResponse ()
call.enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
try {
String jsonData = response.body().string();
String jsonHead = response.headers("Set-Cookie").toString();
Log.v(TAG, jsonData);
if (response.isSuccessful()) {
mData = parseDataFeed(jsonData);
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
ListFeedAdapter adapter = new ListFeedAdapter(mData.getDataFeeds());
rexyxlerView.setAdapter(adapter);
updateDisplay();
}
});
}
}
catch (IOException e) {
Log.e(TAG, "Exception caught: ", e);
}
catch (JSONException e) {
Log.e(TAG, "Exception caught: ", e);
}
}
});
This question already has answers here:
How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?
(17 answers)
Closed 5 years ago.
How to catch moment when AsyncTask is finished?
I have ProfileUpdate class which extends AsyncTask, and from another activity I calling this method and after I need update my data. How to know that asynctask finished? My asynctask method in another class and not in activity class!!!
this is my onRefresh method in the activity:
#Override
public void onRefresh() {
if (!AlertView.isInternetAvailable(getContext())) {
swipeLayout.setRefreshing(false);
Toast.makeText(getContext(), Messages.CONNECTION_ERROR + ": " + Messages.NO_INTERNET, Toast.LENGTH_SHORT).show();
} else {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
new UpdateProfile(getActivity(), swipeLayout, sharedPreferences.getString(Constants.TOKEN, ""), user.getIin()).execute(Urls.GET_USER);
}
});
profileDefaults();
}
}
and here my AsyncTask method:
public class UpdateProfile extends AsyncTask <String, Void, String> {
private Activity activity;
private SwipeRefreshLayout swipeRefreshLayout;
private String token;
private String userIin;
private SharedPreferences sharedPreferences;
public UpdateProfile(Activity activity, SwipeRefreshLayout swipeRefreshLayout, String token, String userIin) {
this.activity = activity;
this.swipeRefreshLayout = swipeRefreshLayout;
this.token = token;
this.userIin = userIin;
sharedPreferences = this.activity.getSharedPreferences(Constants.PROJECT, Context.MODE_PRIVATE);
}
#Override
protected String doInBackground(String... params) {
URL url = null;
try {
url = new URL(params[0]);
try {
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody body = new FormBody.Builder()
.add("iin", userIin)
.build();
Request request = new Request.Builder()
.url(url)
.addHeader(Constants.AUTH_TOKEN, token)
.post(body)
.build();
Response responses = null;
try {
responses = okHttpClient.newCall(request).execute();
} catch (Exception e) {
AlertView.showAlertView(activity, Messages.CONNECTION_ERROR, Messages.NO_INTERNET, Messages.OK);
}
assert responses != null;
return responses.body().string();
} catch (Exception e) {
AlertView.showAlertView(activity, Messages.CONNECTION_ERROR, Messages.NO_INTERNET, Messages.OK);
}
} catch (Exception e) {
AlertView.showAlertView(activity, Messages.CONNECTION_ERROR, Messages.NO_INTERNET, Messages.OK);
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
JSONObject jsonObject = new JSONObject(s);
int code = Integer.valueOf(jsonObject.getString(Constants.CODE));
if (code == Codes.OK) {
Toast.makeText(activity, "Данные обновлены", Toast.LENGTH_SHORT).show();
String userHeader = jsonObject.getString("user");
JSONObject userInfo = new JSONObject(userHeader);
String mobilePhone = userInfo.getString(SingletonConstants.MOBILE_PHONE);
Boolean isActive = userInfo.getBoolean(SingletonConstants.IS_ACTIVE);
Boolean signedAgreement = userInfo.getBoolean(SingletonConstants.SIGNED_AGREEMENT);
Boolean esfEntered = userInfo.getBoolean(SingletonConstants.ESF_ENTERED);
String address = userInfo.getString(SingletonConstants.ADDRESS);
String iin = userInfo.getString(SingletonConstants.IIN);
String certExpDate = userInfo.getString(SingletonConstants.CERT_EXP_DATE);
String firstName = userInfo.getString(SingletonConstants.FIRST_NAME);
String middleName = userInfo.getString(SingletonConstants.MIDDLE_NAME);
String workPhone = userInfo.getString(SingletonConstants.WORK_PHONE);
String secondName = userInfo.getString(SingletonConstants.SECOND_NAME);
String avatarUrl = userInfo.getString(SingletonConstants.AVATAR_URL);;
String secondEmail = userInfo.getString(SingletonConstants.SECOND_EMAIL);
String email = userInfo.getString(SingletonConstants.EMAIL);
User newUser = new User(mobilePhone, isActive, signedAgreement, esfEntered, address, iin, certExpDate, firstName, middleName, workPhone, secondName, avatarUrl, secondEmail, email);
Gson gson = new Gson ();
String userGson = gson.toJson (newUser);
sharedPreferences.edit().putString(SingletonConstants.USER, userGson).apply();
swipeRefreshLayout.setRefreshing(false);
} else {
AlertView.showAlertView(activity, Messages.ERROR, jsonObject.getString(Constants.MESSAGE), Messages.OK);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
How I can call profileDefaults()? It's into my activity. And I need to call it after onPostExecute!
A cleaner way to do it is to use interfaces as listeners.
Create this interface:
public interface OnAsyncFinished{
void onAsyncFinished(Object o);
}
Add the interface as a parameter in your AsyncTaskClass constructor:
private OnAsyncFinished onAsyncFinished;
public UpdateProfile(..., OnAsyncFinished onAsyncFinished) {
...
this.onAsyncFinished = onAsyncFinished;
}
...
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
onAsyncFinished.onAsyncFinished(s); //This will notifiy the method on main activity, and you can now resume the work there
...
}
Implement the interface in your main activity:
public MainActivity extends Activity implements OnAsyncFinished {
#Override
public void onAsyncFinished(Object o) {
//This will get called after onPostExecute, do what u want with the object you got from onPostExecute, json or string in ur example
profileDefaults(); //call ur function
}
}
EDIT:
When creating the async task in your main activity pass this in the constructor likeso:
#Override
public void run() {
new UpdateProfile(..., this).execute(Urls.GET_USER);
}
I have push Notification and I want to update realm objects when the phone gets a notification but when I try launch this:
RealmModelActiveUser actUser= realm.where(RealmModelActiveUser.class).equalTo("id",1).findFirst();
int myid= actUser.getUser().getUser_id();
new ServerBackgroundDownloadConversations(getApplicationContext()) {
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (!result.equals("Error")) {
Log.i("Conversation", "UPDATED");
}
}
}.execute(myid);
The program jumps into the constructor ServerBackgroundDownloadConversations(getApplicationContext()) but doesn't call doInBackground and I don't know why.
My AsyncTask:
public class ServerBackgroundCreateConversation extends AsyncTask<RealmModelConversations,Void,String> {
Context context;
Handler handler;
String out= "";
#SuppressLint("HandlerLeak")
public ServerBackgroundCreateConversation(Context context) {
this.context = context;
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
Bundle bundle= msg.getData();
if (bundle!=null){
out = (String) bundle.get("response");
} else {
out= "Error";
}
}
};
}
#Override
protected String doInBackground(RealmModelConversations... params) {
RealmModelConversations newConv = params[0];
UploadImageApacheHttp uploadTask = new UploadImageApacheHttp();
uploadTask.doFileUpload(newConv.getWork(newConv.getIntWork()), newConv, handler);
while (out.equals("")){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return out;
}
#Override
protected void onPreExecute() {
}
#Override
protected void onPostExecute(String result) {
if (!result.equals("]") || !result.equals("")){
/// prihlási nového user aj do active (login/register)
CreateNewConversation(result);
} else {
result="Error";
}
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
private void CreateNewConversation(String result){
Realm realm= Realm.getDefaultInstance();
try {
Gson gson = new Gson();
Type typeConv = new TypeToken<JsonSablonaConversations>() {
}.getType();
JSONObject pom;
JSONArray parentArray = new JSONArray(result);
JSONObject finalObject = parentArray.getJSONObject(0);
JsonSablonaConversations conversation = gson.fromJson(finalObject.toString(), typeConv);
final RealmModelConversations NewUserConv = new RealmModelConversations();
NewUserConv.setId_dialog(conversation.getId_dialog());
NewUserConv.setDate(conversation.getDate());
NewUserConv.setKey(conversation.getKey());
NewUserConv.setId_user(conversation.getId_user());
NewUserConv.setId_user2(conversation.getId_user2());
NewUserConv.setMeno(conversation.getMeno());
NewUserConv.setMeno2(conversation.getMeno2());
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
try {
realm.copyToRealmOrUpdate(NewUserConv);
} catch (Exception e) {
int pom=4;
}
RealmResults<RealmModelConversations> ru= realm.where(RealmModelConversations.class).findAll();
}
});
}
catch (Exception e) {
int ppp=4;
ppp++;
}finally {
realm.close();
}
}
}
I try calling this ↑ from an external thread which is called from a Service, but my AsyncTask has handler and handler needs to be in runOnUIthread and in Thread. I can't get Activity because the thread is called from a Service which doesn't have access to Activity.
I solved my problem with this code
public String postData(int myUserId) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://www.gallopshop.eu/OFY/getConversations.php");
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("id", Integer.toString(myUserId)));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
String responseStr = EntityUtils.toString(response.getEntity());
return responseStr;
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
} catch (IOException e) {
// TODO Auto-generated catch block
}
return null;
}
I will try to put this method & after this method into simply thread, But maybe it's not needed because it's in a service.
Question - Do I put this into Thread or do you think it'll affect the performance of the app?
I'm trying to use Volley as a DBA layer to call a webservice that hadles JSON objects. Because this layer is below the activity and another service layer, it doesn't seem to be working properly. I'll try to explain my setup:
MainActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ProductService productService = new ProductService();
productService.getProduct();
}
ProductService.java:
public void getProduct() {
JsonObjectRequest req = new JsonObjectRequest("http://echo.jsontest.com/name/Milk/price/1.23/", null, createMyReqSuccessListener(), createMyReqErrorListener());
ApplicationController.getInstance().addToRequestQueue(req);
}
private Response.Listener<JSONObject> createMyReqSuccessListener() {
return new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.v("response", response.toString());
}
};
}
private Response.ErrorListener createMyReqErrorListener() {
return new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
return;
}
};
}
I hope that is clear enough.
In the end, I would like to use the ProductService::getProduct() from an activity and the the actual JSON response from the webservice in a variable which I can later use.
However, at the moment, the line
Log.v("response", response.toString());
doesn't even execute. What am I doing wrong?
What I would try is this:
Declare getProduct as
public void getProduct(Response.Listener<JSONObject> listener,
Response.ErrorListener errlsn) {
JsonObjectRequest req = new JsonObjectRequest("http://echo.jsontest.com/name/Milk/price/1.23/",null, listener, errlsn);
ApplicationController.getInstance().addToRequestQueue(req);
}
And than call in your activity like this:
productService.getProduct(
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
variableFromActivity = response;
//Or call a function from the activity, or whatever...
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//Show error or whatever...
}
});
Create an abstract class AppActivity
import androidx.appcompat.app.AppCompatActivity;
public abstract class AppActivity extends AppCompatActivity
{
abstract void callback(String data);
}
Extend all your Activities using AppActivity
public class MainActivity extends AppActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String url = "Your URL";
JSONObject jsonBody = new JSONObject();
try {
jsonBody.put("Title", "Android Volley Demo");
jsonBody.put("Author", "BNK");
}
catch (JSONException e) {
System.out.println(e);
}
final String requestBody = jsonBody.toString();
Messenger messenger = new Messenger(MainActivity.this);
messenger.sendMessage(this, url, requestBody);
}
public void callback(String data)
{
System.out.println(data);
}
}
Create Messenger class as below:
public class Messenger
{
private AppActivity myActivity;
public Messenger(AppActivity activity)
{
myActivity = activity;
}
public void sendMessage(Context context, String url, final String requestBody)
{
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(context);
// Request a string response from the provided URL.
StringRequest stringRequest =
new StringRequest(
Request.Method.POST,
url,
null,
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println(error);
}
}
) {
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
#Override
public byte[] getBody() throws AuthFailureError {
try {
return requestBody == null ? null : requestBody.getBytes("utf-8");
}
catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
return null;
}
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response)
{
myActivity.callback(new String(response.data));
String responseString = "";
if (response != null) {
responseString = String.valueOf(response.statusCode);
// can get more details such as response.headers
}
return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
}
};
queue.add(stringRequest);
}
}
Hope it helps.