I have a Class, that get me a String of a Data Base.
I call the Class in my Activity, and then I use that string.
The stirng is returned because I get it by Log.d, but the String variable of my Activity donĀ“t get it because the program continues without wait the Class ends.
(SORRY MY BAD ENGLISH)
Code:
Activity:
Cargar_Imagen ci = new Cargar_Imagen();
String s = ci.Cargar_Imagen(params...);
Class:
public class Cargar_Imagen {
private Map<String, String> params;
String sBitmap = "";
public String Cargar_Imagen(final String email, final String id, final String f1, final Context context, final String type, final View v){
StringRequest stringRequest = new StringRequest(Request.Method.POST, "https://feticher.webcindario.com/cargar_imagen.php",
new Response.Listener<String>() {
#Override
public void onResponse(String s) {
Log.d("Imagen", "Se cargo la foto");
try {
JSONObject jsonRespose = new JSONObject(s);
sBitmap =jsonRespose.getString("imagen");
Log.d("Imagen", "STRING: " + sBitmap);
Download_Image download_image = new Download_Image();
download_image.Download_Image(f1, type,context, v, sBitmap);
} catch (JSONException e) {
e.printStackTrace();
Log.d("Imagen", "ERROR: " + e.getMessage());
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("Imagen", "No se pudo cargar la foto");
}
}) {
#Override
protected Map<String, String> getParams(){
Log.d("Imagen", "Ejecutando MAP Cargar Imagen");
Log.d("Imagen", "DATOS: " + id + " " + email + " " + f1);
Map<String, String> params = new Hashtable<String, String>();
params.put("id", id);
params.put("email", email);
params.put("foto", f1);
Log.d("Imagen", "PASO POR AKI");
return params;
}};
RequestQueue queue = Volley.newRequestQueue(context);
queue.add(stringRequest);
return sBitmap;
}
}
sBitmap is assigned after the method gets executed since it's asynchronous. One approach is to declare an interface with a method [for example onFinish(String) ] and pass it as a parameter of Cargar_Imagen, after that you can call it inside your onResponse.Listener method.
// The interface
interface CallBack {
public void onFinish(String response);
}
// The activity (which calls Cargar_Imagen) should implement CallBack
public class MainActivity extends Activity implements CallBack
public void onFinish(String response) {
// here the method did finish, do something with the string
}
// somewhere you call to Cargar_Imagen
String s = ci.Cargar_Imagen(params..., this);
}
// the method signature should receive a CallBack
public String Cargar_Imagen(final String email, final String id, final String f1, final Context context, final String type, final View v, final CallBack callback){
/* code .... */
// ...
// in your onResponse
callback.onFinish(sBitmap);
You have written retrun sBitmap;, try with the correct return and let us know if it solved the problem.
Related
I am developing an android app (java), I am using Firebase, for each registered user I have a token of the device, how can I send a notification to a specific user using his token ?
For sending a notification to users the only thing required is that user's token. You can send notification using FCM.
Here, I'm sharing my FCM class which can be used for this purpose. It is using Okhttp3 requests, so make sure you add its dependency.
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.2'
After adding this dependency, all you have to do is to use this FCM class.
FCMMessages.java
public class FCMMessages {
private Context context;
public void sendMessageSingle(Context context, final String recipient, final String title, final String body, final Map<String, String> dataMap)
{
this.context = context;
Map<String, Object> notificationMap = new HashMap<>();
notificationMap.put("body", body);
notificationMap.put("title", title);
Map<String, Object> rootMap = new HashMap<>();
rootMap.put("notification", notificationMap);
rootMap.put("to", recipient);
if (dataMap != null)
rootMap.put("data", dataMap);
new SendFCM().setFcm(rootMap).execute();
}
public void sendMessageMulti(Context context, final JSONArray recipients, final String title, final String body, final Map<String, String> dataMap) {
this.context = context;
Map<String, Object> notificationMap = new HashMap<>();
notificationMap.put("body", body);
notificationMap.put("title", title);
Map<String, Object> rootMap = new HashMap<>();
rootMap.put("notification", notificationMap);
rootMap.put("registration_ids", recipients);
if (dataMap != null)
rootMap.put("data", dataMap);
new SendFCM().setFcm(rootMap).execute();
}
#SuppressLint("StaticFieldLeak")
class SendFCM extends AsyncTask<String, String, String> {
private String FCM_MESSAGE_URL = "https://fcm.googleapis.com/fcm/send";
private Map<String, Object> fcm;
SendFCM setFcm(Map<String, Object> fcm) {
this.fcm = fcm;
return this;
}
#Override
protected String doInBackground(String... strings) {
try {
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(JSON, new JSONObject(fcm).toString());
Request request = new Request.Builder()
.url(FCM_MESSAGE_URL)
.post(body)
.addHeader("Authorization","key=" + StaticConfig.myMessagingAuth)
.build();
Response response = new OkHttpClient().newCall(request).execute();
return response.body().string();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(String result) {
try {
JSONObject resultJson = new JSONObject(result);
int success, failure;
success = resultJson.getInt("success");
failure = resultJson.getInt("failure");
//Toast.makeText(context, "Sent: " + success + "/" + (success + failure), Toast.LENGTH_LONG).show();
} catch (JSONException e) {
e.printStackTrace();
// Toast.makeText(context, "Message Failed, Unknown error occurred.", Toast.LENGTH_LONG).show();
}
}
}
}
Make sure you get the messagingAuth from your firebase project settings. To get the messagingAuth token, follow these steps:
Open Firebase Project > Project Settings > Cloud Messaging > Server key
Copy the value of server key and paste it as messagingAuth in your android project.
To send a notification to single user token use sendMessageSingle method. It would be like
String user_token = "wiubd92uhe91dik-q";
String notification_title = "This is notification title";
String notification_des = "This is notification description";
new FCMMessages().sendMessageSingle(MainActivity.this, user_token, notification_title, notification_des, null);
To send a notification to multiple user tokens use sendMessageMulti method. It would be like
ArrayList<String> user_tokens = new ArrayList<>();
user_tokens.add(token_1);
user_tokens.add(token_2);
user_tokens.add(token_3);
String notification_title = "This is notification title";
String notification_des = "This is notification description";
new FCMMessages().sendMessageMulti(MainActivity.this, new JSONArray(user_tokens), notification_title, notification_des, null);
Use this YouTube link here EDMT Dev has implemented the following in his Eat it new series. And kindly mark this as the correct answer if this helps you.
Add the below dependency
`implementation 'io.reactivex.rxjava2:rxandroid:2.1.1`'
Now Create these classes :
Token Model This Model is used to retrieve token data( Token , Phone ). I have also a variable for the phone because I made this class according to my datastructure . Kindly modify the code according to your need
public class TokenModel {
private String phone,token;
public TokenModel() {
}
public TokenModel(String phone, String token) {
this.phone = phone;
this.token = token;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}}
FCM Send Data Model
public class FCMSendData {
private String to;
private Map<String,String> data;
public FCMSendData(String to, Map<String, String> data) {
this.to = to;
this.data = data;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public Map<String, String> getData() {
return data;
}
public void setData(Map<String, String> data) {
this.data = data;
}}
Create FCM Result Model
class FCMResult {
private String message_id;
public FCMResult() {
}
public String getMessage_id() {
return message_id;
}
public void setMessage_id(String message_id) {
this.message_id = message_id;
}}
Create RetrofitFCMClient
public class RetrofitFCMClient {
private static Retrofit instance;
public static Retrofit getInstance()
{
if(instance==null)
{
instance = new Retrofit.Builder().baseUrl("https://fcm.googleapis.com/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
return instance;
}
return instance;
}}
Now we need to implement an interface
//Authorization key is server key of Cloud Messaging
public interface IFCMService {
#Headers({
"Content-Type:application/json",
"Authorization:key=**YOUR_AUTHORIZATION KEY HERE**"
})
#POST("fcm/send")
Observable<FCMResponse> sendNotification(#Body FCMSendData body);}
Now We are ready to use the firebase messaging just need to put data and use our retrofit to push it
TokenModel tokenModel = dataSnapshot.getValue(TokenModel.class);
//("FCM",tokenModel.getToken());
Map<String, String> notiData = new
HashMap<>();
notiData.put(Common.NOTI_TITLE, "YOUR NOTIFICATION TITLE");
notiData.put(Common.NOTI_CONTENT,"YOUR_NOTFICATION CONTENT );
FCMSendData sendData = new FCMSendData(tokenModel.getToken(),
notiData);
compositeDisposable
.add(ifcmService.sendNotification(sendData)
.subscribeOn(Schedulers.io()).
observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<FCMResponse>() {
#Override
public void accept(FCMResponse
fcmResponse)
throws Exception {
if (fcmResponse.getSuccess()
== 1) {
Toast.makeText(getContext(),
"Success", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getContext(), "Failed
to Notify", Toast.LENGTH_LONG).show();
}
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable
throwable) throws Exception {
Toast.makeText(getContext(),
throwable.getMessage(), Toast.LENGTH_LONG).show();
}
}));
Use this YouTube link here EDMT Dev has implemented the following in his Eat it new series
I'm trying to implement the premade LoginActivity in Android Studio to no avail. I'm stuck in the file LoginDataSource.java. Below is the class in it's entirety.
public class LoginDataSource {
public Result<LoggedInUser> login(final String username, final String password) {
try {
String url = "http://192.168.1.10:1234/my/api";
// Instantiate the RequestQueue.
RequestQueue requestQueue;
// Instantiate the cache
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap
// Set up the network to use HttpURLConnection as the HTTP client.
Network network = new BasicNetwork(new HurlStack());
// Instantiate the RequestQueue with the cache and network.
requestQueue = new RequestQueue(cache, network);
requestQueue.start();
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.i("Response:", response);
// Display the first 500 characters of the response string.
// textView.setText("Response is: " + response.substring(0, 500));
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// textView.setText("That didn't work!");
Log.e("Error:", error.toString());
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("user", username);
params.put("pass", password);
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/x-www-form-urlencoded");
return params;
}
};
requestQueue.add(stringRequest);
LoggedInUser fakeUser =
new LoggedInUser(
java.util.UUID.randomUUID().toString(),
"John Doe");
return new Result.Success<>(fakeUser);
} catch (Exception e) {
return new Result.Error(new IOException("Error logging in", e));
}
}
public void logout() {
// TODO: revoke authentication
}
}
getCacheDir() gets highlighted with red and the reason states Cannot resolve method 'getCacheDir' in 'LoginDataSource'. I tried changing the parameter to context.getCacheDir() but there's no context available in the file and I can't import one from anywhere.
What am I doing wrong here? This is driving me insane.
getCacheDir() has to be invoked on a Context object, so you need to pass in a Context into to login. So change login to login(final String username, final String password, final Context context)
and then invoke context.getCacheDir()
i have an entry level question:
if there is external java class let's say 'Class1' inside this class there is a method called 'method1' inside this method there is Override method 'onResponse' inside this method two variables is being set 'a' and 'b'.
in the android mainActivity i called the method from the class like this:
Class1.method1();
after calling the method how i can retrieve these variables to be used in mainActivity...
thanks..
public abstract class Class1 extends Context {
final Context mcontext;
public static void method1(final Context mcontext, final String x){
StringRequest stringRequest = new StringRequest(Request.Method.POST, constants.URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject parentObject = new JSONObject(response);
JSONObject userDetails = parentObject.getJSONObject("data");
//read attributes
String a = userDetails.getString("a");
String b = userDetails.getString("b");
} catch (JSONException e) {
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(mcontext, error.getMessage() ,Toast.LENGTH_LONG).show();
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("x", x);
return params;
}
};
requestHandler.getInstance(mcontext).addToRequestQueue(stringRequest);
}
Why not create a wrapper class for a and b
public class Details {
public string a;
public string b;
}
and then read/return it in the method1
public abstract class Class1 extends Context {
final Context mcontext;
public static Details method1(final Context mcontext, final String x){
Details data = new Details;
StringRequest stringRequest = new StringRequest(Request.Method.POST, constants.URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject parentObject = new JSONObject(response);
JSONObject userDetails = parentObject.getJSONObject("data");
//read attributes
data.a = userDetails.getString("a");
data.b = userDetails.getString("b");
} catch (JSONException e) {
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(mcontext, error.getMessage() ,Toast.LENGTH_LONG).show();
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("x", x);
return params;
}
};
requestHandler.getInstance(mcontext).addToRequestQueue(stringRequest);
return data;
}
if you want to return more than one value you should use Android ways called Intent
but if you insist
you can use Array or ArrayList return type for the inner inner method
class Class1{
public static ArrayList<Object> method1(){
return onResponse();
}
public static ArrayList<Object> onResponse(){
return arrayList<Object>;
}
}
but still i see no reason to not use Intent
I use "token", instance of the ValueContainer class declared as final, in order to save data received from a JSON request. Inside the anonymous function, Response.Listener(), I set the value of token and it works.
Log.d("myTag", "token value1:" + token.getValue());
This line displays a correct value (non null). However, when I check the value of token.getValue() again (this time outside the anonymous function)
Log.d("myTag", "token value2:" + token.getValue());
I get token.getValue() = null. I don't understand why token's value seems to be reset to null. Am I missing something?
The full code:
public class MainActivity extends AppCompatActivity {
class ValueContainer<T> {
private T value;
public ValueContainer() { }
public ValueContainer(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ValueContainer<String> token = new ValueContainer<String>();
String getTokenUrl = "http://www.someurl.com/?somekey=somevalue";
JsonObjectRequest getTokenRequest = new JsonObjectRequest(
Request.Method.GET, getTokenUrl, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
token.setValue(response.getString("token"));
Log.d("myTag", "token value1:" + token.getValue());
mainTextView.append("Response: JsonObjectRequest successful: get_token: " + token.getValue() + "\n");
} catch (JSONException e) {
mainTextView.append("Response: JSONException: getString():" + e);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
mainTextView.append("Response: JsonObjectRequest failed: " + error + "\n");
}
});
Log.d("myTag", "token value2:" + token.getValue());
}
You can change the "real content" of a "final" Object, but you can't change it's address, as the example said blew.
String stringTest = "test String";
StringBuffer normalTest = new StringBuffer(stringTest);
normalTest = normalTest.append(" end");
normalTest.delete(0, 5);
System.out.println(normalTest);
final StringBuffer finalTest = new StringBuffer(stringTest);
// finalTest = finalTest.append(" end"); // can't work;
finalTest.delete(0, 5);
System.out.println(finalTest);
you can test by your code as
//token = new Token("...")// can't work
token.changeTheToken("...")// work ok
I have google a lot but i can find solution about my issue my old code for call web service from my activity i have pass two parameter one is link means URL and second is parameters is for data i have to send to server.
problem is i have to use volley in place of following code
call retrieveStream("www.xyz.com/abc.php","data=dfsds");
public static String retrieveStream(String link, String parameters) {
try {
link = link.replace(" ", "%20");
URL url = new URL(link);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.setRequestMethod("POST");
OutputStreamWriter request = new OutputStreamWriter(
connection.getOutputStream());
request.write(parameters);
request.flush();
request.close();
String line = "";
InputStreamReader isr = new InputStreamReader(
connection.getInputStream());
BufferedReader reader = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
while ((line = reader.readLine()) != null) {
sb.append(line);
}
// Response from server after login process will be stored in
// response variable.
String response = sb.toString();
// You can perform UI operations here
isr.close();
reader.close();
return response;
} catch (IOException ignored) {
ignored.printStackTrace();
}
return "";
}`
I have implement in volley
StringRequest sr = new StringRequest(Request.Method.POST,
JSONUtils.WEB_SERVICE + "pausetest.php",
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// mPostCommentResponse.requestCompleted();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// mPostCommentResponse.requestEndedWithError(error);
Toast.makeText(getActivity().getApplicationContext(),
error.toString(), Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("allanswer", alldata);
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/x-www-form-urlencoded");
return params;
}
};
AppController.getInstance().addToRequestQueue(sr);`
FYI. This is assuming that your using application/x-www-form-urlencoded, as to a multi-part-form. I believe the Volley document/videos state somewhere that it is not meant for large data transfers.
I usually make a separate class for my various distinct Volley call, especially for restful processing or reuse as follows:
package com.your.package;
public class MyVolleyRequest1 {
public void myUniqueVolleyRequest(final String _parameter1, final String _parameter2) {
if (!isNetworkAvailable()) {
apiNetworkUnAvailableMsg("No network for this function.");
return;
}
RequestQueue queue = MyVolley.getRequestQueue();
StringRetroFIXRequest myReq = new StringRetroFIXRequest(Method.POST,
getMyContext().getString(R.string.http_url),
createMyReqSuccessListener(),
createMyReqErrorListener()) {
public Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("parameter 1", _parameter1);
params.put("parameter 2", _parameter2);
return params;
}
;
};
queue.add(myReq);
}
private Response.Listener<String> createMyReqSuccessListener() {
return new Response.Listener<String>() {
#Override
public void onResponse(String response) {
setResponseSuccess(response);
}
};
}
private Response.ErrorListener createMyReqErrorListener() {
return new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
setResponseSuccess(error.toString());
}
};
}
private void setResponseSuccess(String result) {
EventBus.getDefault().post(new EventBusResultsClassResponseDone(result));
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager
= (ConnectivityManager) getMyContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
private void apiNetworkUnAvailableMsg(String _purpose) {
String mReturn = "Internet connection unavailable. Try " + _purpose + " at a later time.";
EventBus.getDefault().post(new VolleyReturnEvent(mReturn));
}
}
I also use EventBus, so that I can loosely couple the return value(s), especially, if I decide I want to put those results into a model (pojo), like for using MVC/MVP type processing or say specialized processing of json, etc.
Optionally I also like to use OKHttp in combination Volley, here are the dependencies for gradle in Android Studio.
compile 'de.greenrobot:eventbus:2.1.0'
compile 'com.squareup.okio:okio:1.1.0'
compile 'com.squareup.okhttp:okhttp:2.2.0'
If you are just going to do restful processing Retrofit is a cool library.
Implementing in your Activity or Fragment you then define the above class and instantiate with the parameters, if needed. My example has 2 parameters. Then you implement EventBus, define the eventbus class, and include the return events via EventBus in your app, including the generic VolleyError which is returned as a separate event for error processing.
Here's a gist of what I'd put in my activity to call and then get responses from Volley/OKHttp.
#Override
protected void onResume() {
super.onResume();
EventBus.getDefault().register(this);
requestMyVolleyResponse1();
}
#Override
protected void onPause() {
EventBus.getDefault().unregister(this);
super.onPause();
}
private void requestMyVolleyResponse1() {
MyVolleyRequest1 mVolleyRequest1 = new MyVolleyRequest1();
mVolleyRequest1.MyVolleyRequest1("Parameter 1 value","Parameter 2 value");
}
public void onEventMainThread(MyVolleyRequest1Done event) {
// Your successful response processing.
}
public void onEventMainThread(VolleyReturnEvent event) {
// Your Error Processing
;
}
The EventBus return classes that you have to define (VolleyReturnEvent, MyVolleyRequest1Done) are really simple, i.e.
public class VolleyReturnEvent {
public final String message;
public VolleyReturnEvent(String message) {
this.message = message;
}
}