Android面试题(二)Android基础2

24 篇文章 0 订阅

(二)Android源码相关分析

1、Android动画框架实现原理

RootView 只有一个孩子就是 DecorView,这里整个 View Tree 都是 DecorView 的子 View。

在DecorView中,标题窗口(TitleBar)以下部分的 FrameLayout(Content容器) 就是为了让程序员通过 setContentView 来设置用户需要的窗口内容。

因为整个 View 的布局就是一棵树,所以绘制的时候也是按照树形结构遍历来让每个 View 进行绘制。

递归的绘制整个窗口需要按顺序执行以下几个步骤:

  1. 绘制背景;
  2. 如果需要保存画布(canvas)的层,为淡入或淡出做准备;
  3. 绘制 View 本身的内容:通过调用 View.onDraw(canvas) 函数实现,通过这个我们应该能看出来 onDraw 函数重载的重要性,onDraw 函数中绘制线条 / 圆 / 文字等功能会调用 Canvas 中对应的功能。(每个View都需要重载该方法,ViewGroup不需要实现该方法)
  4. 如果该view是ViewGroup,则需要绘制自己的孩子:通过 dispatchDraw(canvas) 实现,参看 ViewGroup.Java 中的代码可知,dispatchDraw()   ->   drawChild()   ->   child.draw(canvas) 。这样的调用过程被用来保证每个子 View 的 draw 函数都被调用,通过这种递归调用从而让整个 View 树中的所有 View 的内容都得到绘制。(在调用每个子 View 的 draw 函数之前,需要绘制的 View 的绘制位置是在 Canvas 通过 translate 函数调用来进行切换的,窗口中的所有 View 是共用一个 Canvas 对象。)
  5. 如果需要,我们可以绘制淡入淡出相关的内容,并恢复保存的画布所在的层(layer)
  6. 绘制修饰的内容(例如滚动条):这个可知要实现滚动条效果并不需要 ScrollView,可以在 View 中完成的,比如通过ParentView中设置ChildView的画布来调整Canvas,进而实现动画效果(安卓动画就是通过父View来不断调整子View的画不坐标系来实现的)

2、Android各个版本API的区别

Android4.4 KitKat

  • API级别:19
  • 外部存储空间的读取:具有 READ_EXTERNAL_STORAGE 权限才能使用getExternalStoragePublicDirectory() 返回的目录中的文件。但是,如果只需要访问 getExternalFilesDir() 或者是getExternalCacheDir(),也就是本应用自己的文件夹的时候,不需要去申请READ_EXTERNAL_STORAGE权限.
  • WebView的底层代码该用Chromium的源码,支持h5和远程调试
  • AlarmManager:使用set()或setRepeating()方法创建的闹钟会变得不准确。新的setWindow()方法和setExact()方法可以设置在一个时间窗口内触发闹钟或者在一个铁定的精准的时间触发闹钟
  • ContentResolver 同步数据

Android5.0 Lolipop

  • API级别:21
  • 声音与震动:
    1. 之前的Ringtone,MediaPlayer,Vibrator用Notification.Builder方法来替代;
    2. 之前使用 STREAM_MUSIC 作为主流式传输来控制平板电脑设备上的音量。在 Android 5.0 中,手机和平板电脑设备的主音量流式传输现已合并,由 STREAM_RING 或 STREAM_NOTIFICATION 进行控制。
  • 锁定屏幕的情况下,可以利用setPublicVersion()来删减通知显示的文本;若不包含重要信息可以使用setVisibility()并将通知的可见性设为VISIBILITY_PUBLIC
  • 媒体播放显示:从 Android 5.0 开始,系统不再将 RemoteControlClient 对象和MediaSession显示在锁定屏幕上,目前RemoteControlClient 类已经被弃用了。
  • getRecentTasks(): 为提升用户隐私的安全性,现已弃用 ActivityManager.getRecentTasks() 方法。如果您的应用使用此方法检索它自己的任务,则改用 getAppTasks() 检索该信息。
  • 绑定服务:Context.bindService() 方法现在需要显式 Intent,如果提供隐式 intent,将引发异常。
  • WebView:默认情况下,系统会阻止混合内容和第三方 Cookie。要允许混合内容和第三方 Cookie,请分别使用 setMixedContentMode() 和 setAcceptThirdPartyCookies() 方法。

Android6.0 Marshmallow

  • API级别:23
  • 取消支持 Apache HTTP 客户端:改用 HttpURLConnection 类。
    1. 此 API 效率更高,因为它可以通过透明压缩和响应缓存减少网络使用,并可最大限度降低耗电量。
    2. 要继续使用 Apache HTTP API,您必须先在 build.gradle 文件中声明以下编译时依赖项:android { useLibrary 'org.apache.http.legacy' }
  • 通知:此版本移除了 Notification.setLatestEventInfo() 方法。请改用 Notification.Builder 类来构建通知。要重复更新通知,请重复使用 Notification.Builder 实例。调用 build() 方法可获取更新后的 Notification 实例。
  • 音频管理器变更:
    1. 不再支持通过 AudioManager 类直接设置音量或将特定音频流静音。setStreamSolo() 改用 requestAudioFocus() 方法。
    2. 类似地,setStreamMute() 改用 adjustStreamVolume() 方法并传入方向值 ADJUST_MUTE 或 ADJUST_UNMUTE。
  • WLAN 和网络连接变更
  • 相机服务变更

Android7.0 Nougat

  • API级别:23
  • 在应用间共享文件:
    1. Android 框架执行的 StrictMode API 政策禁止在您的应用外部公开 file:// URI。如果一项包含文件 URI 的 intent 离开您的应用,则应用出现故障,并出现 FileUriExposedException 异常。
    2. 要在应用间共享文件,您应发送一项 content:// URI,并授予 URI 临时访问权限。进行此授权的最简单方式是使用 FileProvider 类。
  • 权限更改:为了提高私有文件的安全性,面向 Android 7.0 或更高版本的应用私有目录被限制访问 (0700)。此设置可防止私有文件的元数据泄漏,如它们的大小或存在性

 

3、Requestlayout,onlayout,onDraw,DrawChild区别与联系

requestLayout()方法 :会导致调用measure()过程 和 layout()过程 。 说明:只是对View树重新布局layout过程包括measure()和layout()过程,不会调用draw()过程,但不会重新绘制 任何视图包括该调用者本身。

onLayout()方法(如果该View是ViewGroup对象,需要实现该方法,对每个子视图进行布局)

调用onDraw()方法绘制视图本身 (每个View都需要重载该方法,ViewGroup不需要实现该方法)

drawChild()去重新回调每个子视图的draw()方法

4、invalidate和postInvalidate的区别及使用

Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。 

invalidate()是用来刷新View的,必须是在UI线程中进行工作。比如在修改某个view的显示时,调用invalidate()才能看到重新绘制的界面。invalidate()的调用是把之前的旧的view从主UI线程队列中pop掉。 一个Android 程序默认情况下也只有一个进程,但一个进程下却可以有许多个线程。

在这么多线程当中,把主要是负责控制UI界面的显示、更新和控件交互的线程称为UI线程,由于onCreate()方法是由UI线程执行的,所以也可以把UI线程理解为主线程。其余的线程可以理解为工作者线程。

invalidate()得在UI线程中被调动,在工作者线程中可以通过Handler来通知UI线程进行界面更新。

而postInvalidate()在工作者线程中被调用

5、Activity-Window-View三者的差别

Activity是整个模型的控制单元,

Window属于承载模型,负责承载视图,

View是视图显示模型。

一个比喻总结下Activity Window View三只之间的关系:Activity像一个工匠(控制单元),Window像窗户(承载模型),View像窗花(显示视图)。

  1. 在Activity的attach方法里,系统会创建Activity所属的Window对象并为其设置回调接口,Window对象的创建时通过PolicyManager的makeNewWindow方法实现的。由于Activity实现了Window的Callback接口,因此当Window接收到外界的状态改变就会回调到Activity的方法。
  2. View是Android中的视图呈现方式,但是View不能单独存在,它必须附着在Window这个抽象的概念上面,因此有视图的地方就有Window。
  3. View借助ViewRoot这个纽带,绑定在Window上ViewRoot对应于ViewRootImpl类,它是连接WindowManager和Decorview的纽带,View的三大流程(measure,layout,draw)均是通过ViewRoot来完成的。

在ActivityThread中,当Activity对象被创建完毕后,会将DecorVidew添加到Window中, 同时会创建ViewRootImpl对象,并将ViewRootImpl对象和DecorView建立关联。

一个Activity中视图的绘制流程:

在onCreat()中,我们只有一个setContentView()的操作,

    1. 在Activity的setContentView()中,Activity将具体实现交给了Window处理,
    2. 而Window的具体实现是PhoneWindow在setContentView中创建了DecorView,DecorView是整棵View树的顶级View,
    3. 然后将View添加到DecorView的mContentParent中,
    4. 最后回调Activity的onContentChanged方法通知Activity视图已经发生改变。

DecorView作为顶级View,一般情况下它内部会包含一个竖直方向的LinearLayout,在这个LinearLayout里面有上下两个部分,上面是标题栏,下面是内容栏,其中标题栏一般由Activity的Theme样式所决定。在Activity中我们通过setContentView所设置的布局文件其实就是被加到内容栏之中的。

用户的布局加载:

View的绘制流程是从ViewRoot的performTraversals方法开始的,它经过measure,layout和draw三个过程最终将一个View绘制出来,其中measure用来测量View的宽和高,layout用来确定View在父容器中的放置位置,而draw则负责将View绘制在屏幕上。

如此反复完成一棵View树的遍历,整个View视图就显示在屏幕上了。

6、谈谈对Volley的理解

https://blog.csdn.net/u010873775/article/details/80214900

7、如何优化自定义View

(1)减少不必要的代码:对于频繁调用的方法,需要尽量减少不必要的代码。

(2)不在 onDraw 中做内存分配的事:先从 onDraw 开始,需要特别注意不应该在这里做内存分配的事情,因为它会导致 GC,从而导致卡顿。在初始化或者动画间隙期间做分配内存的动作。不要在动画正在执行的时候做内存分配的事情。

(3)减少 onDraw 被调用的次数:大多数时候导致 onDraw 都是因为调用了 invalidate().因此请尽量减少调用 invaildate()的次数。如果可能的话,尽量调用含有 4 个参数的 invalidate()方法而不是没有参数的 invalidate()。没有参数的 invalidate 会强制重绘整个 view。

(4)减少 layout 的次数:一个非常耗时的操作是请求 layout。任何时候执行 requestLayout(),会使得 Android UI 系统去遍历整个View 的层级来计算出每一个 view 的大小。如果找到有冲突的值,它会需要重新计算好几次。

(5)选用扁平化的 View:另外需要尽量保持 View 的层级是扁平化的(去除冗余、厚重和繁杂的装饰效果),这样对提高效率很有帮助。

(6)复杂的 UI 使用 ViewGroup:如果你有一个复杂的 UI,你应该考虑写一个自定义的 ViewGroup 来执行他的 layout 操作。(与内置的view 不同,自定义的 view 可以使得程序仅仅测量这一部分,这避免了遍历整个 view 的层级结构来计算大小。)继承 ViewGroup作为自定义 view 的一部分,有子 views,但是它从来不测量它们。而是根据他自身的 layout 法则,直接设置它们的大小。

 

8、低版本SDK如何实现高版本api?

编译器还是很强大的,提供了四种解决方案:

但是第一、第二、第三种方法只是能编译通过,到了低于API24的系统(也就是低于Android7.0的手机系统上)运行,将会引发 java.lang.NoSuchMethodError。

最安全的做法是添加运行时SDK版本判断,判断为低版本时添加其他方法实现该功能

1、添加注解 @TargetApi(Build.VERSION_CODES.N)

不管项目的minSdkVersion是多少,被注解元素的的minSdk指定为特定版本,以跳过lint检查

2、添加注解 @RequiresApi(Build.VERSION_CODES.N)

被注解的元素只能在被给的 API 版本或更高情况下才能被调用

3、添加注解 @SuppressLint(“NewApi”)

Lint 静态检测工具将会忽略被注解元素的警告

4、添加运行时SDK版本判断

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //运行系统大于等于指定版本,可运行高于指定版本的api } else { }

9、描述一次网络请求的流程

  1. 域名解析、
  2. TCP的三次握手、
  3. 建立TCP连接后发起HTTP请求、
  4. 服务器响应HTTP请求、
  5. 解析从服务器传过来的数据,并使用

10、HttpUrlConnection 和 okhttp关系

我们最熟悉的肯定是HttpUrlConnection,这是google官方提供的用来访问网络,但是HttpUrlConnection实现的比较简单,只支持1.0/1.1,并没有上面讲的多路复用,如果碰到app大量网络请求的时候,性能比较差,而且HttpUrlConnection底层也是用Socket来实现的。

