Making Retrofit request from DialogFragment - android

I have implemented a login DialogFragment in my app (API 19). I'm using Retrofit 1.7.1 for networking. The implementation is below:
public class SignInDialogFragment extends DialogFragment {
private EditText mUsernameEditText;
private EditText mPasswordEditText;
public static SignInDialogFragment newInstance() {
return new SignInDialogFragment();
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Builder builder = new AlertDialog.Builder(getActivity())
.setPositiveButton(R.string.action_sign_in, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String username = mUsernameEditText.getText().toString();
APIFactory.getAPI().register(username, new Callback<RegistrationResponseModel>() {
#Override
public void success(RegistrationResponseModel registrationResponse, Response response) {
Toast.makeText(getActivity(), "Totally worked!", Toast.LENGTH_SHORT).show();
}
#Override
public void failure(RetrofitError error) {
Toast.makeText(getActivity(), "Something failed!", Toast.LENGTH_SHORT).show();
}
});
}
})
.setNegativeButton(R.string.action_cancel, null);
View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_sign_in, null);
builder.setView(view);
mUsernameEditText = (EditText)view.findViewById(R.id.usernameEditText);
return builder.create();
}
}
As you might predict, this crashes upon success or failure when getActivity() hits a null reference. What is the best way to handle an asynchronous request such as this, including getting callbacks after the dialog has been dismissed?
I thought of a few options; are any of them viable?
I could simply hold the dialog open if there is a request in progress. I haven't implemented this because I'm not sure of the cleanest way to keep the dialog around (handling the Back button, etc).
I would really like to just cancel the Request if the dialog is closed, but I can't, because there is not currently a way to cancel Retrofit requests.
If there is an option that I'm not aware of, I'd like to hear about it.

You should move your action out of Dialog. Dialog is not Activity - once user did a choice, dialog should be dismissed and if there's any action to trigger it should be done as response to user action with dialog, but it should not be part of dialog. Therefore you should just react to user choice in your parent Fragment or Activity, not in Dialog.

Related

Alert Dialog with an option to request the email verification link from firebase is not working

I am trying to show an alert dialog with two buttons ("OK" and "Send Email") in user login activity. I am using firebase for user authentication. Before trying to implement alert dialog, I used Toast.makeText to show that email address is not verified and I was working perfectly fine. But now I want to give user an option to request the email verification link again in case they couldn't find the previous one. I went through https://developer.android.com/guide/topics/ui/dialogs.html and also went through some questions and answers on slackoverflow. The problem I am facing here is even though I can make the dialog popup by making a fragment class, I can't use this option. Because I don't know a way to retrieve current user instance from firebase to another class. It always crushes the app if I try to do it that way. So, I tried to implement alert dialog in the activity class and you can see my code below.
firebaseAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
progressDialog.dismiss();
if(task.isSuccessful()){
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (!user.isEmailVerified()){
AlertDialog.Builder emailAlert = new AlertDialog.Builder(getActivity());
emailAlert.setTitle("Verify you email");
emailAlert.setMessage("The email address is not verified.");
emailAlert.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
firebaseAuth.signOut();
return;
}
});
emailAlert.setNegativeButton(R.string.send_email, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
user.sendEmailVerification()
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()){
Toast.makeText(LoginActivity.this, "Email Sent", Toast.LENGTH_SHORT).show();
}
firebaseAuth.signOut();
return;
}
});
}
});
emailAlert.create();
}
startActivity(new Intent(getApplicationContext(),HomeActivity.class));
}
else{
Toast.makeText(LoginActivity.this, "Login Failed, please make sure all feids are complete", Toast.LENGTH_SHORT).show();
}
progressDialog.dismiss();
}
});
There is no run time error but the alert dialog is not showing up. Can someone please point me out what I am doing wrong? And please let me know if there is a better way to get the same outcome.
First of all replace
AlertDialog.Builder emailAlert = new AlertDialog.Builder(getActivity());
with
AlertDialog.Builder emailAlert = new AlertDialog.Builder(this);
Because getActivity() will not work for Activity.
And the main thing is that replace
emailAlert.create();
with
emailAlert.show();
Hope your problem will be solved.

can not update Data in Kinvey Database

