i would like to use apigee android sdk in android app. By using android sdk, I would like to connect apigee end point proxy but api proxy has got Oauth 2.0 verification. How to access our proxy?
//Create client entity
String ORGNAME = "your-org";
String APPNAME = "your-app";
ApigeeClient apigeeClient = new ApigeeClient(ORGNAME,APPNAME);
DataClient dataClient = apigeeClient.getDataClient();
String type = "item"; //entity type to be retrieved
Map queryString = null; //we don't need any additional query parameters, in this case
//call getCollectionAsync to initiate the asynchronous API call
dataClient.getCollectionAsync(type, queryString, new ApiResponseCallback() {
//If getEntitiesAsync fails, catch the error
#Override
public void onException(Exception e) {
// Error
}
//If getCollectionAsync is successful, handle the response object
#Override
public void onResponse(ApiResponse response) {
try {
if (response != null) {
// Success
}
} catch (Exception e) { //The API request returned an error
// Fail
}
}
});
There is currently no support for OAuth in the Android SDK.
Related
I'm calling SafetyNet Api using Google Client but it not responding the correct response.
SafetyNet.SafetyNetApi.attest(mGoogleApiClient, generateNonce())
.setResultCallback(new ResultCallback<SafetyNetApi.AttestationResult>() {
#Override
public void onResult(SafetyNetApi.AttestationResult result) {
Status status = result.getStatus();
String data = decodeJws(result.getJwsResult());
if (status.isSuccess()) {
// Indicates communication with the service was successful.
// Use result.getJwsResult() to get the result data.
} else {
// An error occurred while communicating with the service.
}
}
});
I'm getting below error message in result method.
Status{statusCode=NETWORK_ERROR, resolution=null}
Any kind of help would be highly appreciated.
This doesn't work because you are using SafetyNetApi, which is no longer supported.
Starting with Google Play Services 11.0.0, you should now get an API key, and use SafetyNetClient instead.
You may also want to take a look at 10 things you might be doing wrong when using the SafetyNet Attestation API.
First you have to generate nonce by following method
private static byte[] getRequestNonce() {
String data = String.valueOf(System.currentTimeMillis());
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
byte[] bytes = new byte[24];
Random random = new Random();
random.nextBytes(bytes);
try {
byteStream.write(bytes);
byteStream.write(data.getBytes());
}catch (IOException e) {
return null;
}
return byteStream.toByteArray();
}
Afterwords use safety net client attestation api
SafetyNet.getClient(context).attest(nonce, <API KEY>).addOnSuccessListener(new OnSuccessListener<SafetyNetApi.AttestationResponse>() {
#Override
public void onSuccess(SafetyNetApi.AttestationResponse attestationResponse) {
// parse response
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// An error occurred while communicating with the service.
}
});
}
Reference: Sample Code Offline verification
Sample Code Online verification using google api
I have an android app that needs to make a call to a asp.net core web api server.
I am using RestSharp to make the request.
Here is the code generating the request:
public LoginResponse SignInWithGoogle(string token)
{
//Api request for token
RestRequest request = new RestRequest("login/google", Method.POST);
request.AddJsonBody(new { Token = token });
//request.AddParameter("token", token, ParameterType.GetOrPost);
var response = restClient.Execute<LoginResponse>(request);
if (response.ErrorException != null)
{
throw new Exception("The APi request failed. See inner exception for more details", response.ErrorException);
}
AuthenticationToken = response.Data.token;
restClient.Authenticator = authenticator;
return response.Data;
}
Here is the web api code:
[AllowAnonymous]
[HttpPost]
[Route("google")]
public IActionResult GoogleLogin([FromBody] GoogleLoginDto data)
{
GoogleJsonWebSignature.Payload payload;
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
SigningCredentials creds = new SigningCredentials(Global.symmetricSecurityKey, SecurityAlgorithms.HmacSha256);
//Try to validate the Google token.
try
{
payload = GoogleJsonWebSignature.ValidateAsync(data.Token).Result;
}
catch (Exception e)
{
return Unauthorized();
}
...
}
GoogleLoginDto contains one property Token that is public.
The problem is that I get a 404. It seems to me that the JSON in the request is not being serialized to GoogleLoginDto but I can't find out why... I'm guessing because the API can't find the data field and so thinks i'm asking for a route that doesn't exist...
I also tried doing request.AddParameter("token", token, ParameterType.GetOrPost); as you can see, but I get an exception saying that Content-Type can't be null.
I thought about adding the Content-Type header but that seems ridiculous because RestSharp is supposed to determine that automatically...
Can anyone see anything I'm missing here? Thanks.
The API is unable to map the provided URL to a controller action. That is what it is 404 Not Found. Nothing to do with the data. It is the URL.
Given that the desired URL is login/google, ensure that the target controller has the proper routes defined that would allow the request to be mapped to the correct actions.
[Route("login")] // Route prefix
public class LoginController : Controller {
[AllowAnonymous]
[HttpPost("google")] // Matches POST login/google
public async Task<IActionResult> GoogleLogin([FromBody] GoogleLoginDto data) {
if(ModelState.IsValid) {
GoogleJsonWebSignature.Payload payload;
var tokenHandler = new JwtSecurityTokenHandler();
var creds = new SigningCredentials(Global.symmetricSecurityKey, SecurityAlgorithms.HmacSha256);
//Try to validate the Google token.
try {
payload = await GoogleJsonWebSignature.ValidateAsync(data.Token);
} catch (Exception e) {
return Unauthorized();
}
return Ok();
}
return BadRequest();
}
}
I need a working example for a custom API for Microsoft Azure App Service.
I could not get any useful or working information/examples for that, or they just show each time different approaches which are outdated?!?!
For now I have a working table controller which gets information from database and returns it back to my Android client. Now I need to define a custom API Controller to get a string back. In the examples they are all sending an object to the service in order to get an object back. I do not want to send anything to the API, just retrieve some information back from a GET Request.
Regards
// EDIT - Added / edited client / server code to Post a String.
You can use the following code to do a GET request on the auto generated API controller Visual Studio creates (ValuesController).
private void getStringFromAzure() throws MalformedURLException {
// Create the MobileService Client object and set your backend URL
String yourURL = "https://yourApp.azurewebsites.net/";
MobileServiceClient mClient = new MobileServiceClient(yourURL, this);
// Your query pointing to yourURL/api/values
ListenableFuture<JsonElement> query = mClient.invokeApi("values", null, GetMethod, null);
// Callback method
Futures.addCallback(query, new FutureCallback<JsonElement>() {
#Override
public void onSuccess(JsonElement jsonElement) {
// You are expecting a String you can just output the result.
final String result = jsonElement.toString();
// Since you are on a async task, you need to show the result on the UI thread
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(mContext, result, Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onFailure(Throwable throwable) {
Log.d(TAG, "onFailure: " + throwable.getMessage());
}
});
}
public void sendString(final String someString) throws MalformedURLException {
// Your query pointing to /api/values/{String}
ListenableFuture<JsonElement> query = mClient.invokeApi("values/" + someString, null, PostMethod, null);
// Callback method
Futures.addCallback(query, new FutureCallback<JsonElement>() {
#Override
public void onSuccess(JsonElement jsonElement) {
// You are expecting a String you can just output the result.
final String result = jsonElement.toString();
}
#Override
public void onFailure(Throwable throwable) { }
});
}
The backend API: (ValuesController)
{
// Use the MobileAppController attribute for each ApiController you want to use
// from your mobile clients
[MobileAppController]
public class ValuesController : ApiController
{
// GET api/values
public string Get()
{
return "Hello World!";
}
// POST api/values/inputString
public string Post(string inputString)
{
return inputString;
}
}
}
You can also send parameters along in the following way:
List<Pair<String, String>> parameters = new ArrayList<>();
parameters.add(new Pair<>("name", "John"));
parameters.add(new Pair<>("password", "fourwordsalluppercase"));
ListenableFuture<JsonElement> query = client.invokeApi("yourAPI", PostMethod, parameters);
Or as json in the body:
JsonObject body = new JsonObject();
body.addProperty("currentPassword", currentPassword);
body.addProperty("password", password);
body.addProperty("confirmPassword", confirmPassword);
ListenableFuture<JsonElement> query = mClient.invokeApi("yourAPI", body, PostMethod, null);
Based on my understanding, I think there are two parts in your question which include as below. And I think you can separately refer to two sections to get the answers and write your own example.
How to define a custom API on Azure Mobile App to retrieve data from database? Please refer to the section Custom APIs to know how to do with Azure Mobile App backend.
How to call a custom API from Android App? Please refer to the section How to: Call a custom API to know how to do with Android SDK.
I want to enable server-side Calendar API access for my android app.
I have followed the steps given here .
I am getting a null value for the authorization code.
I think I am giving wrong values for 'scope' field and the 'server_client_id' field.
Please give me an example showing correct fields values for 'scope' and 'server_client_id' in the getToken() method.
Thanks for any help.
PS- I have used google+ sign in for android given here for connecting to a google account.
EDIT- Here is my code. I have given the OAuth 2.0 scope for the Google Calendar API in the scope field.
I have taken Client ID for Android application from Developers Console and put in 'serverClientID' field. This is probably where I am wrong. I don't know how to get Server's Client ID which is required by the
public class AsyncGetAuthToken extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... params) {
Bundle appActivities = new Bundle();
appActivities.putString(GoogleAuthUtil.KEY_REQUEST_VISIBLE_ACTIVITIES,
"MainActivity");
String scopeString = "https://www.googleapis.com/auth/calendar.readonly";
String serverClientID = CLIENT_ID;
String scopes = "oauth2:server:client_id:" + serverClientID + ":api_scope:" + scopeString;
String code = null;
try {
code = GoogleAuthUtil.getToken(
MainActivity.this, // Context context
Plus.AccountApi.getAccountName(mGoogleApiClient), // String accountName
scopes, // String scope
appActivities // Bundle bundle
);
} catch (IOException transientEx) {
// network or server error, the call is expected to succeed if you try again later.
// Don't attempt to call again immediately - the request is likely to
// fail, you'll hit quotas or back-off.
return null;
} catch (UserRecoverableAuthException e) {
// Requesting an authorization code will always throw
// UserRecoverableAuthException on the first call to GoogleAuthUtil.getToken
// because the user must consent to offline access to their data. After
// consent is granted control is returned to your activity in onActivityResult
// and the second call to GoogleAuthUtil.getToken will succeed.
startActivityForResult(e.getIntent(), AUTH_CODE_REQUEST_CODE);
return null;
} catch (GoogleAuthException authEx) {
// Failure. The call is not expected to ever succeed so it should not be
// retried.
return null;
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
}
And in my onActivityResult, I look for the Auth Code
if (requestCode == AUTH_CODE_REQUEST_CODE) {
if (responseCode == RESULT_OK){
Bundle extra = intent.getExtras();
String oneTimeToken = extra.getString("authtoken");
Log.d("LOG", "one time token" + oneTimeToken);
}
}
I'm trying out a GAE based backend using the sample code on the page below:
https://github.com/GoogleCloudPlatform/gradle-appengine-templates/tree/master/GcmEndpoints
Have been able to deploy the backend and I can view & execute the APIs on API explorer through appspot.com link - project-id.appspot.com
When I execute the client app (Android based) and call
regService.register(regId).execute();
On the server side I get the following log entry on Google Developer Console -
"POST /registration/v1/registerDevice/APA91bHCCvjkMFdvf6YHh_rbdqdKMYoRnwm6iswQtTpztwCfNVWq_7xwSq1y9naiipYmfTrREInybypeLb5mc7LCzYGBSpC9jFM-Co_6xGUBiEjLyo1UT375ak7p0nrOiTdHFNwW7r31WYQJP7ojigRLxBTYvST4XTeNIufD6GHb3SbDFGl1hsc HTTP/1.1" 404 0 - "20773xxxxxxx Google-HTTP-Java-Client/1.17.0-rc (gzip)" "verlllll-auyyyy-zzz.appspot.com" ms=19 cpu_ms=0 app_engine_release=1.9.7 trace_id=ddfbcf4e13e27e2aa2a6c5e77bb8cc6f
where:
registration/v1/registerDevice/ are API/version/Method of the backend service
APA91bHCCvjkMFdvf6YHh_rbdqdKMYoRnwm6iswQtTpztwCfNVWq_7xwSq1y9naiipYmfTrREInybypeLb5mc7LCzYGBSpC9jFM-Co_6xGUBiEjLyo1UT375ak7p0nrOiTdHFNwW7r31WYQJP7ojigRLxBTYvST4XTeNIufD6GHb3SbDFGl1hsc
.. is the device registration id returned by gcm.register(SENDER_ID); gcm is of type GoogleCloudMessaging
20773xxxxxxx or SENDER_ID is the Project number provided on the Google Developer Console.
& verlllll-auyyyy-zzz.appspot.com is the Project Id.
Can you please tell me why am I getting HTTP/1.1 404 in the response?
Thanks in advance..
Sharing the building of regService --
public class GcmRegistrationAsync extends AsyncTask<Context, Void, String> {
private Registration regService; // A Stub API from Server
private GoogleCloudMessaging gcm;
private Context context;
// TODO: change to your own sender ID to Google Developers Console project
// number, as per instructions above
private static final String SENDER_ID = "20773xxxxxxx";
public void GcmRegistrationAsyncTask(int i) {
Registration.Builder builder = new Registration.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null)
// Need setRootUrl and setGoogleClientRequestInitializer only for local testing,
// otherwise they can be skipped
.setRootUrl("https://verlllll-auyyyy-zzz.appspot.com")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
#Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
i = this.test();
builder.setApplicationName(SENDER_ID);
regService = builder.build();
}
public int test () {
return 1;
}
#Override
protected String doInBackground(Context... params) {
int i = params.length;
context = (Context) params[0];
String msg = "test";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
String regId = gcm.register(SENDER_ID);
msg = "Device registered, registration ID=" + regId;
// You should send the registration ID to your server over HTTP,
// so it can use GCM/HTTP or CCS to send messages to your app.
// The request to your server should be authenticated if your app
// is using accounts.
regService.register(regId).execute();
} catch (IOException ex) {
ex.printStackTrace();
msg = "Error: " + ex.getMessage();
}
return msg;
}
}
In MyActivity.java
protected void onCreate(Bundle savedInstanceState) {
:
:
gcmRegistrationAsync = new GcmRegistrationAsync();
gcmRegistrationAsync.GcmRegistrationAsyncTask(1);
gcmRegistrationAsync.execute(this);
}
To connect to an endpoint you have to connect with https, if you connect with http like you did (in your setUrl) then you get the 404 error.
Also your code can probably look more like :
Registration.Builder builder = new Registration.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null);
The rootUrl doesn't need be set, by default it uses your appspot location, when running locally, it's useful to direct the endpoint to your devapp server (app engine local testing server).
The code that disables compression is also just used to be compatible with the devapp server