Why value is assigned after usage in method? - java

So, I was bothering with this issue.
I have in my code value named
public String currentSong = "artist- title";
and I use it in code like this
private MetadataOutput getSongTime() {
return new MetadataOutput() {
#Override
public void onMetadata(Metadata metadata) {
final int length = metadata.length();
if (length > 0) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(existingURL.split("play")[0] + "currentsong").build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(#NotNull Call call, #NotNull IOException e) {
call.cancel();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
currentSong = response.body().toString();
}
});
Toast.makeText(RadioService.this, currentSong, Toast.LENGTH_SHORT).show();
}
}
};
}
But value in Toast is always behind the change (on second run it have value I expected on first run)
Is there any way to make it work correctly?

currentSong get the value on the onResponse, and its asynchronous
You must wait the response to show the Toast Message
#Override
public void onResponse(Call call, Response response) throws IOException {
currentSong = response.body().toString();
// you new a new Thread to show info in the screen beacausre the methos is asynchronous
Activity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// show toast here
}
}
}

Related

How to auto refresh data in android studio every second?

I am new to android studio, I am making an app that gets the json of a field in thingspeak, but I don't know how can I make an auto refresh to the data I get every second. Can you please help me?
public class MainActivity extends AppCompatActivity {
private TextView mTextViewResult;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextViewResult = findViewById(R.id.text_view_result);
OkHttpClient client = new OkHttpClient();
// Read field url from thingspeak
String url = "https://api.thingspeak.com/channels/XXXXXXX/fields/1.json?api_key=XXXXXXXXXXXXX&results=2";
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onResponse(#NonNull okhttp3.Call call, #NonNull Response response) throws IOException {
if (response.isSuccessful()) {
// this is what I want to refresh every second
final String myResponse = response.body().string();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
mTextViewResult.setText(myResponse);
}
});
}
}
});
}
}
I found a solution finally, I placed the data request inside the following code and it worked perfectly:
final Handler handler = new Handler();
Runnable refresh = new Runnable() {
#Override
public void run() {
// data request
handler.postDelayed(this, 5000);
}
};
handler.postDelayed(refresh, 5000);
Use a CountDown Timer . Set the timer for 1 second and in onFinish method call request data .
new CountDownTimer(1000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
//Request Data
}
}.start();

android how to make validation url available from retrofit

To check whether youtube url is available I used retrofit, it works well but I want to use it as validation I got stuck, here's my code :
CheckUrlHelper.java
private static final String BASE_URL= "https://youtu.be/";
public void CheckUrl(String youtube_id)
{
retrofit=new Retrofit.Builder().baseUrl(BASE_URL+youtube_id).build();
Call<ResponseBody> call= retrofit.create(CheckUrlAvailable.class).checkUrl();
call.enqueue(new Callback<ResponseBody>()
{
#Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
//Log.d("","response : "+response);
if(response.code() == 200)
{
result = "true";
}
else
{
result = "false";
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
result = "false";
}
});
listener.getResult(result);
}
public interface callbackListener {
void getResult(String result);
}
I've tried using interface like code on above but caused error.
My expectation : to get result (if it possibly to get result from code whether 200, 500 or etc), so :
MyClass.java
private String error_message;
public void onClick(View v) {
String video_link = editVideoLink.getText().toString();
CheckUrlHelper curl = new CheckUrlHelper();
/* MY Expectation */
if(curl.CheckUrl(video_link) == 200){
Toast.makeText(getActivity(),"url available",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity(),"url not available",Toast.LENGTH_SHORT).show();
}
/**** Edit ****/
String video_link = editVideoLink.getText().toString();
if(TextUtils.is_empty(video_link){
error_message = "Link cannot be empty";
} else if(/* methodNamewhatever(video_link) == false*/ OR /* methodNamewhatever(video_link) == 404*/){
error_message = "Invalid Link";
}else{
// save
}
Toast.makeText(getActivity(),error_message,Toast.LENGTH_SHORT).show();
So when user put youtube id on editText and then click on submit, it could be give the result as validation.
please help me
Thanks
Well, you misplaced the listener's location. Instead of calling it out of all functions, you need to call it once in each method in order to get the result after the response is triggered in onResponse and onFailure callbacks.
So you have to change your code to be like this
private static final String BASE_URL= "https://youtu.be/";
public void CheckUrl(String youtube_id, callbackListener listener)
{
retrofit = new Retrofit.Builder().baseUrl(BASE_URL+youtube_id).build();
Boolean result = false;
Call<ResponseBody> call= retrofit.create(CheckUrlAvailable.class).checkUrl();
call.enqueue(new Callback<ResponseBody>()
{
#Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
//Log.d("","response : "+response);
if(response.code() == 200)
{
result = true;
}
else
{
result = false;
}
listener.getResult(result);
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
result = false;
listener.getResult(result);
}
});
}
public interface callbackListener {
void getResult(Boolean result);
}
I have created some code snippets for you just try to use to solve your issues.
CheckUrlHelper.java
private static final String BASE_URL= "https://youtu.be/";
public void CheckUrl(String youtube_id, callbackListener listener)
{
retrofit = new Retrofit.Builder().baseUrl(BASE_URL+youtube_id).build();
Boolean result = false;
Call<ResponseBody> call= retrofit.create(CheckUrlAvailable.class).checkUrl();
call.enqueue(new Callback<ResponseBody>()
{
#Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
//Log.d("","response : "+response);
if(response.code() == 200)
{
result = true;
}
else
{
result = false;
}
listener.getResult(result);
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
result = false;
listener.getResult(result);
}
});
}
public interface callbackListener {
void getResult(Boolean result);
}
And modify your click code in
MyClass.java
public void onClick(View v) {
String video_link = editVideoLink.getText().toString();
CheckUrlHelper curl = new CheckUrlHelper();
//curl.CheckUrl(video_link);
curl.CheckUrl(video_link, new callbackListener() {
#Override
public void getResult(Boolean result) {
if(result){
Toast.makeText(getActivity(),"url available",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity(),"url not available",Toast.LENGTH_SHORT).show();
}
}
});
Hopefully this will solve your problems.

SwipeRefresh layout progress bar is not hiding even after completion

I am using MVVM pattern in which I am using SwipeRefresh layout to refresh recycler view in my layout.When I am pulling it then it continue to refresh even after method completed successfully.
Below is my code:
MainActivity.java
refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
userRepository.getUserList();
}
});
UserRepository.java
public void getUserList(){
Retrofit retrofit = RetrofitClient.getInstance();
ApiService apiService = retrofit.create(ApiService.class);
Call<List<User>> userList = apiService.getUser();
userList.enqueue(new Callback<List<User>>() {
#Override
public void onResponse(Call<List<User>> call, final Response<List<User>> response) {
Completable.fromAction(new Action() {
#Override
public void run() throws Exception {
if(response.body() != null) {
List<User> list = response.body();
for (int i = 0; i < list.size(); i++) {
String id = list.get(i).get_id();
String names = list.get(i).getName();
String age = list.get(i).getAge();
User user = new User(id,names,age);
userDb.userDao().Insert(user);
}
}
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new CompletableObserver() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onComplete() {
Toast.makeText(context,"Data inserted",Toast.LENGTH_SHORT).show();
}
#Override
public void onError(Throwable e) {
Toast.makeText(context,e.getMessage(),Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onFailure(Call<List<User>> call, Throwable t) {
Toast.makeText(context,t.getMessage(),Toast.LENGTH_LONG).show();
}
});
}
Method fetching list is in another class UserRepository and I am calling method in another activity MainActivity.I am not getting any way how can I stop refreshing process.Someone please let me know a way to stop refreshing process.
Any help would be appreciated.
THANKS
To disable the progress dialog add this,
swipeLayout.setRefreshing(false);

Reply from Retrofit

I'm making a GET request:
public interface CheckUserInDBRequest {
#GET("api/checkUserInDB.php")
Call<ResponseBody> searchForUser(
#Query("login") String login,
#Query("pass") String pass
);
}
And I get the answer true || false in json, according to whether there is a user in the database or not.
Retrofit.Builder builder = new Retrofit.Builder().baseUrl("https://kurusa.zhecky.net/").addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
CheckUserInDBRequest client = retrofit.create(CheckUserInDBRequest.class);
Call<ResponseBody> call = client.searchForUser (
UserLogin.getText().toString(),
UserPass.getText().toString()
);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(#NonNull Call<ResponseBody> call, #NonNull Response<ResponseBody> response) {
Toast.makeText(MainActivity.this, response.body().toString(), Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(#NonNull Call<ResponseBody> call, #NonNull Throwable t) {
Toast.makeText(MainActivity.this, "no ", Toast.LENGTH_SHORT).show();
}
});
Here is just the output of okHttp3. I do not understand how to get a normal answer.
First, create a class representing your JSON object
public class UserResult {
public boolean isSet;
}
Restructure your Retrofit call in this way
#GET("api/checkUserInDB.php")
Call<UserResult> searchForUser(
#Query("login") String login,
#Query("pass") String pass
);
Then in your code:
call.enqueue(new Callback<UserResult>() {
#Override
public void onResponse(#NonNull Call<UserResult> call, #NonNull Response<UserResult> response) {
if (response.isSuccesfull()) {
UserResult result = response.body();
//use the value result.isSet where you need it
} else {
//something is broken
}
}
#Override
public void onFailure(#NonNull Call<UserResult> call, #NonNull Throwable t) {
Toast.makeText(MainActivity.this, "no ", Toast.LENGTH_SHORT).show();
}
});

Executing okhttp post requests one after another

I have 3 recursion methods which make post requests by okhttp
The first one is:
private void sendStatPhoto() {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (!mSharedPreferences.getString("Statistics_photo", "").equals("")) {
mStatisticsPhoto = mSharedPreferences.getString("Statistics_photo", "").split(";");
System.out.println(mStatisticsPhoto[0]);
mPhoto = DBReader.read(mSQLiteDatabase,
"photo_statistics_" + mStatisticsPhoto[0],
"names");
mDictionaryForRequest = new Hashtable();
mDictionaryForRequest.put("login_admin", QuestionnaireActivity.this.getString(R.string.login_admin));
OkHttpClient client = new OkHttpClient();
client.newCall(new DoRequest(QuestionnaireActivity.this).Post(mDictionaryForRequest, QuestionnaireActivity.this.getString(R.string.url), mPhoto))
.enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
System.out.println("Ошибка");
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(QuestionnaireActivity.this, "Ошибка отправки!", Toast.LENGTH_SHORT).show();
Log.d("TAG", "3 error");
}
});
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
String responseCallback = response.body().string();
if (responseCallback.substring(1, responseCallback.length() - 1).equals("1")) {
mSQLiteDatabase.execSQL("DROP TABLE if exists " + "photo_statistics_" + mStatisticsPhoto[0]);
SharedPreferences.Editor editor = mSharedPreferences.edit()
.putString("Statistics_photo", mSharedPreferences.getString("Statistics_photo", "").replace(mStatisticsPhoto[0] + ";", "")); //temp-оставшиеся анкеты.
editor.apply();
new File(getFilesDir(), "files/" + mPhoto + ".jpg").delete();
System.out.println("Deleted");
Log.d("TAG", "3 good");
sendStatPhoto();
}
}
}
);
}
}
});
}
And 2 other methods which make exactly the same with some other kind of data
private void sendAudio() {...}
private void send() {...}
I need to execute them one after another.
I tried to make the array of methods
Runnable[] methods = new Runnable[]{
new Runnable() {
#Override
public void run() {
Log.d("TAG", "1");
send();
}
},
new Runnable() {
#Override
public void run() {
Log.d("TAG", "2");
sendAudio();
}
},
new Runnable() {
#Override
public void run() {
Log.d("TAG", "3");
sendStatPhoto();
}
}
};
But okhttp makes all posts in new Threads and it does not work.
if (Internet.hasConnection(this)) {
Log.d("TAG", "start");
ExecutorService service = Executors.newSingleThreadExecutor();
for (Runnable r : methods)
service.submit(r);
service.shutdown();
Log.d("TAG", "finish");
}
How to execute one post after another?
The problem is that i want to send a pack of data(like 10-20 times) in 3 metods(in sequence 1-2-3) but i get the data for 3-rd some later and if i ll put the execution of the next method in onResponse i ll lose the 3-rd
use .then to concat http methods:
$http.post(UserPass, {username : vm.data.username, password : vm.data.password
}).then(function (res){
var serverresponse = res.data;
}).then(function (){
// another http request here and so on
$http.post({}).then(function (){
//etc...
});
});
;)
Hope this helps, for me this was a nightmare the first time!
(".then" waits for the http to execute and then proceeds with what it has inside)

Categories