Android中FileProvider的各种场景应用详解

目录
  • 前言
  • 一、常规使用与定义
  • 二、能不能自定义接收文件?
  • 三、能不能主动查询对方的沙盒?
  • 总结

前言

有部分同学只要是上传或者下载,只要用到了文件,不管三七二十一写个 FileProvider 再说。

不是每一种情况都需要使用 FileProvider 的,啥?你问行不行?有没有毛病?

这... 写了确实可以,没毛病!但是这没有必要啊。

如果不需要FileProvider就不需要定义啊,如果定义了重复的 FileProvider,还会导致清单文件合并失败,需要处理冲突,从而引出又一个问题,解决 FileProvider 的冲突问题,当然这不是本文的重点,网上也有解决方案。

这里我们只使用 FileProvider 来说,分析一下如下场景:

1.比如我们下载文件到SD卡,当然我们一般都下载到download目录下,那么使用这个文件,需要 FileProvider 吗?

不需要!因为他是共享文件夹中,并不是在沙盒中。

2.那我们把文件保存到沙盒中,比如 getExternalFilesDir 。那么我们使用这个沙盒中的文件,需要 FileProvider 吗?

3.看情况,如果只是把此文件上传到服务器,上传到云平台,也就是我们自己App使用自己的沙盒,是不需要 FileProvider 的

4.如果是想使用系统打开文件,或者传递给第三方App,那么是需要 FileProvider 的。

也就是说一般使用场景,我们只有在自己App沙盒中的文件,需要给别的App操作的时候,我们才需要使用 FileProvider 。

比较典型的例子是,下载Apk到自己的沙盒文件中,然后调用Android的Apk安装器去安装应用(这是一个单独的App),我们就需要 FileProvider 。

或者我们沙盒中的图片,需要发送到第三方的App里面展示,我们需要 FileProvider 。

话不多说,我们从常规的使用与示例上来看看怎么使用,清楚它的一些小细节。

一、常规使用与定义

一般来说没有什么特殊的需求,我们使用系统自带的 FileProvider 类来定义即可。

我们再清单文件注册我们的FileProvider

    <provider
        android:authorities="com.guadou.kt_demo.fileprovider"
        android:name="androidx.core.content.FileProvider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_path">
        </meta-data>
    </provider>

属性的一些说明:

  • authorities 是标记我们这个ContentProvider的唯一标识,是一个用于认证的暗号,我们一般默认使用包名+fileprovider来定义。(能不能使用别的,可以,abcd都行,但是没必要)
  • name 是具体的FileProvider类,如果是系统的,就用上面的这种,如果是自定义的,就写自定义FileProvider的全类名。
  • exported 是否限制其他应用获取此FileProvider。
  • grantUriPermissions 是否授权其他应用获取访问Uri权限,一般为true。
  • meta-data 和下面的 name 都是固定的写法,重点是 resource 需要自己实现规则,定义哪些私有文件会被提供访问。

看看我们定义的file_path文件:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <root-path name="myroot" path="." />
    <external-path name="external_file" path="." />
    <files-path name="inner_app_file" path="." />
    <cache-path name="inner_app_cache" path="." />
    <external-files-path name="external_app_file" path="." />
    <external-files-path name="log_file" path="log" />
    <external-cache-path name="external_app_cache" path="." />
    <external-cache-path name="naixiao_img" path="pos" />
</paths>

属性的含义如下:

  • root-path 从SD卡开始找 例如 storage/emulated/0/Android/data/com.guadou.kt_demo/cache/pos/naixiao-1122.jpg
  • external-path 从外置SD卡开始 例如 Android/data/com.guadou.kt_demo/cache/pos/naixiao-1122.jpg
  • external-files-path 外置沙盒file目录 例如 pos/naixiao-1122.jpg (真实目录在 Android/data/com.guadou.kt_demo/cache/pos/)
  • external-cache-path 外置沙盒cache目录 例如 naixiao-1122.jpg (真实目录在 Android/data/com.guadou.kt_demo/cache/)
  • files-path 和上面的同理,只是在内置的data/data目录下面
  • cache-path 和上面的同理,只是在内置的data/data目录下面

