背景:
微博sdk 登录提示
Application requires permission to access the Internet
如上图
问题分析:
这种情况,只有手机上没有安装微博客户端的时候,才会出现。
我们可以跟下微博sdk 的代码,在这里:
protected void startWebAuth() {
if (!NetworkHelper.hasInternetPermission(this.mAuthActivity)) {
UIUtils.showAlert(this.mAuthActivity, "Error", "Application requires permission to access the Internet");
} else {
AuthWebViewRequestParam param = new AuthWebViewRequestParam(authInfo, WebRequestType.AUTH, mAuthListenerKey, "微博登录", url, this.mAuthActivity);
Intent intent = new Intent(this.mAuthActivity, WeiboSdkWebActivity.class);
Bundle bundle = new Bundle();
param.fillBundle(bundle);
intent.putExtras(bundle);
this.mAuthActivity.startActivity(intent);
}
}
很明显,NetworkHelper.hasInternetPermission返回了fasle,也就是没有权限才会有这个弹窗。
我们看下这个是怎么写的:
public static boolean hasInternetPermission(Context context) {
if (context != null) {
return 0 == context.checkCallingPermission("android.permission.INTERNET");
} else {
return true;
}
}
这里调用了checkCallingPermission!如果是同一个进程调用这个方法,一定会返回-1,也就是permission define。(权限拒绝)
我们开始看源码:
/**
* Determine whether the calling process of an IPC you are handling has been
* granted a particular permission. This is basically the same as calling
* {@link #checkPermission(String, int, int)} with the pid and uid returned
* by {@link android.os.Binder#getCallingPid} and
* {@link android.os.Binder#getCallingUid}. One important difference
* is that if you are not currently processing an IPC, this function
* will always fail. This is done to protect against accidentally
* leaking permissions; you can use {@link #checkCallingOrSelfPermission}
* to avoid this protection.
*
* @param permission The name of the permission being checked.
*
* @return {@link PackageManager#PERMISSION_GRANTED} if the calling
* pid/uid is allowed that permission, or
* {@link PackageManager#PERMISSION_DENIED} if it is not.
*
* @see PackageManager#checkPermission(String, String)
* @see #checkPermission
* @see #checkCallingOrSelfPermission
*/
@CheckResult(suggest="#enforceCallingPermission(String,String)")
@PackageManager.PermissionResult
public abstract int checkCallingPermission(@NonNull String permission);
/**
* Determine whether <em>you</em> have been granted a particular permission.
*
* @param permission The name of the permission being checked.
*
* @return {@link PackageManager#PERMISSION_GRANTED} if you have the
* permission, or {@link PackageManager#PERMISSION_DENIED} if not.
*
* @see PackageManager#checkPermission(String, String)
* @see #checkCallingPermission(String)
*/
@PackageManager.PermissionResult
public abstract int checkSelfPermission(@NonNull String permission);
我们看下checkCallingPermission 的实现,以及checkSelfPermission 的实现:
@Override
public int checkCallingPermission(String permission) {
if (permission == null) {
throw new IllegalArgumentException("permission is null");
}
int pid = Binder.getCallingPid();
if (pid != Process.myPid()) {
return checkPermission(permission, pid, Binder.getCallingUid());
}
return PackageManager.PERMISSION_DENIED;
}
checkCallingPermission 如果是同一个进程的话,那么直接返回PERMISSION_DENIED 。只适用于不同进程之间判断有没有权限。
@Override
public int checkSelfPermission(String permission) {
if (permission == null) {
throw new IllegalArgumentException("permission is null");
}
return checkPermission(permission, Process.myPid(), Process.myUid());
}
这个才是判断当前进程,当前用户,有没有这个权限。
解决方法:
我们重写调用微博登录的activity 的 checkCallingPermission 方法:
@Override
public int checkCallingPermission(String permission) {
return super.checkCallingOrSelfPermission(permission);
}
这样的话,checkCallingOrSelfPermission 就会返回正确的,当前应用有没有网络权限。就不会再弹窗了。