在android AndroidManifest.xml文件中怎样设置访问网络的权限

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在android AndroidManifest.xml文件中怎样设置访问网络的权限相关的知识,希望对你有一定的参考价值。

android访问网络的权限是android.permission.INTERNET。
声明权限的方式:
第一步:打开 AndroidManifest.xml文件
第二步:在application节点之前增加<uses-permission android:name=”android.permission.INTERNET”></uses-permission>
代码中需要通过Thread来访问网络,UI线程连接网络Android会抛出异常。

资料拓展:

Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用“安卓”或“安致”。Android操作系统最初由Andy Rubin开发,主要支持手机。2005年8月由Google收购注资。2007年11月,Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。随后Google以Apache开源许可证的授权方式,发布了Android的源代码。第一部Android智能手机发布于2008年10月。Android逐渐扩展到平板电脑及其他领域上,如电视、数码相机、游戏机等。2011年第一季度,Android在全球的市场份额首次超过塞班系统,跃居全球第一。 2013年的第四季度,Android平台手机的全球市场份额已经达到78.1%。2013年09月24日谷歌开发的操作系统Android在迎来了5岁生日,全世界采用这款系统的设备数量已经达到10亿台。

参考技术A

在<manifest标签下添加语句:

<uses-permission android:name="android.permission.INTERNET"/>

即可申请到访问网络的权限

拓展内容:

Android 6.0 运行时权限的介绍

在保护用户隐私方面:Android6.0为了更好的保护个人隐私,添加了运行时权限:分为两类,一类是Normal Permissions,这类权限不涉及个人隐私,不需要用户进行授权,比如手机震动,访问网络;一类是Dangerous Permissions,这类权限涉及个人隐私,需要用户进行授权,比如读取SD卡,访问通讯录等。

在用户操作方面:当执行敏感操作之前弹出对话框,请求权限,可以拒绝,可以同意;可以在设置页面对APP的权限进行查看,以及对单个权限进行授权或者解除授权。



参考技术B

Android访问网络的权限是android.permission.INTERNET。

声明权限的方式:

    打开 AndroidManifest.xml文件

    在application节点之前增加<uses-permission android:name=”android.permission.INTERNET”></uses-permission>

    代码中需要通过Thread来访问网络,UI线程连接网络Android会抛出异常。

参考技术C Android访问网络的权限是android.permission.INTERNET。
声明权限的方式:
打开 AndroidManifest.xml文件
在application节点之前增加<uses-permission android:name=”android.permission.INTERNET”></uses-permission>
代码中需要通过Thread来访问网络,UI线程连接网络Android会抛出异常。
参考技术D 在 AndroidManifest.xml中加入下面这句
<uses-permission android:name="android.permission.INTERNET" />

Android判断Activity是否在AndroidManifest.xml里面注册(源码分析)

Android判断Activity是否在AndroidManifest.xml里面注册(源码分析)

Android的PackageManagerService10.0源码解读

Android的ActivityManagerService(简称AMS)的源码分析

Android判断Activity是否在AndroidManifest.xml里面注册(源码分析)


这个问题相信大家在实际的开发中,都遇到过这个问题,答案就不用说了,在AndroidManifest.xml中添加Activity的注册,毕竟Activity属于四大组件之一,使用的时候,需要要在清单文件中注册。

<activity android:name=".TargetActivity"></activity>

但是这个出现这个问题的根源在哪里?下面我们就进入源码仔细看看。

这里就不一步一步进入源码,直接分析关键代码:

public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options)  ...
     try 
      intent.migrateExtraStreamToClipData();
      intent.prepareToLeaveProcess(who);//1.通过IActivityManager调用我们执行AMS的startActivity方法,并返回执行 结果
      int result = ActivityManager.getService() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
     //2. 检查结果
     checkStartActivityResult(result, intent);
      catch (RemoteException e) 
         throw new RuntimeException("Failure from system", e);
     
      return null;
  

通过源码execStartActivity这个方法可以看到主要是在这个检查结果这里面去分析的checkStartActivityResult(result, intent);