总共使用的就这么几个,大家可以看到我的定义,它是可以重复定义的。

比我我用到的这两个,是的同样类型的可以定义多个,

 <external-cache-path name="external_app_cache" path="." />
 <external-cache-path name="naixiao_img" path="pos" />

如果我定义了两个同类型的 external-cache-path ,他们的 name 你可以随便取,叫abc都行,主要是path , 推荐大家如果想暴露根目录就使用点. , 如果想暴露指定的目录就写对应的文件夹名称。

比我我现在有一个图片在这个目录下

storage/emulated/0/Android/data/com.guadou.kt_demo/cache/pos/naixiao-1122.jpg

通过 FileProvider 获取Uri 也是分优先顺序的。

比如我定义了pos的目录,那么打印如下:

打印Uri:content://com.guadou.kt_demo.fileprovider/naixiao_img/naixiao-1122.jpg

那我们现在把pos的去掉,只要这个。

<external-cache-path name="external_app_cache" path="." />

那么打印就如下:

打印Uri:content://com.guadou.kt_demo.fileprovider/external_app_cache/pos/naixiao-1122.jpg

换了name,多了pos的路径。

那我们都去掉呢?只保留外置SD卡和SD卡的规则。

    <root-path name="myroot" path="." />
    <external-path name="external_file" path="." />

那么打印就如下:

打印Uri:content://com.guadou.kt_demo.fileprovider/external_file/Android/data/com.guadou.kt_demo/cache/pos/naixiao-1122.jpg

就走到了外置SD卡的规则中去了。

那我们再去掉外置卡的规则。此时定义如下

 <root-path name="myroot" path="." />

此时打印如下:

打印Uri:content://com.guadou.kt_demo.fileprovider/myroot/storage/emulated/0/Android/data/com.guadou.kt_demo/cache/pos/naixiao-1122.jpg

可以看到它的匹配规则是一层一层往上找的,那我们再去掉SD卡的规则呢。。。

那不就空了吗,此时就崩溃报错了,这样是真拿不到Uri了...

使用示例:

说到这里,我们还没有真的使用 FileProvider ,下面我们以一个图片实例为例子演示如何发送到系统的App

    //测试FileProvider
    fun fileProvider1() {
        val drawable = drawable(R.drawable.chengxiao)
        val bd: BitmapDrawable = drawable as BitmapDrawable
        val bitmap = bd.bitmap
        FilesUtils.getInstance().saveBitmap(bitmap, "naixiao-1122.jpg")
        val filePath = FilesUtils.getInstance().sdpath + "naixiao-1122.jpg"
        YYLogUtils.w("文件原始路径:$filePath")
        val uri = FileProvider.getUriForFile(commContext(), "com.guadou.kt_demo.fileprovider", File(filePath))
        YYLogUtils.w("打印Uri:$uri")
        //到系统中找打开对应的文件
        openFile(filePath, uri)
    }
    private fun openFile(path: String, uri: Uri) {
        //取得文件扩展名
        val extension: String = path.substring(path.lastIndexOf(".") + 1)
        //通过扩展名找到mimeType
        val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
        YYLogUtils.w("mimeType: $mimeType")
        try {
            //构造Intent,启动意图,交由系统处理
            startActivity(Intent().apply {
                //临时赋予读写权限
                addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
                //表示用其它应用打开
                action = Intent.ACTION_VIEW
                //给Intent 赋值
                setDataAndType(uri, mimeType)
            })
        } catch (e: Exception) {
            e.printStackTrace()
            YYLogUtils.e("不能打开这种类型的文件")
        }
    }

很简单的一个例子,我们把drawable中的一个图片,保存到我们私有沙盒目录中,目录为

文件原始路径:/storage/emulated/0/Android/data/com.guadou.kt_demo/cache/pos/naixiao-1122.jpg

我们通过 FileProvider 拿到 content://开头的uri路径。然后通过Intent匹配找到对于的第三方App来接收。

运行结果如下:

打开了系统自带的图片查看器,还能编辑图片,查看信息等。

那么打印就如下:

打印Uri:content://com.guadou.kt_demo.fileprovider/external_app_cache/pos/naixiao-1122.jpg

content 是 scheme。

com.guadou.kt_demo.fileprovider 即为我们在清单文件中定义的 authorities,即是我们的FileProvider的唯一表示,在接收的时候作为host。

这样封装之后,当其他的App收到这个Uri就无法从这些信息得知我们的文件的真实路径,相对有安全保障。

其他场景中,比如沙盒中的Apk文件想要安装,也是一样的流程,我们需要赋予读写权限,然后设置DataAndType即可。代码的注释很详细,大家可以参考参考。

此时我们都是发送了一个Intent,让系统自己去匹配符合条件的Activity。那有没有可能我们自己做一个App去匹配它。

这... 好像还真行。

二、能不能自定义接收文件?

其实我们仿造系统的App的做法,我们在自定义的Activity中加入指定Filter即可,比如这里我需要接收图片,那么我定义如下的 intent-filter :

     <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".ReceiveImageActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="content" />
                <data android:scheme="file" />
                <data android:scheme="http" />
                <data android:mimeType="image/*" />
            </intent-filter>
        </activity>

都是一些固定的写法,我们在Activity上指明,它可以接收图片数据,此时我们再回到第一个App,发送图片,看看运行的效果:

之前还是图片查看器,现在可以选择我们自己的App来接收图片数据了,但是我们如何接收数据呢?

其实都是一些固定的代码,主要是拿到input流,然后操作流的处理。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_receive_image)
        if (intent != null && intent.action == Intent.ACTION_VIEW) {
            val uri = intent.data
            YYLogUtils.w("uri: $uri")
            if (uri != null && uri.scheme != null && uri.scheme == "content") {
                val fis = contentResolver.openInputStream(uri)
                if (fis != null) {
                    val bitmap = BitmapFactory.decodeStream(fis)
                    //展示
                    if (bitmap != null) {
                        val ivReveiverShow = findViewById<ImageView>(R.id.iv_reveiver_show)
                        ivReveiverShow.setImageBitmap(bitmap)
                    }
                }
            }
        }
    }

最简单的做法,直接根据uri打开输入流,然后我们可以通过 BitmapFactory 就可以拿到 Bitmap了,就能展示图片到ImageView上面。

效果如图:

甚至我们拿到了 input 流,我们还能对流进行copy 操作,把你的图片保存到我自己的沙盒目录中,例如:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_receive_image)
        if (intent != null && intent.action == Intent.ACTION_VIEW) {
            val uri = intent.data
            YYLogUtils.w("uri: $uri")
            if (uri != null && uri.scheme != null && uri.scheme == "content") {
                val fis = contentResolver.openInputStream(uri)
                if (fis != null) {
                    val inBuffer = fis.source().buffer()
                    val outFile = File(getExternalFilesDir("xiaoxiao"), "naixiao5566.jpg")
                    outFile.sink().buffer().use {
                        it.writeAll(inBuffer)
                        inBuffer.close()
                    }
                    YYLogUtils.w("存放的路径:${outFile.absolutePath}")
                    //展示
                    val ivReveiverShow = findViewById<ImageView>(R.id.iv_reveiver_show)
                    ivReveiverShow.extLoad(outFile.absolutePath)
                }
            }
        }
    }

保存到自己的沙盒文件之后,我们看一看效果:

好像还真的能行,秀啊。

那此时有人还会有一个疑问,你这方法都是我主动的发送给别人去展示,去操作!这都不是事,关键是能不能让别人主动的来操作、玩弄我的沙盒文件?

比如我做的App想获取微信,支付宝这些别人的App的沙盒中的图片?行不行?有没有方法可以做到?

这...,你别逗我了。

三、能不能主动查询对方的沙盒?

转头一想,好像还真行,有操作空间啊... 既然 FileProvider 是继承自 ContentProvider 。那凭什么我们的App都能获取到别人App的数据库了,不能获取别人的沙盒文件呢?那数据库文件不也存在沙盒中么?

例如联系人App,我们开发的第三方App可以通过 ContentProvider 获取到联系人App中的联系人数据,那么只要第三方的App定义好对应的 ContentProvider 我不就能获取到它沙盒的文件了吗?

说到就做,我们先把FileProvider设置为可访问

     <provider
        android:name=".MyFileProvider"
        android:authorities="com.guadou.kt_demo.fileprovider"
        android:exported="true"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_path">
        </meta-data>
    </provider>

是的,android:exported="true" 设置成功之后我们直接通过 contentResolver 去查询不就好了吗?

先运行一下试试! 运行就崩了?

什么鬼哦,看看FileProvider的代码,原来不允许开放

原来 FileProvider的 exported 和 grantUriPermissions 都是指定的写法,不能改变,并且不允许暴露,不允许给别的App主动访问!

这和我们的需求不符合啊,我就要主动访问,既然你不行,那我不用你行了吧!我继承 ContentProvider 行了吧!我自己实现文件获取、Cursor封装行了吧!

不皮了,其实我们直接通过继承 ContentProvider 并且允许 exported ,然后我们通过自己实现的query方法,返回指定的Cursor信息,就可以实现!

部分代码如下:

public class MyFileProvider extends ContentProvider {
    @Override
    public void attachInfo(Context context, ProviderInfo info) {
        super.attachInfo(context, info);
        mStrategy = getPathStrategy(context, info.authority);
    }
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        YYLogUtils.w("走到query方法");
        final File file = mStrategy.getFileForUri(uri);
        YYLogUtils.w("file:" + file);
        if (!file.exists()) {
            return null;
        }
        boolean directory = file.isDirectory();
        if (directory) {
            YYLogUtils.w("说明是文件夹啊!");
            File[] files = file.listFiles();
            for (File childFile : files) {
                if (childFile.isFile()) {
                    String name = childFile.getName();
                    String path = childFile.getPath();
                    long size = childFile.length();
                    Uri uriForFile = mStrategy.getUriForFile(childFile);
                    YYLogUtils.w("name:" + name + " path:" + path + " size: " + size +" uriForFile:"+uriForFile);
                }
            }
            //自己遍历封装Cursor实现
            return null;
        } else {
            YYLogUtils.w("说明是文件啊!");
            if (projection == null) {
                projection = COLUMNS;
            }
            String[] cols = new String[projection.length];
            Object[] values = new Object[projection.length];
            int i = 0;
            for (String col : projection) {
                if (OpenableColumns.DISPLAY_NAME.equals(col)) {
                    cols[i] = OpenableColumns.DISPLAY_NAME;
                    values[i++] = file.getName();
                } else if (OpenableColumns.SIZE.equals(col)) {
                    cols[i] = OpenableColumns.SIZE;
                    values[i++] = file.length();
                }
            }
            cols = copyOf(cols, i);
            values = copyOf(values, i);
            final MatrixCursor cursor = new MatrixCursor(cols, 1);
            cursor.addRow(values);
            return cursor;
        }
    }
}

我简单的做了文件和文件夹的处理,并不完整,如果是文件我们可以直接返回一个简单的cursor,如果是文件夹需要大家自己拼接子文件的cursor并返回。

接下来我们看看其他App如何主动这些文件,在另一个App中我们先加上权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.hongyegroup.receiver">
    <queries>
        <provider android:authorities="com.guadou.kt_demo.fileprovider" />
    </queries>
    ...
</manifest>

然后我们直接使用 contentResolver.query

  private fun queryFiles() {
        val uri = Uri.parse("content://com.guadou.kt_demo.fileprovider/external_app_cache/pos/naixiao-1122.jpg")
        val cursor = contentResolver.query(uri, null, null, null, null)
        if (cursor != null) {
            while (cursor.moveToNext()) {
                val fileName = cursor.getString(cursor.getColumnIndex("_display_name"));
                val size = cursor.getLong(cursor.getColumnIndex("_size"));
                YYLogUtils.w("name: $fileName  size: $size")
                Toast.makeText(this, "name: $fileName  size: $size", Toast.LENGTH_SHORT).show()
            }
            cursor.close()
        } else {
            YYLogUtils.w("cursor-result: 为空啊")
            Toast.makeText(this, "cursor-result: 为空啊", Toast.LENGTH_SHORT).show()
        }
    }

如果我们知道它的指定文件Uri,我们可以通过query查询到文件的一些基本信息。具体是哪些信息,需要对方提供和定义。

如果想操作对方的文件,由于我们已经拿到了对方的Uri,我们可以直接通过inputStream来操作,例如:

        val fis = contentResolver.openInputStream(uri)
        if (fis != null) {
            val inBuffer = fis.source().buffer()
            val outFile = File(getExternalFilesDir(null), "abc")
            outFile.sink().buffer().use {
                it.writeAll(inBuffer)
                inBuffer.close()
            }
            YYLogUtils.w("保存文件成功")
        }

这些都是简单的基本操作,重点是如果我不知道具体的文件呢?

我就想把对方App的沙盒中的文件夹下面的全部文件都拿到,行不行?

行!只要对方App配合就行,例如:

     private fun queryFiles() {
        val uri = Uri.parse("content://com.guadou.kt_demo.fileprovider/external_app_cache/pos/")
        val cursor = contentResolver.query(uri, null, null, null, null)
        if (cursor != null) {
            while (cursor.moveToNext()) {
                val fileName = cursor.getString(cursor.getColumnIndex("_display_name"));
                val size = cursor.getLong(cursor.getColumnIndex("_size"));
                val uri = cursor.getString(cursor.getColumnIndex("uri"));
                val fileUri = Uri.parse(uri)
                //就可以使用IO或者BitmapFactory来操作流了
                YYLogUtils.w("name: $fileName  size: $size")
                Toast.makeText(this, "name: $fileName  size: $size", Toast.LENGTH_SHORT).show()
            }
            cursor.close()
        } else {
            YYLogUtils.w("cursor-result: 为空啊")
            Toast.makeText(this, "cursor-result: 为空啊", Toast.LENGTH_SHORT).show()
        }
    }

这样就是把对方外置SD卡下面的cache目录下的pos目录下的全部文件拿到手,当然了,这个需要对方App封装对应的cursor才行哦。

打印的Log如下:

只要对方封装的Cursor,我们可以把名字,大小,uri等信息都封装到Cursor中,提供给对方获取。

总结

FileProvider的主要应用场景就是分享,把自己沙盒中的文件分享,主动提供给其他匹配的App去使用。

使用其他App的图片?查询了目前市场上的主流App,微信,支付宝,闲鱼,美团,等App,例如在保存文件的时候都没有存在自己的沙盒中了,都是默认在DCIM或Pictures中,并存入 MediaStore 保存到图库中。

这样就算公共目录,无需FileProvider,大家直接通过 MediaStore 就能获取和使用。

而如果想主动访问其他App的沙盒文件,则需要对方App全方位配合,一般用于自家App的全家桶之类的应用。相对来说相对应用场景比较少。

不是做不到,只是大家觉得没有必要而已,毕竟定义和使用相对复杂,并且有暴露风险,被攻击的风险等。

本文全部代码均以开源,源码在此

以上就是Android中FileProvider的各种场景应用详解的详细内容,更多关于Android FileProvider应用场景的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android 动态加载 so实现示例详解

    目录 背景 so动态加载介绍 从一个例子出发 so库检索与删除 动态加载so 结束了吗? ELF文件 扩展 总结 背景 对于一个普通的android应用来说,so库的占比通常都是巨高不下的,因为我们无可避免的在开发中遇到各种各样需要用到native的需求,所以so库的动态化可以减少极大的包体积,自从2020腾讯的bugly团队发部关于动态化so的相关文章后,已经过去两年了,相关文章,经过两年的考验,实际上so动态加载也是非常成熟的一项技术了. 但是很遗憾,许多公司都还没有这方面的涉略又或者说不知

  • Android数据缓存框架内置ORM功能使用教程

    目录 使用教程如下 配置初始化 注解详解 CRUD操作 其他注意事项 使用教程如下 配置初始化 Orm.init(this, OrmConfig.Builder() .database("dcache_sample") .tables(Account::class.java) .version(1) .build()) 在自定义的Application类的入口加入一行配置,database为数据库名,version从1开始每次递增1,tables用来配置需要初始化的表,dcache中所

  • Android neon 优化实践示例

    目录 搭建实验环境 小试牛刀 实战尝试 CMake添加汇编支持 实现汇编Neon优化 搭建实验环境 首先新建一个包含native代码的项目: 然后在gradle中添加对neon的支持: externalNativeBuild { cmake { cppFlags "-std=c++14" arguments "-DANDROID_ARM_NEON=TRUE" } } 这样,项目就可以支持neon加速了. 小试牛刀 一个最简单的neon编程的流程大致是这样的: 1.装

  • Android 性能优化实现全量编译提速的黑科技

    目录 一.背景描述 二.效果展示 2.1.测试项目介绍 三.思路问题分析与模块搭建: 3.1.思路问题分析 3.2.模块搭建 四.问题解决与实 编译流程启动,需要找到哪一个 module做了修改 module 依赖关系获取 module 依赖关系 project 替换成 aar 技术方案 hook 编译流程 五.一天一个小惊喜( bug 较多) 5.1 output 没有打包出 aar 5.2 发现运行起来后存在多个 jar 包重复问题 5.3 发现 aar/jar 存在多种依赖方式 5.4 发

  • Android NDK 开发中 SO 包大小压缩方法详解

    目录 背景 1.STL的使用方式 2.不使用Exception和RTTI RTTI Exception 3.使用 gc-sections去除没有用到的函数 4.去除冗余代码 5.设置编译器的优化flag 6.设置编译器的 Visibility Feature 7.设置编译器的Strip选项 8.去除C++代码中的iostream相关代码 总结 背景 这周在做Yoga包的压缩工作.Yoga本身是用BUCK脚本编译的,而最终编译出几个包大小大总共约为7M,不能满足项目中对于APK大小的限制,因此需要

  • Android开发OkHttp执行流程源码分析

    目录 前言 介绍 执行流程 OkHttpClient client.newCall(request): RealCall.enqueue() Dispatcher.enqueue() Interceptor RetryAndFollowUpInterceptor BridgeInterceptor CacheInterceptor 前言 OkHttp 是一套处理 HTTP 网络请求的依赖库,由 Square 公司设计研发并开源,目前可以在 Java 和 Kotlin 中使用. 对于 Androi

  • Android中FileProvider的各种场景应用详解

    目录 前言 一.常规使用与定义 二.能不能自定义接收文件? 三.能不能主动查询对方的沙盒? 总结 前言 有部分同学只要是上传或者下载,只要用到了文件,不管三七二十一写个 FileProvider 再说. 不是每一种情况都需要使用 FileProvider 的,啥?你问行不行?有没有毛病? 这... 写了确实可以,没毛病!但是这没有必要啊. 如果不需要FileProvider就不需要定义啊,如果定义了重复的 FileProvider,还会导致清单文件合并失败,需要处理冲突,从而引出又一个问题,解决

  • Android 中Fragment与Activity通讯的详解

    Android 中Fragment与Activity通讯的详解 与activity通讯 尽管fragment的实现是独立于activity的,可以被用于多个activity,但是每个activity所包含的是同一个fragment的不同的实例. Fragment可以调用getActivity()方法很容易的得到它所在的activity的对象,然后就可以查找activity中的控件们(findViewById()). 例如: ViewlistView =getActivity().findView

  • Android中asset和raw的区别详解

    *res/raw和assets的相同点: 1.两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制. *res/raw和assets的不同点: 1.res/raw中的文件会被映射到R.java文件中,访问的时候直接使用资源ID即R.id.filename:assets文件夹下的文件不会被映射到 R.java中,访问的时候需要AssetManager类. 2.res/raw不可以有目录结构,而assets则可以有目录结构,也就是assets目录下可以再建立文件夹 *读取文件资源

  • Android 中Lambda表达式的使用实例详解

     Android 中Lambda表达式的使用实例详解 Java8 中着实引入了一些非常有特色的功能,如Lambda表达式.streamAPI.接口默认实现等等.Lambda表达式在 Android 中最低兼容到 Android2.3 系统,兼容性还是不错的,Lambda表达式本质上是一种匿名方法,它既没有方法名,也没有访问修饰符和返回值类型,使用它编写的代码将更加简洁易读. 1.Lambda表达式的基本写法 如果想要在 Android 项目中使用 Lambda表达式 或者 Java8 的其他新特

  • Android中判断网络是否连接实例详解

    Android中判断网络是否连接实例详解 在android中,如何监测网络的状态呢,这个有的时候也是十分重要的,方法如下: public class ConnectionDetector { private Context _context; public ConnectionDetector(Context context){ this._context = context; } public boolean isConnectingToInternet(){ ConnectivityMana

  • Android中关于Notification及NotificationManger的详解

    Android状态栏提醒 在Android中提醒功能也可以用AlertDialog,但是我们要慎重的使用,因为当使用AlertDialog的时候,用户正在进行的操作将会被打断,因为当前焦点被AlertDialog得到.我们可以想像一下,当用户打游戏正爽的时候,这时候来了一条短信.如果这时候短信用AlertDialog提醒,用户必须先去处理这条提醒,从而才能继续游戏.用户可能会活活被气死.而使用Notification就不会带来这些麻烦事,用户完全可以打完游戏再去看这条短信.所以在开发中应根据实际

  • Android中使用HTTP服务的用法详解

    在Android中,除了使用Java.NET包下的API访问HTTP服务之外,我们还可以换一种途径去完成工作.Android SDK附带了Apache的HttpClient API.Apache HttpClient是一个完善的HTTP客户端,它提供了对HTTP协议的全面支持,可以使用HTTP GET和POST进行访问.下面我们就结合实例,介绍一下HttpClient的使用方法. 我们新建一个http项目,项目结构如图: 在这个项目中,我们不需要任何的Activity,所有的操作都在单元测试类H

  • Android中Serializable和Parcelable序列化对象详解

    本文详细对Android中Serializable和Parcelable序列化对象进行学习,具体内容如下 学习内容: 1.序列化的目的 2.Android中序列化的两种方式 3.Parcelable与Serializable的性能比较 4.Android中如何使用Parcelable进行序列化操作 5.Parcelable的工作原理 6.相关实例  1.序列化的目的 1).永久的保存对象数据(将对象数据保存在文件当中,或者是磁盘中 2).通过序列化操作将对象数据在网络上进行传输(由于网络传输是以

  • Android中从图库中选取图片实例详解

    android 从图库中选取图片 在android中,如何从图库gallary中挑选图片呢,其实很简单,步骤如下 1) 设计一个imageview,用来显示图库选出来的图片 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientati

  • Android中检查、设置默认程序详解

    Android作为一个伟大的系统,自然提供了设置默认打开程序的实现.在这篇文章中,我会介绍如何在Android系统中设置默认的程序. 在设置默认程序之前,无非有两种情况,一种是已经有默认的程序,另一种则是没有任何默认程序. 检测是否有默认的程序 检查是必须的,因为结果关乎着我们下一步该怎么做. 复制代码 代码如下: public void testGetDefaultActivity() {     PackageManager pm = mContext.getPackageManager()

随机推荐