I want to integrate google photos api in android,I have done google sign in process but I am not able to get access token because i was getting error in FixedCredentialsProvider.create method while passing parameter.
PhotosLibrarySettings settings =
PhotosLibrarySettings.newBuilder()
.setCredentialsProvider(
FixedCredentialsProvider.create(/ Add credentials here. /))
.build();
try (PhotosLibraryClient photosLibraryClient =
PhotosLibraryClient.initialize(settings)) {
// Create a new Album with at title
Album createdAlbum = photosLibraryClient.createAlbum("My Album");
// Get some properties from the album, such as its ID and product URL
String id = album.getId();
String url = album.getProductUrl();
} catch (ApiException e) {
// Error during album creation
}
I was able to get a solutions to the issue
UserCredentials.newBuilder()
.setClientId("your client id")
.setClientSecret("your client secret")
.setAccessToken("Access Token")
.build()
You can pass this UserCredentials Object to ` FixedCredentialsProvider.create())
Get access token using
val client = OkHttpClient()
val requestBody = FormEncodingBuilder()
.add("grant_type", "authorization_code")
.add("client_id", "")
.add("client_secret", "")
.add("redirect_uri", "")
.add("code", "yourweb server id)
.build()
val request = Request.Builder()
.url("https://www.googleapis.com/oauth2/v4/token")
.post(requestBody)
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(request: Request, e: IOException) {
}
#Throws(IOException::class)
override fun onResponse(response: Response) {
try {
val jsonObject = JSONObject(response.body().string())
mTokenExpired = SystemClock.elapsedRealtime() + jsonObject.optLong("expires_in") * 1000
accessTokenObservable.postValue(Resource.success("",jsonObject.optString("access_token")))
} catch (e: JSONException) {
e.printStackTrace()
}
}
})
https://github.com/erickogi/AndroidGooglePhotosApi
Hope it helps
Related
Dio request for login authentication
Future<String?> authentication(String mobileNumber, String password, Dio dio) async {
dynamic data = {
"username": mobileNumber,
"password": password,
"grant_type": "password",
"client_id": "client_id"
};
try {
final response = await _dio.post(baseurl,
data: data,
options: Options(headers: {
"Content-Type": "application/x-www-form-urlencoded"
})); //'Authorization': 'Bearer $token
if (response.statusCode == 200) {
accessToken = response.data["access_token"];
refreshToken = response.data["refresh_token"];
Fluttertoast.showToast(msg: "Successfully Logged in");
return accessToken;
}
}on DioError catch (e) {
Fluttertoast.showToast(msg: "Something went wrong");
return e.toString();
}
return accessToken;
}
**Unit testing **
MockDio mockDio = MockDio();
test("if authentication successfull token will return ", () async {
when(mockDio.post(Apiservices().baseurl)).thenAnswer((_)async =>*need return a response????*
);
expect(await service.authentication("username", "password", mockDio),
isA<String>());
});
I need to check the login auth testing using dio and mockito packages.
It will return a token.
I am not able to do the mocking.
Please give a details example of this.
or give me some reference
Try something like this:
test(
'Given: Fake login request with username and password,'
'When: Mock login API,'
'Then: Successful response from mock api', () async {
// arrange
when(
mockDio.post(
Apiservices().baseurl
),
).thenAnswer((realInvocation) async {
return Response(jsonEncode(loginSuccessResponse), 200); //this will create a response for your api request
});
// act, this will return a fake api response, we created above
final resp = await _networkCallMock.post(
Apiservices().baseurl
);
// assert, actualResponse we mocked to get from api call, have a actual
// response as expectedResponse, and compare it.
final actualResponse = LoginResponse.fromJson(jsonDecode(resp.body));
final expectedResponse = LoginResponse.fromJson(loginSuccessResponse);
expect(
actualResponse,
expectedResponse,
);
});
We have both asynchronous and synchronous calls implemented using retrofit and Either to map success/error. After adding the network interceptor asynchronous calls are returning bad responses(works fine on postman). I have tried adding a general error JSON response thinking Either is not able to catch the exceptions but still no luck. please suggest a fix or new approach
Interceptorclass -
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
try {
val response = chain.proceed(request)
val bodyString = response.body!!.string()
return response.newBuilder()
.body(ResponseBody.create(response.body?.contentType(), bodyString))
.build()
} catch (e: Exception) {
e.printStackTrace()
var msg = ""
when (e) {
is SocketTimeoutException -> {
msg = "Timeout - Please check your internet connection"
}
is UnknownHostException -> {
msg = "Unable to make a connection. Please check your internet"
}
is ConnectionShutdownException -> {
msg = "Connection shutdown. Please check your internet"
}
is IOException -> {
msg = "Server is unreachable, please try again later."
}
is IllegalStateException -> {
msg = "${e.message}"
}
else -> {
msg = "${e.message}"
}
}
return Response.Builder()
.request(request)
.protocol(Protocol.HTTP_1_1)
.code(999)
.message(msg)
.body(ResponseBody.create(null, "{${e}}")).build()
}
}`
client - val client1 = OkHttpClient.Builder() .addInterceptor(Interceptor) .build()
ServiceConfig.kt - Adding client as below
#Singleton
#Provides
#BaseUrl(BaseUrlType.SERVICES)
fun provideSupportRetrofit(
jsonConverters: Converter.Factory,
#HttpClient(ClientType.OAUTH) client: Call.Factory
): ServicesFactory {
return fakeServicesFactory ?: Retrofit.Builder()
.callFactory(client)
.baseUrl(baseUrlServices)
.addCallAdapterFactory(EitherCallAdapterFactory())
.addConverterFactory(EitherConverterFactory())
.addConverterFactory(FiberErrorConverterFactory())
.addConverterFactory(jsonConverters)
.addConverterFactory(primitiveTypeConverters)
.client(client1)
.build()
.asFactory
}
EitherCovertor.kt -
`override fun enqueue(callback: Callback<Either<*, *>>) {
call.enqueue(object : Callback<Either<*, *>> {
override fun onResponse(call: Call<Either<*, *>>, response: Response<Either<*, *>>) {
callback.onResponse(this#EitherCall, response.asEither)
}
}
override fun onFailure(call: Call<Either<*, *>>, t: Throwable) {
when (t) {
is Error -> {
Timber.e("Failure Error from API")
callback.onFailure(call, t)
}
else -> callback.onResponse(this#EitherCall, t.asEither)
}
}
})
}`
To get the error text in the header section
headers["Accept"] = "application/json"
and process the error in json form, this way worked for me
Response.ErrorListener { error: VolleyError? ->
if (error is TimeoutError || error is NoConnectionError) {
Constants.checkInternet(context)
} else if (error is ServerError) {
val responseBody = String(error.networkResponse.data, Charsets.UTF_8)
val errorMsg: String =
JSONObject(responseBody).getJSONObject(TAG_META).getJSONObject(
TAG_STATUS)
.getString(TAG_MESSAGE)
Toast.makeText(context, errorMsg + "", Toast.LENGTH_SHORT)
.show()
Log.e("responseBody", responseBody)
Log.e("errorMsg", errorMsg)
}
Loading.hide(loading)
}
fun getTimeOutInterceptor(): Interceptor {
return Interceptor {
val request: Request = it.request()
val response = it.proceed(request)
try {
val content: String? = response.body()?.string()
response.newBuilder().body(ResponseBody.create(response.body()?.contentType(), content)).build()
} catch (exception: IOException) {
// Toast.makeText( BaseActivity.baseContext , "Time Out :)" , Toast.LENGTH_LONG).show()
Log.d("RetrofitClientInstance", "TimeOutFRomout")
}
response
}
}
1 .I do not understand the following
proceed(request) -> does not call HTTP server ,and send request
response.newBuilder().body(ResponseBody.create(response.body()?.contentType(), content)).build() -> why he rebuild
2 does multiple proceed(request) make it slow
3 how this will handle timeout
I'm using Firebase Cloud Functions library on Android, and using getHttpsCallable to call a cloud function.
The problem is that the function needs 10-15 seconds to return the result back to the client, so the client throws an exception java.net.SocketTimeoutException: timeout.
Code
// Create the arguments to the callable function.
Map<String, Object> data = new HashMap<>();
data.put("info", info);
mFunctions.getHttpsCallable(function)
.call(data)
.continueWith(new Continuation<HttpsCallableResult, String>() {
#Override
public String then(#NonNull Task<HttpsCallableResult> task) {
// This continuation runs on either success or failure, but if the task
// has failed then getResult() will throw an Exception which will be
// propagated down.
if (task.isSuccessful()) {
String result = (String) task.getResult().getData();
Log.v(Constants.LOG_TAG, result);
return result;
} else {
// The condition never was true, always logs the exception.
Exception e = task.getException();
Log.e(Constants.LOG_TAG, "Failed to join multiplayer room.", e);
return null;
}
}
});
How can I change the timeout so the client would wait more before throwing the exception?
Note. I'm not using OkHttp, Retrofit or the default system Networking functions, I'm using Firebase Cloud Functions library (getHttpsCallable) to call the function.
firebase-functions version 16.3.0, released 15 Mar 2019, adds the ability to configure the timeout.
I had same issue, so I called https functions with OkHttp instead of getHttpsCallable as a workaround.
The protocol of https.onCall is public.
https://firebase.google.com/docs/functions/callable
The code of calling https functions with OkHttp is here.
https://github.com/ryuta46/firebase-callable-okhttp/blob/56adc5e29a35bdb3b355c14d734e6145da4b6809/android/app/src/main/java/com/ttechsoft/okhttp_callable/MainActivity.kt#L184-L239
Editied.
The code of essential part is below.
private fun callWithOkHttp(functionName: String) {
val idToken = idToken ?: return
val instanceId = instanceId ?: return
val projectId = FirebaseApp.getInstance()?.options?.projectId ?: return
val url = "https://us-central1-$projectId.cloudfunctions.net/$functionName"
val jsonData = JSONObject()
jsonData.put("text", "inputText")
val json = JSONObject()
json.put("data", jsonData)
val requestBody = RequestBody.create(JSON, json.toString())
val request = Request.Builder()
.url(url)
.post(requestBody)
.addHeader("Authorization", "Bearer $idToken")
.addHeader("Firebase-Instance-ID-Token", instanceId)
.build()
val okHttpClient = OkHttpClient.Builder()
.connectTimeout(1 , TimeUnit.MINUTES)
.readTimeout(1, TimeUnit.MINUTES)
.writeTimeout(1, TimeUnit.MINUTES)
.build()
Log.i(TAG, "Start Okhttp")
okHttpClient.newCall(request).enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
if (!response.isSuccessful) {
val message = response.body()?.string() ?: "Network Error"
runOnUiThread {
textOkHttpResult.text = message
}
return
}
runOnUiThread {
textOkHttpResult.text = "OK"
}
val responseBody = response.body()
Log.i(TAG, responseBody?.string())
}
override fun onFailure(call: Call, e: IOException) {
val message = e.message ?: "Unknown Network error"
runOnUiThread {
textOkHttpResult.text = message
}
}
})
}
I am trying to fetch google contacts for a user via oAuth2 mechanism. I am following this tutorial - https://developers.google.com/identity/sign-in/web/server-side-flow
I have javascript code that calls start() on pageload -
function start() {
gapi.load('auth2', function() {
auth2 = gapi.auth2.init({
client_id: 'SOME_CLEINT_ID',
scope: 'https://www.googleapis.com/auth/contacts.readonly'
});
});
}
and
auth2.grantOfflineAccess().then(signInCallback);
and then -
function signInCallback(authResult) {
if (authResult['code']) {
var callback = function(data){
data = JSON.parse(data);
console.log(data);
};
callAjax({action: 'saveGmailAuth', gaccesscode: authResult['code']}, callback, true);
} else {
// There was an error.
}
}
This front end code calls my backend Java web servlet, which tries to get access token -
String authCode = request.getParameter("gaccesscode");
String REDIRECT_URI = "";
String CLIENT_SECRET_FILE = "G:/eclipse_proj/GoogleContacts/CLIENT_JSON_FILE.json";
GoogleClientSecrets clientSecrets;
try {
clientSecrets = GoogleClientSecrets.load(JacksonFactory.getDefaultInstance(),
new FileReader(CLIENT_SECRET_FILE));
REDIRECT_URI = clientSecrets.getDetails().getRedirectUris().get(0);
GoogleAuthorizationCodeTokenRequest tokenRequest = new GoogleAuthorizationCodeTokenRequest(new NetHttpTransport(),
JacksonFactory.getDefaultInstance(), "https://www.googleapis.com/oauth2/v3/token",
clientSecrets.getDetails().getClientId(), clientSecrets.getDetails().getClientSecret(), authCode,
REDIRECT_URI);
GoogleTokenResponse tokenResponse = tokenRequest.execute();
String accessToken = tokenResponse.getAccessToken();
GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Every time I try this java code, every time it gives me error at tokenRequest.execute() -
com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
"error" : "redirect_uri_mismatch",
"error_description" : "Bad Request"
}
With REDIRECT_URI as empty string, it give another error saying - redirect_uri_not_provided.
I tried it with both "https://www.googleapis.com/oauth2/v3/token" and "https://www.googleapis.com/oauth2/v4/token"
I need help figuring this out. What am I doing wrong here?
My redirect URI is - http://localhost:8080/GoogleContacts/Callback in both json file and in developer console for oauth2.
For redirect_uri in using Google APIs,go to your Google Dev console and type what you see as is:
//you can use any port you want
http:localhost:8080/oauth2callback
oauth2callback is the key ingredient.