I want to display an AlertDialog in my View showing that the result was successful,
private void actionUpdateProfesional() {
btnSave.setOnClickListener(view -> {
alertDialog = new AlertDialog.Builder(this)
.setTitle("Wait!")
.setMessage("Are you sure you want update your data?")
.setPositiveButton("YES", (dialogInterface, i) -> presenter.updateProfile())
.setNegativeButton("NO", null)
.create();
alertDialog.show();
});
}
after my Completable made onComplete on my Presenter:
#Override
public void updateProfile() {
Disposable d = updateInfoInteractor
.build(new ProfileUpdateInfoInteractor.Param(view.getPhone(), view.getLocation(), view.getDescription()))
.observeOn(schedulers.main())
.subscribeWith(new DisposableCompletableObserver() {
#Override
public void onComplete() {
Timber.d("Profile edited");
}
#Override
public void onError(Throwable e) {
Timber.d("Error at edit profile");
}
});
}
But if you want to solve this problem by MVP Architecture you have to create new method in your View interface. Because presenter does not do UI logic or your architecture will be broken.
public interface MyObjectView {
void resultSuccess(int status);
}
MyObjectView myView
Public MyPresenterConstructor(MyObjectView myView){
this.myView = myView;
}
#Override
public void updateProfile() {
Disposable d = updateInfoInteractor
.build(new ProfileUpdateInfoInteractor.Param(view.getPhone(), view.getLocation(), view.getDescription()))
.observeOn(schedulers.main())
.subscribeWith(new DisposableCompletableObserver() {
#Override
public void onComplete() {
Timber.d("Profile edited");
// Show alert dialog here!
myView.resultSuccess(200) // Okee
}
#Override
public void onError(Throwable e) {
Timber.d("Error at edit profile");
}
});
}
Then, do not forget to implement your View interface in your Activity (UI). then call your alertDialog.
public class MainActivity extend AppCompatActivity implement MyObjectView{
…….
#Override
Public void resultSuccess(int code){
// call your dialog here
}
…..
}
You should call the actionUpdateProfesional() method of your view from the onComplete method.
You'll probably need to add the actionUpdateProfesional() to your View interface that you reference in your presenter.
It would be something like this:
#Override
public void updateProfile() {
Disposable d = updateInfoInteractor
.build(new ProfileUpdateInfoInteractor.Param(view.getPhone(), view.getLocation(), view.getDescription()))
.observeOn(schedulers.main())
.subscribeWith(new DisposableCompletableObserver() {
#Override
public void onComplete() {
Timber.d("Profile edited");
if (view != null) {
view.actionUpdateProfesional()
}
}
#Override
public void onError(Throwable e) {
Timber.d("Error at edit profile");
}
});
}
You have not actually asked a question, so I'm assuming that you are wondering how to show your alert dialog on a complete event. You can to this by simply instantiating it again in the onComplete() function.
#Override
public void updateProfile() {
Disposable d = updateInfoInteractor
.build(new ProfileUpdateInfoInteractor.Param(view.getPhone(), view.getLocation(), view.getDescription()))
.observeOn(schedulers.main())
.subscribeWith(new DisposableCompletableObserver() {
#Override
public void onComplete() {
Timber.d("Profile edited");
// Show alert dialog here!
alertDialog = new AlertDialog.Builder(this)
.setTitle("Wait!")
.setMessage("Are you sure you want update your data?")
.setPositiveButton("YES", (dialogInterface, i) ->
presenter.updateProfile())
.setNegativeButton("NO", null)
.create();
alertDialog.show();
}
#Override
public void onError(Throwable e) {
Timber.d("Error at edit profile");
}
});
}
Hope this helps!
Related
Actually i couldn't find any error here. I think i m missing something here. this filtersbutton is not working. Your help will be appreciated. Thank you
This is my fragment.class
sortByLeastExpensive = rootView.findViewById(R.id.sort_by_least_expensive);
sortByMostExpensive = rootView.findViewById(R.id.sort_by_most_expensive);
sortByMostRecent = rootView.findViewById(R.id.sort_by_most_recent);
applyFiltersBtn = rootView.findViewById(R.id.apply_filters_btn);
sortByLeastExpensive.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//set the filter; or call the viewmodel to set the filter?
mViewModel.sortBy.setValue(getResources().getString(R.string.sort_rooms_ascending));
}
});
sortByMostExpensive.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mViewModel.sortBy.setValue(getResources().getString(R.string.sort_rooms_descending));
}
});
sortByMostRecent.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mViewModel.sortBy.setValue("sort_most_recent");
}
});
return rootView;
}
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(getActivity()).get(FilterRoomsViewModel.class);
mViewModel.getSortBy().observe(this, Observer -> {
Log.i("Viewmodel", "Viewmodel ,sortby: " + mViewModel.sortBy.getValue());
});
applyFiltersBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FilterRoomsRepository roomsRepository = new FilterRoomsRepository();
roomsRepository.getFilteredRooms(mViewModel.sortBy.getValue());
}
});
}
This is viewmodel.class
i have updated my viewmodel.class. now its showing me another error on fragment.class
public FilterRoomsViewModel(Application application){
super();
FilterRoomsRepository filterRoomsRepository = new FilterRoomsRepository(application);
}
public MutableLiveData<String> getRooms(){
if (rooms==null){
rooms = new MutableLiveData<String>();
}
return rooms;
}
public LiveData<String> getSortBy() {
if (sortBy == null){
sortBy = new MutableLiveData<String>();
}
return sortBy;
}
this is repository.class
if(sortyBy.equals("ascending")){
Log.i("Sort by", "Rooms sorted in ascending order");
filterQuery.orderByAscending("roomRentalAmount");
}else if (sortyBy.equals("descending")){
Log.i("Sort by", "Rooms sorted in descending order");
filterQuery.orderByDescending("roomRentalAmount");
}else {
filterQuery.orderByDescending("updatedAt");
}
filterQuery.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if(e == null){
//success
Log.i("Rooms", "Filtered rooms, " + objects.get(0).getObjectId());
rooms.setValue(objects);
}else{
//error, handle accordingly
Log.e("Error", "Error filtering, " + e.getMessage());
}
}
});
Log.i("Rooms", "Live data rooms, " + rooms.getValue());
return rooms;
}
What do you mean that its not showing? It's not showing in the ui or in logs? Because when you call getFilteredRooms you don't do anything with the result.
What i would suggest is to move the repository call to the viewModel, so that instead of calling getFilteredRooms in the fragment, you would call sth like viewModel.getFilteredRooms and then, in the viewmodel, you call the repository and you use the result to set the value of the livedata.
Then, in the fragment you just need to observe this variable and based on that you update the ui. By doing so, you separate the logic (viewmodel and repository) from the ui part (fragment).
Here is a good tutorial on how to code with mvvm pattern: https://medium.com/#er.ankitbisht/mvvm-model-view-viewmodel-kotlin-google-jetpack-f02ec7754854
i have a recycler view and i want to control of downloading using buttons in my card view.
i use PRDownloader library but i have issue i can't resume download after finish the app and open it again it start the download not resume it.
my code as below
holder.downloadResumeOrPlayBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
downLoadID = PRDownloader.download(remoteLink, myLocalDirectory,
fileName)
.build()
.setOnStartOrResumeListener(new OnStartOrResumeListener() {
#Override
public void onStartOrResume() {
holder.pauseDownloadBtn.setVisibility(View.VISIBLE);
holder.cancelBtn.setVisibility(View.VISIBLE);
holder.downloadResumeOrPlayBtn.setVisibility(View.GONE);
notifyDataSetChanged();
}
})
.setOnPauseListener(new OnPauseListener() {
#Override
public void onPause() {
holder.pauseDownloadBtn.setText(mContext.getResources().getString(string.resume_text_btn));
holder.downloadResumeOrPlayBtn.setVisibility(View.GONE);
holder.pauseDownloadBtn.setVisibility(View.VISIBLE);
holder.cancelBtn.setVisibility(View.GONE);
notifyDataSetChanged();
}
})
.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel() {
holder.mProgressBar.setProgress(0);
holder.downloadResumeOrPlayBtn.setText(mContext.getResources().getString(R.string.download_text));
holder.downloadResumeOrPlayBtn.setVisibility(View.VISIBLE);
holder.pauseDownloadBtn.setVisibility(View.GONE);
holder.cancelBtn.setVisibility(View.GONE);
notifyDataSetChanged();
}
})
.setOnProgressListener(new OnProgressListener() {
#Override
public void onProgress(Progress progress) {
video.setVideoProgress(progress.currentBytes * 100 / progress.totalBytes);
Log.i("videosAdapter", video.getVideoProgress() + "");
holder.mProgressBar.setProgress((int) video.getVideoProgress());
holder.mProgressBar.setVisibility(View.VISIBLE);
notifyDataSetChanged();
}
})
.start(new OnDownloadListener() {
#Override
public void onDownloadComplete() {
System.out.println("download completed");
holder.downloadResumeOrPlayBtn.setText(mContext.getResources().getString(string.play_video_text));
holder.downloadResumeOrPlayBtn.setVisibility(View.VISIBLE);
holder.pauseDownloadBtn.setVisibility(View.GONE);
holder.cancelBtn.setVisibility(View.GONE);
notifyDataSetChanged();
}
#Override
public void onError(Error error) {
holder.downloadResumeOrPlayBtn.setText(mContext.getResources().getString(string.download_text));
Toast.makeText(mContext, error.getServerErrorMessage(), Toast.LENGTH_SHORT).show();
holder.mProgressBar.setProgress(0);
}
});
}
if(holder.downloadResumeOrPlayBtn.getText().toString().equals(mContext.getResources().getString(string.resume_text_btn)))
{
PRDownloader.resume(downLoadID);
}
});
my question is how to resume the download without downloading the file from the start and if there is another library to use how can i make it.
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);
I want to use Rewarded video ads (Admob) but I want to show a progress bar while the video ads is loading
I already try to did it with async task just to see if the video will load but it didn't work
#SuppressLint("StaticFieldLeak")
public class videoAd extends AsyncTask<Void, Void, Void> {
#Override
protected void doInBackground(Void... voids) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mRewardedVideoAd.loadAd("ca-app-pub-3940256099942544/5224354917", new AdRequest.Builder().build());
}
});
}
#Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
if (mRewardedVideoAd.isLoaded()){
Toast.makeText(SetFullWallpaper.this, "Video loaded", Toast.LENGTH_SHORT).show();
mRewardedVideoAd.show();
}
}
}
Now I want to load a progress bar if the video is not loaded yet
Thank you
This is how I did it:
I had a button, which when clicked showed the ad, so I had a boolean variable which tracked whether the button has been clicked:
boolean buttonClicked = false
These lines were in my onCreate function:
mRewardedVideoAd = MobileAds.getRewardedVideoAdInstance(getContext());
rewardedVideoAdListener = new RewardedVideoAdListener() {
#Override
public void onRewardedVideoAdLoaded() {
if(buttonClicked) {
showAd();
}
}
#Override
public void onRewardedVideoAdOpened() {
}
#Override
public void onRewardedVideoStarted() {
}
#Override
public void onRewardedVideoAdClosed() {
loadRewardedVideoAd();
}
#Override
public void onRewarded(RewardItem rewardItem) {
}
#Override
public void onRewardedVideoAdLeftApplication() {
}
#Override
public void onRewardedVideoAdFailedToLoad(int i) {
if(buttonClicked) {
progressBar.setVisibility(View.INVISIBLE);
Toast toast = Toast.makeText(getContext(), "Please try again later", Toast.LENGTH_SHORT);
toast.show();
}
}
#Override
public void onRewardedVideoCompleted() {
}
};
mRewardedVideoAd.setRewardedVideoAdListener(rewardedVideoAdListener);
loadRewardedVideoAd();
pointsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showAd();
}
});
This was my showAd function:
public void showAd(){
if (mRewardedVideoAd.isLoaded()) {
progressBar.setVisibility(View.GONE);
mRewardedVideoAd.show();
buttonClicked = false;
} else {
loadRewardedVideoAd();
progressBar.setVisibility(View.VISIBLE);
buttonClicked = true;
}
}
How this works is, the app tries to load the ad in the background by calling the loadRewaredVideoAd() function when the activity/fragment is created. Then when the user clicks the button,showAd() function is called and one of two things happen:
1) If the ad was successfully loaded, it shows the ad.
2) If not, it calls loadRewardedVideoAd() again and shows a progressbar this time. It also sets buttonClicked to true. Then if the ad loads, the onRewardedVideoAdLoaded() function is called which calls showAd() again and this time the 1st option happens.
If the ad didn't load this time as well, then onRewardedVideoAdFailedToLoad(int i)is called and it shows a toast saying the user to try again later.
add OnProgressUpdate() in your class that extends AsyncTask and add progress dialog in this.
I am placing an admob video, which is executed when you enter the activity. In my case, I put an executable loop to start the video when it is already loaded.
if (mRewardedVideoAd.isLoaded()) {
mRewardedVideoAd.show();
}else{
loadRewardedVideoAd();
}
This is part of all my code
private boolean started = false;
private Handler handler = new Handler();
private void initializeAdMob() {
mRewardedVideoAd = MobileAds.getRewardedVideoAdInstance(this);
mRewardedVideoAd.setRewardedVideoAdListener(this);
loadRewardedVideoAd();
}
private void loadRewardedVideoAd() {
if (!mRewardedVideoAd.isLoaded()) {
mRewardedVideoAd.loadAd(getString(R.string.id_block_activity), new AdRequest.Builder().build());
}
}
private void showRewardedVideoAd() {
if (BaseInteractor.isNetworkAvailable(this)) {
showProgressBar(true);
start();
}
}
private Runnable runnable = new Runnable() {
#Override
public void run() {
if (mRewardedVideoAd.isLoaded()) {
mRewardedVideoAd.show();
}else{
loadRewardedVideoAd();
}
if (started) {
start();
}
}
};
public void stop() {
started = false;
handler.removeCallbacks(runnable);
}
public void start() {
started = true;
handler.postDelayed(runnable, 2000);
}
finally I stop the runnable in
#Override
public void onRewardedVideoAdOpened() {
showProgressBar(false);
stop();
}
I hope this helps you.
I am trying to use the AdMob Rewarded Ad in my Android application.
In order to include it in the refered app, I need to wait for the rewarded video to load after the user click the buttom.
I am trying it throughout the code bellow, but I get the error:
java.lang.IllegalStateException: showAd must be called on the main UI
thread.
When the buttom is clicked:
b_r_ans.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(isSomBotaoLigado() && loaded[0])
soundPool.play(soundID, MyApplication.getVolumeBotao(), MyApplication.getVolumeBotao(), 1, 0, 1f);
Toast.makeText(MyApplication.getAppContext(),carregando_rv, Toast.LENGTH_LONG).show();
Thread t_rv = new Thread(new Runnable() {
public void run() {
while(!rv_loaded){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t_rv.start();
try {
t_rv.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
mRewardedVideoAd.show();
}
});
Overrided the listener:
#Override
public void onRewardedVideoAdLoaded() {
Toast.makeText(this, "onRewardedVideoAdLoaded", Toast.LENGTH_SHORT).show();
rv_loaded = true;
}
Using the mRewardedVideoAd.isLoaded() function triggers the same issue.
How can I wait for the video to load properly?
It appears to happen that you are calling show from a different thread to the UI so I'd try to force its execution on the main thread like:
// Get a handler that can be used to post to the main thread
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = new Runnable() {
#Override
public void run() {
if (mRewardedVideoAd.isLoaded()) {
mRewardedVideoAd.show();
}
};
mainHandler.post(myRunnable);
You can also disable the button until the ad is loaded, then in the onRewardedVideoAdLoaded function enable the button:
override fun onRewardedVideoAdLoaded() {
ad_btn.isEnabled = true
}
Hope it helps. This is the implementation that I am using.
Solved it through this code:
#Override
public void onRewardedVideoAdLoaded() {
//Toast.makeText(this, "onRewardedVideoAdLoaded", Toast.LENGTH_SHORT).show();
rv_loaded = true;
if(goToAnswers)
mRewardedVideoAd.show();
goToAnswers = false;
}
b_r_ans.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(isSomBotaoLigado() && loaded[0])
soundPool.play(soundID, MyApplication.getVolumeBotao(), MyApplication.getVolumeBotao(), 1, 0, 1f);
Toast.makeText(MyApplication.getAppContext(),carregando_rv, Toast.LENGTH_LONG).show();
if(mRewardedVideoAd.isLoaded())
mRewardedVideoAd.show();
else goToAnswers=true;
}
});
This code will show a ProgressDialog while loading the reward video:
package com.mountzoft.waitForrewardvideoProperly;
import android.app.ProgressDialog;
import android.content.Context;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.MobileAds;
import com.google.android.gms.ads.reward.RewardItem;
import com.google.android.gms.ads.reward.RewardedVideoAd;
import com.google.android.gms.ads.reward.RewardedVideoAdListener;
public class MainActivity extends AppCompatActivity implements RewardedVideoAdListener {
private RewardedVideoAd mAd;
private ProgressDialog mProgressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage("Please wait... Loading Reward Video Ad!");
mProgressDialog.setCancelable(false);
}
private final showRewardVideoAd() {
mProgressDialog.show();
initializeRewardVideoAd();
loadRewardedVideoAd();
}
private void initializeRewardVideoAd(){
String adMobAppId = BuildConfig.AD_MOB_APP_ID; //id is stored in build gradle file
MobileAds.initialize(this, adMobAppId);
mAd = MobileAds.getRewardedVideoAdInstance(this);
mAd.setRewardedVideoAdListener(this);
}
private void loadRewardedVideoAd() {
String admobAdUnitId = BuildConfig.ADMOB_AD_UNIT_ID;//id is stored in build gradle
mAd.loadAd(admobAdUnitId,
new AdRequest.Builder().build());
}
#Override
public void onRewardedVideoAdLoaded() {
mAd.show();
}
#Override
public void onRewardedVideoAdOpened() {
mAd = null;
}
#Override
public void onRewardedVideoStarted() {
mProgressDialog.dismiss();
}
#Override
public void onRewardedVideoAdClosed() {
}
#Override
public void onRewarded(RewardItem rewardItem) {
}
#Override
public void onRewardedVideoAdLeftApplication() {
}
#Override
public void onRewardedVideoAdFailedToLoad(int i) {
}
#Override
public void onRewardedVideoCompleted(){
}
}
If you need to wait until rewarded ad loading use SingleLiveEvent. Please refer following code snippet.
private val isRewardedAdLoaded: LiveData<Event<Boolean>>
get() = _isRewardedAdLoaded
private var _isRewardedAdLoaded: MutableLiveData<Event<Boolean>> = MutableLiveData()
I used this is in fragment. So this from onViewCreated()
rewardedAd = createAndLoadRewardedAd()
and I post loading state as following
private fun createAndLoadRewardedAd(): RewardedAd {
val rewarded = RewardedAd(requireContext(), getString(R.string.admob_rewarded_id_test))
val adLoadCallback = object : RewardedAdLoadCallback() {
override fun onRewardedAdLoaded() {
Log.e(TAG, "onRewardedAdLoaded")
_isRewardedAdLoaded.postValue(Event(true))
}
override fun onRewardedAdFailedToLoad(errorCode: Int) {
_isRewardedAdLoaded.postValue(Event(false))
}
}
rewarded.loadAd(Builder().build(), adLoadCallback)
return rewarded
}
this is rewarded ad show method
private fun showRewardedAds(rewarded: RewardedAd) {
rewarded.show(requireActivity(), object : RewardedAdCallback() {
override fun onRewardedAdOpened() {
Log.e(TAG, "onRewardedAdOpened")
}
override fun onRewardedAdClosed() {
Log.e(TAG, "onRewardedAdClosed")
rewardedAd = createAndLoadRewardedAd()
}
override fun onUserEarnedReward(rewardItem: RewardItem) {
Log.e(TAG, "onUserEarnedReward")
translateText()
}
override fun onRewardedAdFailedToShow(errorCode: Int) {
translateText()
}
})
}
Finally I called as following
R.id.btnTranslate -> {
if (rewardedAd.isLoaded){
showMessage(
getString(R.string.translate_ads_show_warning_title),
getString(R.string.translate_ads_show_warning_msg)
)
} else {
progress.setVisible(true)
isRewardedAdLoaded.observe(viewLifecycleOwner, Observer {
it.getContentIfNotHandled()?.let { loaded ->
if (loaded and progress.isVisible){
progress.setVisible(false)
showMessage(
getString(R.string.translate_ads_show_warning_title),
getString(R.string.translate_ads_show_warning_msg)
)
}
}
})
}
}