uri.getQueryParameter() returning null value - java

I have the following code in a class:
#Override
public boolean shouldOverrideUrlLoading(WebView wv, String url)
{
if (url.startsWith(Constants.OAUTH_REDIRECT))
{
Uri uri = Uri.parse(url);
String state = uri.getQueryParameter("state");
if (state != null && state.equals(Constants.randString))
{
String error = uri.getQueryParameter("error");
if (error != null && error.length() > 0)
{
if (error.equals("access_denied"))
{
//user chose not to login
Log.d("oAuthView", "Access Denied");
finish();
}
else
{
Toast.makeText(getApplicationContext(), error, Toast.LENGTH_LONG).show();
finish();
}
}
//Go back to MainActivity with authorization code
Intent resultIntent = getIntent();
resultIntent.putExtra("authCode", uri.getQueryParameter("code"));
setResult(RESULT_OK, resultIntent);
finish();
return true;
}
}
return false;
}
For some reason I am getting a null value when trying to capture "state", even though I have made sure that it is in the URL. This means the app never enters the if statement that follows. I have also checked and the same thing happens when I try to capture the authCode. Any ideas on why they would return null?
Edit: For some reason when I try an alternative URL scheme, it parses correctly.
The URL I need to parse but doesn't work:
http://www.website.com/#access_token=tokenstringhere&token_type=bearer&state=randomStringHere&expires_in=3600&scope=identity+submit
A similar URL that does work:
http://www.website.com/?state=cnmdr6&code=tokenStringHere
What would cause the first parse to fail but the second one to properly parse?

If someone is looking for solution.
Your url is invalid because you missed the question sign ? before query in your url.
Your url should look like this:
http://www.website.com/?access_token=tokenstringhere&token_type=bearer&state=randomStringHere&expires_in=3600&scope=identity+submit
Please check the documentation.

Related

Google Play Games API returns SIGN_IN_REQUIRED