OkHttp 与 HttpUrlConnection一样,实现了一个网络连接的过程( OkHttp 和 HttpUrlConnection是一级的)。OkHttp使用的是sink和source,这两个是在Okio这个开源库里的,sink相当于outputStream,source相当于是inputStream。Sink和source比InputSrteam和OutputSrewam更加强大(其子类有缓冲BufferedSink、支持Gzip压缩GzipSink、服务于GzipSink的ForwardingSink和InflaterSink)

11、ActivityThread,AMS,WMS的工作原理

https://blog.csdn.net/github_37130188/article/details/89577449

12、自定义View如何考虑机型适配

布局类建议:

  • 合理使用warp_content,match_parent.
  • 尽可能的是使用RelativeLayout
  • 引入android的百分比布局。
  • 针对不同的机型,使用不同的布局文
  • 件放在对应的目录下,android会自动匹配。

Icon类建议:

  • 尽量使用svg转换而成xml。
  • 切图的时候切大分辨率的图,应用到布局当中。在小分辨率的手机上也会有很好的显示效果。
  • 使用与密度无关的像素单位dp,sp

13、自定义View的事件

https://blog.csdn.net/jsonnan/article/details/73693543

14、AstncTask+HttpClient 与 AsyncHttpClient有什么区别

AsyncHttpClient来自android-async-http库是在Apache的HttpClient库的基础上开发构建而成的,这里的异步,是指它所有的网络请求都是在app的UI线程之外的独立工作线程中执行。而开发者通过利用Android的消息处理机制,把我们所需要编写的回调函数放在这个回调函数的创建线程中执行(一般就是UI线程),所以使用起来非常方便除了能应用在开发普通App上,还可以用来开发Service或后台线程,async-http-client库可以自已分辨是被用在哪一种应用下,不需要额外的设置。

15、AsyncTask 如何使用?

https://blog.csdn.net/qq_37321098/article/details/81625580

16、SpareArray原理

https://blog.csdn.net/qq1263292336/article/details/78871751

17、IntentService原理及作用是什么?

IntentService 是 Service 的子类,是一个异步的,会自动停止的服务,很好解决了传统的 Service 中处理完耗时操作忘记停止并销毁 Service 的问题生成一个默认的且与线程相互独立的工作线程执行所有发送到onStartCommand()方法的 Intent,可以在 onHandleIntent()中处理. 串行队列,每次只运行一个任务,不存在线程安全问题,所有任务执行完后自动停止服务,不需要自己手动调用 stopSelf()来停止

18、说说Activity、Intent、Service 是什么关系

一个 Activity 通常是一个单独的屏幕,每一个 Activity 都被实现为一个单独的类,这些类都是从 Activity 基类中继承而来的。

Activity 类会显示由视图控件组成的用户接口,并对视图控件的事件做出响应。

Intent 的调用是用来进行屏幕之间的切换。Intent 描述应用想要做什么。Intent 数据结构中两个最重要的部分是动作和动作对应的数据,一个动作对应一个动作数据。

Service 是运行在后台的代码,不能与用户交互,可以运行在自己的进程里,也可以运行在其他应用程序进程的上下文里。需要一个Activity 或者其他 Context 对象来调用。

联系:

Activity 跳转 Activity,Activity 启动 Service,Service 打开 Activity 都需要 Intent 表明意图,以及传递参数,Intent 是这些组件间信号传递的承载着

19、SP(SharedPreferences)是进程同步的吗?有什么方法做到同步?

1. SharedPreferences不支持进程同步

一个进程的情况,经常采用SharePreference来做,但是SharePreference不支持多进程,它基于单个文件的,默认是没有考虑同步互斥,而且,APP对SP对象做了缓存,不好互斥同步.

MODE_MULTI_PROCESS的作用是什么?

在getSharedPreferences的时候, 会强制让SP进行一次读取操作,从而保证数据是最新的. 但是若频繁多进程进行读写 . 若某个进程持有了一个外部sp对象, 那么不能保证数据是最新的. 因为刚刚被别的进程更新了.

2.考虑用ContentProvider来实现SharedPreferences的进程同步.ContentProvider基于Binder,不存在进程间互斥问题,对于同步,也做了很好的封装,不需要开发者额外实现。 

另外ContentProvider的每次操作都会重新getSP. 保证了sp的一致性.

20、谈谈多线程在Android中的使用