I am trying to update a record in kinvey collection but it keep saying insufficient credentials
i found a similar question on the forum that said i have to setGloballyWriteable to the acl of my model i have done that but still have the error
here is my code
public void loadMenuHelper(){
menu_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final Order order = my_orders[position];
order.getAcl().setGloballyWriteable(true);
order.getAcl().setGloballyReadable(true);
int requests = order.getRequests();
////////////have the handler
AlertDialog.Builder alert = new AlertDialog.Builder(
new ContextThemeWrapper(ImageTargets.this, R.style.AlertDialogCustom));
LinearLayout layout = new LinearLayout(ImageTargets.this);
layout.setOrientation(LinearLayout.VERTICAL);
alert.setTitle("There are " + requests + "Before you");
alert.setView(layout);
alert.setPositiveButton("Create", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
///////////////
order.getAcl().setGloballyWriteable(true);
order.getAcl().setGloballyReadable(true);
order.setRequests(order.getRequests() + 1);
AsyncAppData<Order> myevents = mKinveyClient.appData("Order", Order.class);
myevents.save(order, new KinveyClientCallback<Order>() {
#Override
public void onFailure(Throwable e) {
Log.i("TAG", "failed to save event data" + e.getMessage());
Log.i("TAG", sharedpreferences.getString("owner_name", ""));
}
#Override
public void onSuccess(Order r) {
Log.d("TAG", "saved data for entity " + r.getName());
Toast.makeText(getApplicationContext(), "Your Order was Created Sucessfully", Toast.LENGTH_SHORT).show();
}
});
}
////////////
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// what ever you want to do with No option.
}
});
alert.show();
////////////////
}
});
///////////////
}
Considering that you have a user properly logged in, this seems to be related to collection permissions.
Your collection is in shared mode, that's why you are able to read the order object created by somebody else. But, because only creator can modify the object, you are getting "insufficient credentials" error.
You have two options here. The first option is to change collection permissions to public so that anybody can edit any order object. You can do that in Kinvey web console by going to settings tab in the data browser for the Order collection. After this, you won't need to use setGloballyWriteable/setGloballyReadable.
Other option (better suitable according to me) is to create another collection for requests for specific orders. In this new collection, you will be able to store a reference of the order object as well as store user information about the user who requested it.
You can find necessary documentation related to collection permissions here - http://devcenter.kinvey.com/android/guides/security

How to create an AlertDialog before an sms text is sent?

I would like to know if it is possible to create an AlertDialog before a text message is sent from the default messaging app. I have looked at other people's questions on intercepting outgoing sms messages, however, those only seem to show how to read the message and not actually prevent it from being sent. I also do not want to create my own messaging app from scratch, so please do not suggest that. Thank you.
First of all create a new AlertDialog object like this
AlertDialog.Builder builder = new AlertDialog.Builder(this);
Now lets say the SMS you want to send is triggered by the click of a button. Lets call it sendSMS. Inside the onClick method set the parameters of the AlertDialog object like this :
sendSMS.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
builder.setMessage("You are about to send an SMS! are you sure you want to send it?")
.setTitle("Warning!")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(#SuppressWarnings("unused") final DialogInterface dialog, #SuppressWarnings("unused") final int id) {
//*******************************
//PUT HERE THE SMS SENDING CODE!!!
//*******************************
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(final DialogInterface dialog, #SuppressWarnings("unused") final int id) {
//closes the dialog; nothing interesting happens here
dialog.cancel();
}
});
final AlertDialog alert = builder.create();
alert.show();
}
});
return true;
}
This displays an AlertDialog with the click of a button, warning the user that he/she is about to send an SMS. If he/she clicks yes then, the SMS code is triggered. If he/she clicks no nothing happens.

Check Facebook Login in Android

I have an application that uses the Facebook SDK for Android to login into my application. But I am having some problems in checking whether the user is already logged-in or not. After the login page, the main interface will be displayed to the user. What I want is that, if the user has logged-in in its past interaction with application, the next time the application is launched, no more login screen just the main interface. So at start-up my application should check whether a user is logged in or not. How will I do it?
I tried using mFacebook.isSessionValid(), but it's always returning a false.
You can try the following code :
if(mFacebook.isSessionValid()) {
onFacebookClick();
}
private void onFacebookClick() {
if (mFacebook.isSessionValid()) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Delete current Facebook connection?")
.setCancelable(false)
.setPositiveButton("Yes",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
fbLogout();
}
})
.setNegativeButton("No",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
dialog.cancel();
facebook_btn.setText(getResources().getString(R.string.signinout));
}
});
final AlertDialog alert = builder.create();
alert.show();
} else {
facebook_btn.setText(getResources().getString(R.string.signin));
mFacebook.authorize(this, PERMISSIONS, -1,new FbLoginDialogListener());
}
}

Android Licensing Server on a device