I'm trying to implement automating player sign in to Google Play games in my Android app. Firstly, as mentioned here, I try to sign in silently:
#Override
protected void onResume() {
super.onResume();
signInSilently();
}
private void signInSilently() {
mGoogleSignInClient.silentSignIn().addOnCompleteListener(this, task -> {
if (task.isSuccessful())
//everything ok
else {
final ApiException exception = (ApiException) task.getException();
if (BuildConfig.DEBUG)
Log.d(TAG, "Silent Sign In failure: ", exception);
if (exception.getStatusCode() == CommonStatusCodes.SIGN_IN_REQUIRED)
startSignInIntent();
}
});
Every time I got an exception with code 4 (CommonStatusCodes.SIGN_IN_REQUIRED). So in this case I try to sign in with ui:
private void startSignInIntent() {
startActivityForResult(mGoogleSignInClient.getSignInIntent(), RC_SIGN_IN);
}
#Override
protected void onActivityResult(int request, int response, Intent data) {
super.onActivityResult(request, response, data);
if (request == RC_SIGN_IN) {
final GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if (result.isSuccess()) {
// everything is ok, get account from result
} else if (result.getStatus().hasResolution()) {
resolveManually(result.getStatus());
} else {
String message = result.getStatus().getStatusMessage();
if (BuildConfig.DEBUG)
Log.d(TAG, "status code" + result.getStatus().getStatusCode());
if (message == null || message.isEmpty()) {
message = "other error";
}
new AlertDialog.Builder(this).setMessage(message)
.setNeutralButton(android.R.string.ok, null).show();
}
}
}
And here everytime I get message with other error! The status code is again 4 (CommonStatusCodes.SIGN_IN_REQUIRED). How can I get this code when I try to sign in using intent? So, my app are in infinite loop because onResume is called everytime my activity loads after receiving a result, and everytime the status code is CommonStatusCodes.SIGN_IN_REQUIRED. So, where is the problem?
In Google samples there is no information how can I handle automatic sign in, only manual with sign in buttons. But google recommends to use automating sign in. Please help anybody to understand what is wrong here.
You must not start the login screen from your onResume method. It is a silent login which works if the user wants it (by tapping a button). That's why the examples show it only this way.
There was wrong OAuth 2.0 client ID for the debug version of my app! Don't know why there is SIGN_IN_REQUIRED status code in this situation, it is really confusing!

Best way to handle error and success messages copy texts from back-end?

I have an Android application and right now I am managing error and success messages in strings.xml resource file. Now in case if I want to change these messages I need to make changes in strings.xml file and give an app update in play-store, which is a bit overhead. Instead, I want these messages to be managed from server side (back-end) so that they can be changed without any update. Can anyone please suggest me the best way to achieve this.
If you are use Volley then this is helpfil for you
VolleyError is really just an extended Exception, so Exception.getMessage() likely wouldn't return what you are looking for unless you override the parsing methods for parsing your VolleyError in your extended Request class. A really basic way to handle this would be to do something like:
//In your extended request class
#Override
protected VolleyError parseNetworkError(VolleyError volleyError){
if(volleyError.networkResponse != null && volleyError.networkResponse.data != null){
VolleyError error = new VolleyError(new String(volleyError.networkResponse.data));
volleyError = error;
}
return volleyError;
}
}
If you add this to your extended Request classes, your getMessage() should at least not return null. I normally don't really bother with this, though, since it's easy enough to do it all from within your onErrorResponse(VolleyError e) method.
You should use a JSON library to simplify things -- I use Gson for example or you could use Apache's JSONObjects which shouldn't require an additional external library. The first step is to get the response JSON sent from your server as a String (in a similar fashion to what I just demonstrated), next you can optionally convert it to a JSONObject (using either apache's JSONObjects and JsonArrays, or another library of your choice) or just parse the String yourself. After that, you just have to display the Toast.
Here's some example code to get you started:
public void onErrorResponse(VolleyError error) {
String json = null;
NetworkResponse response = error.networkResponse;
if(response != null && response.data != null){
switch(response.statusCode){
case 400:
json = new String(response.data);
json = trimMessage(json, "message");
if(json != null) displayMessage(json);
break;
}
//Additional cases
}
}
public String trimMessage(String json, String key){
String trimmedString = null;
try{
JSONObject obj = new JSONObject(json);
trimmedString = obj.getString(key);
} catch(JSONException e){
e.printStackTrace();
return null;
}
return trimmedString;
}
//Somewhere that has access to a context
public void displayMessage(String toastString){
Toast.makeText(context, toastString, Toast.LENGTH_LONG).show();
}

Android, Glide Image Loading Library: NullPointerException, ProviderInfo

Just getting into the Glide image loading library for Android. Currently working with some code from here:
https://github.com/bumptech/glide/issues/459
My full project is here is you want to look at it:
https://github.com/mhurwicz/glide02
I'm getting the following exception when I run the app in the emulator in Android Studio:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
This is the key statement in MainActivity:
new ShareTask(this).execute("http://thelink");
(thelink is actually goo.gl/gEgYUd -- couldn't leave that in above because stackoverflow doesn't allow URL shorteners. )
Here is my code for the ShareTask class
class ShareTask extends AsyncTask<String, Void, File> {
private final Context context;
public ShareTask(Context context) {
this.context = context;
}
#Override protected File doInBackground(String... params) {
String url = params[0]; // should be easy to extend to share multiple images at once
try {
return Glide
.with(context)
.load(url)
.downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.get() // needs to be called on background thread
;
} catch (Exception ex) {
Log.w("SHARE", "Sharing " + url + " failed", ex);
return null;
}
}
#Override protected void onPostExecute(File result) {
if (result == null) { return; }
Uri uri = FileProvider.getUriForFile(context, context.getPackageName(), result);
share(uri); // startActivity probably needs UI thread
}
private void share(Uri result) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/jpeg");
intent.putExtra(Intent.EXTRA_SUBJECT, "Shared image");
intent.putExtra(Intent.EXTRA_TEXT, "Look what I found!");
intent.putExtra(Intent.EXTRA_STREAM, result);
context.startActivity(Intent.createChooser(intent, "Share image"));
}
}
Using debug, it seems I may be running into trouble at the get() statement. For one thing, the width and the height are very large negative numbers. (See the code highlighted in green below.) Then the get() statement returns null. (See the code highlighted in red below.)
Thanks in advance for any help you can provide!
The NPE is coming from FileProvider.getUriForFile because you're passing in the wrong authority. You declared android:authorities="com.example.fileprovider" in the manifest, but you're using the package name at the call. This fails to resolve the info in FileProvider.parsePathStrategy. Match those two strings up and you'll be good to go.
The easiest fix is to use android:authorities="${applicationId}", this leads to 0 hardcoded strings, so you can keep using context.getPackageName().
Regarding your concerns during debug:
Target.SIZE_ORIGINAL is declared to be MIN_VALUE, hence the large number
it's not returning null, IDEA is just confused about where it is in the method, that return null; shouldn't be executed if it fails in the FileProvider code.
doGet(null): null is the timeout here, it's guarded properly in code
I've run the app and weirdly I got a log line saying
W/SHARE: Sharing http://... failed
but not a stack trace, which is weird, because ex cannot be null in a catch!