public static void checkStartActivityResult(int res, Object intent) 
        if (!ActivityManager.isStartResultFatalError(res)) 
            return;
        
        switch (res) 
            case ActivityManager.START_INTENT_NOT_RESOLVED:
            case ActivityManager.START_CLASS_NOT_FOUND:
                //3. 这里我们找到了报错的地方,原来是res结果为 START_INTENT_NOT_RESOLVED,
                // START_CLASS_NOT_FOUND就会报这个错误
                if (intent instanceof Intent && ((Intent) intent).getComponent() != null)
                    throw new ActivityNotFoundException("Unable to find explicit activity class " + ((Intent) intent).getComponent().toShortString() + "; have you declared this activity in your AndroidManifest.xml?");
                throw new ActivityNotFoundException("No Activity found to handle " + intent);
            case ActivityManager.START_PERMISSION_DENIED:
                throw new SecurityException("Not allowed to start activity " + intent);
            case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
                throw new AndroidRuntimeException("FORWARD_RESULT_FLAG used while also requesting a result");
            case ActivityManager.START_NOT_ACTIVITY:
                throw new IllegalArgumentException("PendingIntent is not an activity");
            case ActivityManager.START_NOT_VOICE_COMPATIBLE:
                throw new SecurityException("Starting under voice control not allowed for: " + intent);
            case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
                throw new IllegalStateException("Session calling startVoiceActivity does not match active session");
            case ActivityManager.START_VOICE_HIDDEN_SESSION:
                throw new IllegalStateException("Cannot start voice activity on a hidden session");
            case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION:
                throw new IllegalStateException("Session calling startAssistantActivity does not match active session");
            case ActivityManager.START_ASSISTANT_HIDDEN_SESSION:
                throw new IllegalStateException("Cannot start assistant activity on a hidden session");
            case ActivityManager.START_CANCELED:
                throw new AndroidRuntimeException("Activity could not be started for " + intent);
            default:
                throw new AndroidRuntimeException("Unknown error code " + res + " when starting " + intent);
        
    

可以看到当结果为

case ActivityManager.START_INTENT_NOT_RESOLVED:

case ActivityManager.START_CLASS_NOT_FOUND:

​就会报
throw new ActivityNotFoundException("Unable to find explicit activity class " + ((Intent) intent).getComponent().toShortString() + “; have you declared this activity in your AndroidManifest.xml?”);

这下我们就知道了如果没在清单文件中添加这个注册,报错的位置。

AMS是如何判断activity没有注册的,首先我们得明白startActivity执行的主流程

这个篇幅太多了,可以自己去源码跟一下,这里不作介绍,

我们这里分析主要流程代码

找到在ASR.startActivity (ActivityStarter)中返回了

START_INTENT_NOT_RESOLVED,START_CLASS_NOT_FOUND

private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) 
        int err = ActivityManager.START_SUCCESS;
        ...
        //接下来开始做一些校验判断
        if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) 
            // We couldn't find a class that can handle the given Intent.
            // That's the end of that! err = ActivityManager.START_INTENT_NOT_RESOLVED;
            // 从Intent中无法找 到相应的Component
        
        if (err == ActivityManager.START_SUCCESS && aInfo == null) 
            // We couldn't find the specific class specified in the Intent.
            // Also the end of the line.
            err = ActivityManager.START_CLASS_NOT_FOUND;
            // 从Intent中无法找到相 应的ActivityInfo
        
                 ...
        if (err != START_SUCCESS) 
            //不能成功启动了,返回err
            if (resultRecord != null) 
                resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
            
            SafeActivityOptions.abort(options);
            return err;
        
        //创建出我们的目标ActivityRecord对象,存到传入数组0索引上
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid, callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, mSupervisor, checkedOptions, sourceRecord);
        ...
        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask, outActivity);
    

但是 intent.getComponent(),aInfo又是从哪儿获取的呢,我们回溯到

startActivityMayWait.

看下上面的aInfo哪来的.

