如您所见,我已使用我的帐户登录,并显示在 Firebase 控制台上。
当用户使用Google Sign-in登录后,函数firebaseAuthWithGoogle使用Firebase对用户进行身份验证:
private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
Log.d(TAG, "firebaseAuthWithGoogle:" + acct.getId());
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
mFirebaseAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "signInWithCredential:success");
final FirebaseUser user = mFirebaseAuth.getCurrentUser();
//This is to connect to the http server and save the user data in my MySql database
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(LoginActivity.this, new OnSuccessListener<InstanceIdResult>() {
@Override
public void onSuccess(InstanceIdResult instanceIdResult) {
String userToken = instanceIdResult.getToken();
String uid = user.getUid();
String name = user.getDisplayName();
String email = user.getEmail();
String profileUrl = user.getPhotoUrl().toString();
String coverUrl = "";
UserInterface userInterface = ApiClient.getApiClient().create(UserInterface.class);
Call<Integer> call = userInterface.signin(new LoginActivity.UserInfo(uid,name,email,profileUrl,coverUrl,userToken));
call.enqueue(new Callback<Integer>() {
@Override
public void onResponse(Call<Integer> call, Response<Integer> response) {
progressDialog.dismiss();
Toast.makeText(LoginActivity.this,"Login succesfull AFTER API CALL",Toast.LENGTH_SHORT).show();
startActivity(new Intent(LoginActivity.this,MainActivity.class));
finish();
}
@Override
public void onFailure(Call<Integer> call, Throwable t) {
progressDialog.dismiss();
Toast.makeText(LoginActivity.this,"Login failed AFTER API CALL",Toast.LENGTH_SHORT).show();
}
});
}
});
} else {
// If sign in fails, display a message to the user.
Log.w(TAG, "signInWithCredential:failure", task.getException());
}
// ...
}
});
}
函数firebaseAuthWithGoogle做的另一件事是:通过下面的代码片段连接到http Apache服务器,并将用户信息保存在MySQL users表中:
//This is to connect to the http server and save the user data in my MySql database
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(LoginActivity.this, new OnSuccessListener<InstanceIdResult>() {
@Override
public void onSuccess(InstanceIdResult instanceIdResult) {
String userToken = instanceIdResult.getToken();
String uid = user.getUid();
String name = user.getDisplayName();
String email = user.getEmail();
String profileUrl = user.getPhotoUrl().toString();
String coverUrl = "";
UserInterface userInterface = ApiClient.getApiClient().create(UserInterface.class);
Call<Integer> call = userInterface.signin(new LoginActivity.UserInfo(uid,name,email,profileUrl,coverUrl,userToken));
call.enqueue(new Callback<Integer>() {
@Override
public void onResponse(Call<Integer> call, Response<Integer> response) {
progressDialog.dismiss();
Toast.makeText(LoginActivity.this,"Login succesfull AFTER API CALL",Toast.LENGTH_SHORT).show();
startActivity(new Intent(LoginActivity.this,MainActivity.class));
finish();
}
@Override
public void onFailure(Call<Integer> call, Throwable t) {
progressDialog.dismiss();
Toast.makeText(LoginActivity.this,"Login failed AFTER API CALL",Toast.LENGTH_SHORT).show();
}
});
}
});
}
因此,在用户成功通过身份验证后,对服务器的调用失败,显然会执行以下代码行:
Toast.makeText(LoginActivity.this,"Login failed AFTER API CALL",Toast.LENGTH_SHORT).show();
我将Retrofit用作http客户端,将okhttp用作http主体拦截器,以如下方式记录http请求:
ApiClient.java
public static Retrofit getApiClient(){
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(httpLoggingInterceptor)
.build();
if(retrofit==null){
retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
因此,在模拟器上出现吐司文本“API调用后登录失败”之后,我在日志上有这个:
D/OkHttp: --> POST http://10.0.2.2/friendster/public/app/login
Content-Type: application/json; charset=UTF-8
Content-Length: 413
D/OkHttp: {"CoverUrl":"","email":"MyEmail@gmail.com","name":"Ahmed Ghrib","profileUrl":"https://lh6.googleusercontent.com/-S8l_5gZaXJ8/AAAAAAI/AAAAAAAAAAA/ACHi3rfObo6-Ta-wxrMUvcAZ8Yg/s96-c/photo.jpg","uid":"YACACYYDcGVr26N8OHuTuQlQqvU2","userToken":"ecxdtFaKldI:APA91bHb1PAA5hU6i1oMqnSsDXXkAaXNb6dynyaYmhU_soHTWmLXud6REjCpqTjsGpgdBh1NMYUqAr3SaTUWapN4v73zkvyYD2f3yegUP3H38eeU_JtH7NOSMKbF4U"}
D/OkHttp: --> END POST (413-byte body)
W/e.myapplicatio: Verification of okhttp3.internal.http.ExchangeCodec okhttp3.internal.connection.RealConnection.newCodec$okhttp(okhttp3.OkHttpClient, okhttp3.Interceptor$Chain) took 134.353ms
D/OkHttp: <-- HTTP FAILED: java.net.UnknownServiceException: CLEARTEXT communication to 10.0.2.2 not permitted by network security policy
所以我发现——这是导致错误的原因:
网络安全策略不允许与10.0.2.2进行明文通信
在经历了StackOverflow之后,我发现我需要创建这个文件:
src/main/res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">api.example.com(to be adjusted)</domain>
</domain-config>
</network-security-config>
并将其添加到清单中:
<application
---
android:networkSecurityConfig="@xml/network_security_config">
在使用Postman测试了我的数据库后,我确定问题出在我的Android项目上。
我认为这应该已经解决了这个问题。但是,我仍然有完全相同的问题。我仍然在日志中收到这个错误:
网络安全策略不允许与10.0.2.2进行明文通信
只需将这一行放到您的AndroidManifest.xml中
请对安全配置文件使用此选项:
src/main/res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!--Set application-wide security config using base-config tag.-->
<base-config cleartextTrafficPermitted="true"/>
</network-security-config>
它解决了我的问题:)
在AndroidManifest.xml中,只需使用这一行。它解决了我的问题。
<application
...
android:usesCleartextTraffic="true">
</application>
问题内容: 我正在尝试做的事情 :: 我正在尝试学习 Okhttp 在android中进行网络通话的用法 我做了什么 :: 我 在这里 阅读了他们的文档 __ 我已经在项目中下载并添加了JAR 我从 这里 使用他们的示例代码 __ MyCode :: MainActivity.java 我面临的错误 :: 在这一行中, 我收到以下错误消息: 客户无法解析为变量 如何解决这个问题! {更新} 现在我
问题内容: 我要使用的REST服务以压缩的JSON格式存储答案。它提供,但是我的OkHttp不会将其编码为可读文本,因此JSON转换器将引发异常。 根据Jake Whartons的评论, 标头应告诉OkHttp解码正文。 用于创建RestAdapter的代码是: gradle依赖项是: 我的ServiceInterface中的方法: 问题答案: 替换为: 有了这个: 当您提供自己的标头时,您将指示
问题内容: 我正在尝试固定服务器的自签名证书。我的OkHttpClient使用两个参数,第一个是ssl Socket Factory: 其次是证书固定器: 注意:如果我不添加certificatePinner,则一切正常。问题是执行请求时,将调用CertificatePinner.check(): 显然,如果我确实设置了一个(非空的)certificatePinner,则该方法不会在那里停止,而是
问题内容: 我想使用OkHttpClient加载URL,如果给定URL的网站以pdf内容类型响应,我将继续下载PDF,否则我想忽略响应。 我的问题是,我是否需要做一些特殊的事情来关闭请求/响应,或者如果我选择不读取响应字节流,是否需要做任何事情来表明我将不使用响应?如果没有,OkHttpClient何时关闭连接? 问题答案: 调用将释放响应所拥有的所有资源。连接池将使连接保持打开状态,但是如果未使
问题内容: 我在将OkHttp 2.7.0与Retrofit 2-beta2结合使用。 为了从Retrofit 获取对象,我正在使用Retrofit .client() 方法并取消所有正在运行的请求,我将其称为cancel(Object tag) 方法,但是请求仍然保持运行,并且得到响应。 即使客户的getQueuedCallCount()和getRunningCallCount()返回0调用ca
问题内容: 在我的项目中,我已经使用OkHttp(版本2.5.0)作为我的网络请求库。但是几天前,我尝试将Retrofit2作为应用程序的网络请求库的一部分,正如您所知,新的Retrofit2库依赖于OkHttp(版本3.2.0)。因此,当我的应用程序在其android android 5.0下的版本始终会导致崩溃(较大的版本运行良好且不会导致崩溃),崩溃堆栈信息如下所示: 从堆栈跟踪中,我猜想O
问题内容: 我读了一些将jsons发布到服务器的示例。 有人说: OkHttp是Java提供的HttpUrlConnection接口的实现。它提供用于编写内容的输入流,并且不知道(或不在乎)内容的格式。 现在,我想用名称和密码的参数对URL进行常规发布。 这意味着我需要自己将名称和值对编码为流? 问题答案: 当前接受的答案已过期。现在,如果您想创建一个发布请求并向其中添加参数,则应该使用Mul
问题内容: 问题: 如何向OkHTTP添加授权代理。 我知道OkHTTP的生成器确实支持代理,尽管我很难设置一个代理。 我有IP /端口/用户名/密码。 尽管我不知道如何将其转换为client.SetProxy()中可以使用的那些。 这似乎过于复杂,我似乎无法弄清楚。任何帮助,将不胜感激。 问题答案: 试试这个: