【百度面试题】如何在Android2.3以前的版本中使用DownloadManager呢?

0. 问题

Android 系统中有一个DownloadManager类,可以方便得用来进行下载任务的创建和管理,该类是在Android 2.3(API 9) 的时候引入的。那么,在Android 2.3之前的版本上是否可以用这个功能呢?如果可以的话该怎么做?

1. 问题分析

这是一道百度曾经的Android开发岗位的面试题。可能很多初学者看到后会觉得莫名其妙,一个新版本加的API,你怎么可能在旧版本上用呢?肯定直接就ClassNotFoundException,然后App就gg了。

这个时候你就会开动脑筋想一想,没有这个类怎么办呢?既然面试官都问了,那说明这个问题肯定是有办法做到的,至于如何做,那就是面试官希望你回答的。

你可能首先想到的是:

把这个类复制一份到App里面。

这个时候面试官就会说:复制不行吧,这个类里面会调用一些系统内部的隐藏API,普通的App是无法访问的,你还有其他的办法呢?

想了又想,你可能会说:没有办法。

那么,既然是系统的API类,我们不妨去看看这个类的源码,看能不能从源码里面找到思路。

然后从DownloadManager 的源码里面,你会发现这样的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* columns to request from DownloadProvider.
* @hide
*/
public static final String[] UNDERLYING_COLUMNS = new String[] {
Downloads.Impl._ID,
Downloads.Impl._DATA + " AS " + COLUMN_LOCAL_FILENAME,
Downloads.Impl.COLUMN_MEDIAPROVIDER_URI,
Downloads.Impl.COLUMN_DESTINATION,
Downloads.Impl.COLUMN_TITLE,
Downloads.Impl.COLUMN_DESCRIPTION,
Downloads.Impl.COLUMN_URI,
Downloads.Impl.COLUMN_STATUS,
Downloads.Impl.COLUMN_FILE_NAME_HINT,
Downloads.Impl.COLUMN_MIME_TYPE + " AS " + COLUMN_MEDIA_TYPE,
Downloads.Impl.COLUMN_TOTAL_BYTES + " AS " + COLUMN_TOTAL_SIZE_BYTES,
Downloads.Impl.COLUMN_LAST_MODIFICATION + " AS " + COLUMN_LAST_MODIFIED_TIMESTAMP,
Downloads.Impl.COLUMN_CURRENT_BYTES + " AS " + COLUMN_BYTES_DOWNLOADED_SO_FAR,
Downloads.Impl.COLUMN_ALLOW_WRITE,
/* add the following 'computed' columns to the cursor.
* they are not 'returned' by the database, but their inclusion
* eliminates need to have lot of methods in CursorTranslator
*/
"'placeholder' AS " + COLUMN_LOCAL_URI,
"'placeholder' AS " + COLUMN_REASON
};

里面有提到DownloadProvider,而且还定义了一堆的字段名称,看起来像是在操作一个ContentProvider。

于是你立马恍然大悟:

DownloadManager 其实就是对DownloadProvider 的封装。

而 DownloadProvider 则是在旧的版本中也存在的,它是系统的内置的一个ContentProvider。

那么,问题的答案就呼之欲出了:

可以直接操作DownloadProvider 来实现DownloadManager的功能

当然,Android系统内置的ContentProvider 还有其他的一些,比如短信信息、联系人信息、浏览器书签信息等等,类似的问题都是可以通过直接操作ContentProvider 来解决的。

2. 总结

这个问题,如果看到答案之后,就会觉得其实也不过如此,但是如果在面试的时候不熟悉DownloadManager 的实现原理的话,那么这个问题是很难回答的,技术上不是多困难的东西,但是确实知识的盲区。

这个问题其实是几年前,我自己亲身经历的,当时的我工作了没两年,还是个稚嫩的少年,完全没想到面试官会问这样的问题(本来预期是Activity启动模式、View事件分发这样的经典问题),自然也是没回答出来。

后来也是对这个问题耿耿于怀了很久,所以在回去后就研究DownloadManager的源码,最终才算是搞明白了。

等我明白了这个问题的答案之后,就意识到这个问题是一个非常精妙的面试题:

  1. 它不是很常见的那种套路题(俗称八股文题)
  2. 它能筛选出来对Framework源码熟悉的候选人
  3. 它能很好得考察候选人对Android系统内置的ContentProvider的理解,以及对ContentProvider 这个组件的理解。

可以看出,面试官是希望筛选出对系统运行原理深入理解的人,而不是死记知识点。

最后,祝各位开发者们头发坚挺!

坚持原创技术分享,您的支持将鼓励我继续创作!