I'm trying to figure out the whole Android licensing thing, and getting frustrated.
In the emulator, I run the app with no account, or one that isn't in the testing environment, and it seems to work correctly, returning the not licensed response and pops up the buy the app now message.
When I try to run it on an actual Android device, it returns licensed every time, even though the device account isn't one that is in the testing environment.
Also, even though it returns licensed, the "checking license" box never goes away, unless you click cancel. Then it just lets you use the app as if it was licensed.
It's mostly C&P from the example, with a few changes. I removed the check license button and the status text box.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new Handler();
// Try to use more data here. ANDROID_ID is a single point of attack.
String deviceId = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
// Library calls this when it's done.
mLicenseCheckerCallback = new MyLicenseCheckerCallback();
// Construct the LicenseChecker with a policy.
mChecker = new LicenseChecker(
this, new ServerManagedPolicy(this,
new AESObfuscator(SALT, getPackageName(), deviceId)),
BASE64_PUBLIC_KEY);
doCheck();
ArrayAdapter<String> booksAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mBooks);
this.setListAdapter(booksAdapter);
}
protected Dialog onCreateDialog(int id) {
// We have only one dialog.
return new AlertDialog.Builder(this)
.setTitle(R.string.unlicensed_dialog_title)
.setMessage(R.string.unlicensed_dialog_body)
.setPositiveButton(R.string.buy_button, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(
"http://market.android.com/details?id=" + getPackageName()));
startActivity(marketIntent);
finish();
}
})
.setNegativeButton(R.string.quit_button, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.create();
}
private void doCheck() {
setProgressBarIndeterminateVisibility(true);
alertbox("status", getString(R.string.checking_license));
mChecker.checkAccess(mLicenseCheckerCallback);
}
protected void alertbox(String title, String mymessage)
{
new AlertDialog.Builder(this)
.setMessage(mymessage)
.setTitle(title)
.setCancelable(true)
.setNeutralButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton){}
})
.show();
}
private void displayResult(final String result) {
mHandler.post(new Runnable() {
public void run() {
alertbox("status", result);
setProgressBarIndeterminateVisibility(false);
}
});
}
private class MyLicenseCheckerCallback implements LicenseCheckerCallback {
public void allow() {
if (isFinishing()) {
// Don't update UI if Activity is finishing.
return;
}
// Should allow user access.
//displayResult(getString(R.string.allow));
}
public void dontAllow() {
if (isFinishing()) {
// Don't update UI if Activity is finishing.
return;
}
//displayResult(getString(R.string.dont_allow));
// Should not allow access. In most cases, the app should assume
// the user has access unless it encounters this. If it does,
// the app should inform the user of their unlicensed ways
// and then either shut down the app or limit the user to a
// restricted set of features.
// In this example, we show a dialog that takes the user to Market.
showDialog(0);
}
public void applicationError(ApplicationErrorCode errorCode) {
if (isFinishing()) {
// Don't update UI if Activity is finishing.
return;
}
// This is a polite way of saying the developer made a mistake
// while setting up or calling the license checker library.
// Please examine the error code and fix the error.
String result = String.format(getString(R.string.application_error), errorCode);
displayResult(result);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
mChecker.onDestroy();
}
I just don't know what I need to change to make it work... or if the license is somehow cached (even though this is the first time I've run it on this device) and if I can uncache it without wiping the device, as that'll be nice for when I do testing on other apps.
Also, how do I remove the "checking license" message without having to click the cancel button... should I just make it so that it doesn't show up?
I'm just getting into licensing myself so don't take this as gospel but a few things stick out:
or if the license is somehow cached (even though this is the first time I've run it on this device) and if I can uncache it without wiping the device, as that'll be nice for when I do testing on other apps.
You are using the ServerManagedPolicy so the approval will be cached and obfuscated. This is the recommended way to do it. ( I assume to provide a better user experience and better response time ) In order to debug your approval you need to log into your market profile and change the "Test response" option. You need to use a device that has the same account as your publisher profile for the test response to work for a app that isn't released to the market yet.
You also have no code in your allow() method for your MyLicenseCheckerCallback class which should probably be where you clear the dialog (outside the isFinishing conditional).
if I can uncache it without wiping the device, as that'll be nice for when I do testing on other apps
Based on LicenseValidator.java It looks like the approval is stored in a prefs file at com.android.vending.licensing.ServerManagedPolicy in private mode. You can use the sharedpreferences editor to clear it from another place in the app.
Again I'm not a pro on this yet so I could be wrong but I think you might be able to troubleshoot your bug if you get it configured right.

Categories

Resources