ActivityInfo resolveActivity(Intent intent, ResolveInfo rInfo, int startFlags, ProfilerInfo profilerInfo) final ActivityInfo aInfo = rInfo != null ? rInfo.activityInfo : null;
        if (aInfo != null) 
            // Store the found target back into the intent, because now that
            // we have it we never want to do this again. For example, if the
            // user navigates back to this point in the history, we should
            // always restart the exact same activity.
            intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
            // Don't debug things in the system process ...
        
        return aInfo;
    

发现是从rInfo来的

ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags, int filterCallingUid) 
        synchronized (mService) try ...final long token = Binder.clearCallingIdentity();
                try 
                    return mService.getPackageManagerInternalLocked().resolveIntent(intent, resolvedType, modifiedFlags, userId, true, filterCallingUid);
                 finally 
                    Binder.restoreCallingIdentity(token);
                 ...
            
        
    

rInfo的获取

PackageManagerInternal getPackageManagerInternalLocked() 
        if (mPackageManagerInt == null) 
​            mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
        
        return mPackageManagerInt;
    

具体实现类是PackageManagerService

@Override
    public ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags, int userId) 
        return resolveIntentInternal(intent, resolvedType, flags, userId, false, Binder.getCallingUid());
    

看resolveIntentInternal

private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,int flags, int userId, boolean resolveForStart, int filterCallingUid) 
        try ...
            //获取ResolveInfo列表
            final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags, filterCallingUid, userId, resolveForStart, true /*allowDynamicSplits*/);Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            //找出最好的返回
            final ResolveInfo bestChoice = chooseBestActivity(intent, resolvedType, flags, query, userId);
            return bestChoice;
         finally 
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        
    

看 queryIntentActivitiesInternal

private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent, String resolvedType, int flags, int filterCallingUid, int userId, boolean resolveForStart, boolean allowDynamicSplits) ...
        if (comp != null) 
            final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
            final ActivityInfo ai = getActivityInfo(comp, flags, userId);
            if (ai != null) 
                ...
            
        

原来是从getActivityInfo获取的

	@Override
    public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) 
        return getActivityInfoInternal(component, flags, Binder.getCallingUid(), userId);

getActivityInfoInternal方法

private ActivityInfo getActivityInfoInternal(ComponentName component, int flags, int filterCallingUid, int userId) 
        if (!sUserManager.exists(userId)) return null;
        flags = updateFlagsForComponent(flags, userId, component);
        if (!isRecentsAccessingChildProfiles(Binder.getCallingUid(), userId)) 
            mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId, false /* requireFullPermission */, false /* checkShell */, "get activity info");
        
        synchronized (mPackages) 
            //关键点
            PackageParser.Activity a = mActivities.mActivities.get(component);
            if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) 
                PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                if (ps == null) return null;
                if (filterAppAccessLPr(ps, filterCallingUid, component, TYPE_ACTIVITY, userId)) 
                    return null;
                
                //关键点
                return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId), userId);
            
            if (mResolveComponentName.equals(component)) 
                return PackageParser.generateActivityInfo(mResolveActivity, flags, new PackageUserState(), userId);
            
        
        return null;
    

分析到这里,大家应该知道怎么回事了吧,其实就是解析了AndroidManifest.xml里面的信息,具体怎么解析,等有空了分析。
Android的PackageManagerService10.0源码解读(AndroidManifest.xml解析)

欢迎关注下面公众号,里面有大量免费的android进阶资料,回复 资料 即可领取。

以上是关于在android AndroidManifest.xml文件中怎样设置访问网络的权限的主要内容,如果未能解决你的问题,请参考以下文章

Android判断Activity是否在AndroidManifest.xml里面注册(源码分析)

Android判断Activity是否在AndroidManifest.xml里面注册(源码分析)

android怎么在androidmanifest.xml文件中注册权限

在 Android Studio 的 AndroidManifest.xml 中添加权限?

android:androidmanifest.xml 中的名称值

在android AndroidManifest.xml文件中怎样设置访问网络的权限