Android提供了四种常用的操作多线程的方式,分别是:

  • Handler+Thread
  • AsyncTask
  • ThreadPoolExecutor
  • IntentService

Handler + Thread

Android主线程包含一个消息队列(MessageQueue),该消息队列里面可以存入一系列的Message或Runnable对象。通过一个Handler你可以往这个消息队列发送Message或者Runnable对象,并且处理这些对象。

每次你新创建一个Handler对象,它会绑定于创建它的线程(也就是UI线程)以及该线程的消息队列,从这时起,这个handler就会开始把Message或Runnable对象传递到消息队列中,并在它们出队列的时候执行它们。

Handler Thread原理图

Handler(会绑定于创建它的线程(也就是UI线程)以及该线程的消息队列)可以把一个Message对象或者Runnable对象压入到消息队列中,进而在UI线程中获取Message或者执行Runnable对象。

Handler把压入消息队列有两类方式,Post和sendMessage:

优缺点

1. Handler用法简单明了,可以将多个异步任务更新UI的代码放在一起,清晰明了

2. 处理单个异步任务代码略显多

适用范围

多个异步任务的更新UI

AsyncTask

AsyncTask是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程。内部通过Handler + Thread原理。

AsyncTask通过一个阻塞队列BlockingQuery<Runnable>存储待执行的任务,利用静态线程池THREAD_POOL_EXECUTOR提供一定数量的线程,默认128个。默认采用串行任务执行器,通过静态串行任务执行器SERIAL_EXECUTOR控制任务串行执行,循环取出任务交给THREAD_POOL_EXECUTOR中的线程执行,执行完一个,再执行下一个。

优缺点

1. 处理单个异步任务简单,可以获取到异步任务的进度

2. 可以通过cancel方法取消还没执行完的AsyncTask

3. 处理多个异步任务代码显得较多

适用范围

单个异步任务的处理

ThreadPoolExecutor

ThreadPoolExecutor提供了一组线程池,可以管理多个线程并行执行。这样一方面减少了每个并行任务独自建立线程的开销,另一方面可以管理多个并发线程的公共资源,从而提高了多线程的效率。所以ThreadPoolExecutor比较适合一组任务的执行。Executors利用工厂模式对ThreadPoolExecutor进行了封装,使用起来更加方便。

适用范围

1. 批处理任务

IntentService

IntentService继承自Service,是一个经过包装的轻量级的Service,用来接收并处理通过Intent传递的异步请求。客户端通过调用startService(Intent)启动一个IntentService,利用一个work线程依次处理顺序过来的请求,处理完成后自动结束Service。

特点

1. 一个可以处理异步任务的简单Service

 

21、进程和 Application 的生命周期

Android一个不同寻常的基本特点就是应用的进程生命周期并不是由应用本身控制的,而是由系统综合考虑决定的,因素包括系统所知的该应用运行中的组件、对于用户的重要程度,以及系统所有的可用内存大小。

Android根据运行在进程中的组件及其状态来决定进程的优先级。可分为以下几种:

1.前台进程:即用户正在交互的进程。多种应用组件都可以使所在进程变成前台进程。 (与用户正在交互的activity、正在运行BroadcasetReceiver中的onReceiver、一个Service正在执行回调)

前台进程在系统内只有少数几个,内存低的情况下是最后才会被终止掉的。

2.可见进程:即正在执行用户意识到的任务的进程,所以终止这个进程会导致明显的负面 体验。(一个可见不可操作的activity、正在运行的前台服务(通过Service.startForeground())、系统使用的服务(动态壁纸等、输入法服务等))

3.服务进程:含有一个调用了Service.startService()方法启动的服务。尽管这种进程通常对于用户不可见,但是可能运行一些用户需要的工作。长期运行的服务(比如30分钟以上)会被降级到缓存进程的级别。可以避免一些内存泄露或者其他问题的长期运行服务消耗系统资源。

4.缓存进程:是当前不需要的,系统可以随时终止的进程。在一个良好的系统里,总是有多个可用的缓存进程以便切换,只在需要时终止最久的进程。只有在非常严峻的情况下,所有的缓存进程都被终止了,必须开始终止服务进程了。 (不可见的activity实例)

 

对进程进行分类时,是基于进程内所有正在运行的组件的最高优先级来决定。一个进程的优先级也可能基于其他依赖的进程优先级而提升。

 

22、AndroidManifest的作用与理解

<manifest/>标签层:

1.package="应用包名"

整个应用的包名。这里有个坑,当我们通过ComponentName来启动某个Activity时,所用的包名一定是这个应用的包名,而不是当前Activity的包名。

2.xmlns:android="http://schemas.android.com/apk/res/android"

命名空间的声明,使得各种Android系统级的属性能让我们使用。当我们需要使用自定义属性时,可以将其修改为res-auto,编译时会为我们自动去找到该自定义属性。

3.android:sharedUserId="android.uid.system"

将当前应用进程设置为系统级进程。

4.uses-permission

为我们的应用添加必须的权限。同时我们也可以该层声明自定义的权限。

<application/>标签层:

应用层标签,用来配置我们的apk的整体属性,也可以统一指定所有界面的主题。

1."android:name"、"android:icon"、"android:label"

顾名思义,用来指定应用的名称、在桌面的启动图标、应用的标签名

2."android:theme"

为当前应用的每个界面都默认设置一个主题,可以后续在activity标签层单独覆盖此Theme。

3."android:allowBackup"

关闭应用程序数据的备份和恢复功能,注意该属性值默认为true,如果你不需要你的应用被恢复导致隐私数据暴露,必须手动设置此属性。

4.android:hardwareAccelerated="true"

开启硬件加速,一般应用不推介使用。就算非要使用也最好在某个Activity单独开启,避免过大的内存开销。

5.android:taskAffinity

设置Activity任务栈的名称,可忽略。

<具体组件/>标签层:

因为</provider>、</service>在实际开发中接触得不多,这部分主要讲解 </activity> 、</receiver>标签。

关于Activity标签的属性,个人最觉得绕和难掌握的就是Intent-filter的匹配规则了,每次使用错了都要去查资料修改,所以这边总结得尽可能仔细。

 

</activity>

1.android:configChanges

当我们的界面大小,方向,字体等config参数改变时,我们的Activity就会重新执行onCreate的生命周期。而当我们设置此属性后,就可以强制让Activity不重新启动,而是只会调用一次onConfigurationChanged方法,所以我们可以在这里做一些相关参数改变的操作。

2."android.intent.category.LAUNCHER"、"android.intent.action.MAIN"

这两个属性共同将当前Activity声明为了我们应用的入口,将应用注册至系统的应用列表中,缺一不可。

注:这里还有一点需要注意,如果希望我们的应用有多个入口,每个入口能进入到app的不同Activity中时,光设置这两个属性还不够,还要为它指定一个进程和启动模式。

 android:process=".otherProcess" 

 android:launchMode ="singleInstance"

1.android:exported="true"

将当前组件暴露给外部。属性决定它是否可以被另一个Application的组件启动。

当我们通过intent去隐式调用一个Activity时,需要同时匹配注册activity中的action、category、data才能正常启动,而这三个属性的匹配规则也略有不同。

2.action

action是最简单的匹配项,我们将其理解为一个区分大小写的字符串即可。

一般用来代表某一种特定的动作,隐式调用时intent必须setAction。一个过滤器中可以有多个action属性,只要我们的itent和其中任意一项equal则就算匹配成功。

3.category

category属性也是一个字符串,匹配时也必须和过滤器中定义的值相同。

当我们没有为intent设置addCategory时,系统为帮我们默认添加一个值为"android.intent.category.DEFAULT"的category。

反过来说,如果我们需要我们自己写的Activity能接受隐式intent启动,我们就必须在它的过滤器中添加"android.intent.category.DEFAULT",否则无法成功启动。

3.data

data比较复杂,幸运地是我们几乎用不到它。

额外扩展一些关于activity的属性:

<meta-data/>标签:

标签<meta-data>是提供组件额外的数据用的,它本身是一个键值对,写在清单文件中之后,可以在代码中获取。

android:excludeFromRecents="true"

设置为true后,当用户按了“最近任务列表”时候,该activity不会出现在最近任务列表中,可达到隐藏应用的目的。

可在receiver标签中添加权限, 发广播时可以设置相应权限的应用接收

</receiver>

        </intent-filter>

            <action android:name="com.android.settings.action.SWITH_AGED_MODE"/>

        <intent-filter>

        android:permission="com.android.settings.permission.SWITH_SETTING">

        android:name="com.android.settings.AliAgeModeReceiver"

    <receiver

关于receiver,广播接收器,也可以给他设置接收权限。一个permission问题:

</receiver>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值