Parse Password Reset

I am new to parse, trying to reset a password by:
user.requestPasswordResetInBackground(password.getText().toString(), new RequestPasswordResetCallback() {
#Override
public void done(com.parse.ParseException e) {
if (e == null) {
Toast.makeText(getApplicationContext(), "Password rest email has been sent to your inbox", Toast.LENGTH_LONG).show();
}else if(e.getCode()== com.parse.ParseException.INVALID_EMAIL_ADDRESS){
Toast.makeText(getApplicationContext(),"Email not found",Toast.LENGTH_LONG).show();
}
}
});
Everything is fine an email will be sent to the inbox, by how I can tell Parse to validate the password at least 8 characters (it's taking everything even 1234)
Thank you
I think you can write a cloud code, so before _User object is updated, check user.get("password").length.
Something Like this:
PF.Cloud.beforeSave("_User", function(request, response) {
//Prototype linking
var user = request.object;
if (user.get("password").length >= 8) {
response.success();
} else {
response.error("Password too short");
}
});
For more information, please visit the reference: Cloud Code

HttpPost and HttpRequest multiple responses

I have a Http Post
try {
String response1 = null;
response1 = CustomHttpClient.executeHttpPost(
"http://giveaway.synamegames.com/appfiles/login.php",
postParameters);
String res = response1.toString();
// res = res.trim();
res = res.replaceAll("\\s+", "");
if (res.equals("2350") && checkboxv.equals("1")) {
Intent login = new Intent(this, MainMenuActivity.class);
login.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(login);
SavePreferences("lu", et_username.getText().toString());
SavePreferences("lp", et_pass.getText().toString());
SavePreferences("cbauto", "1");
} else if (res.equals("2350") && checkboxv.equals("0")) {
Intent login = new Intent(this, MainMenuActivity.class);
login.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(login);
SavePreferences("lu", "");
SavePreferences("lp", "");
SavePreferences("cbauto", "0");
} else if (res.equals("1000")) {
Toast.makeText(this, "Incorrect version. Please update.",
Toast.LENGTH_SHORT).show();
} else if (res.equals("588")) {
Toast.makeText(this, "Incorrect Password or Username.",
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,
"Server Error. Please try again later.",
Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
}
If my response is 1000, 2350, etc. it'll give the android phone a specific response. However I want my database to give android database information. In my situation I have
players register and enter in their name, email, username, and password. Upon login I want the phone to retrieve the name the user assigned when they created their account. For security reasons I can't store this information on the phone. I could have multiple HTTP Posts but that would just slow the application down. My question is...
Is there any possible way I can retrieve multiple responses and put those responses into different Strings without having to do another http post?
If you are designing the server side also, what I would do is basically returning the profile information as part of the response in JSON format. You could use JSONObject from Android to parse the JSON response from your server. So your response String for successful login would look like
{
"response" : {
"responseCode" : 2350,
"userProfile" : {
"name" : "Me",
"email" : "me#me.com"
}
}
}
And for failed response
{
"response" : {
"responseCode" : 588
}
}
This way, you don't have to make 2 http calls and would save you from another trip to the server

Categories