TextView文字颜色渐变
1 | import android.graphics.LinearGradient |
使用方式,调用扩展方法即可
textView.setHorizontalGradientTextColor(Color.RED, Color.GREEN)
1 | import android.graphics.LinearGradient |
使用方式,调用扩展方法即可
textView.setHorizontalGradientTextColor(Color.RED, Color.GREEN)
应用签名: https://source.android.google.cn/docs/security/features/apksigning?hl=zh-cn
Android 7.0以下版本, 只能用旧签名方案 V1 scheme (JAR signing)
Android 7.0开始, 谷歌增加新签名方案 V2 Scheme (APK Signature)
V2签名优点很明显:
Android 9 支持 APK 密钥轮替,这使应用能够在 APK 更新过程中更改其签名密钥。为了实现轮替,APK 必须指示新旧签名密钥之间的信任级别。v3 在 APK 签名分块中添加了有关受支持的 SDK 版本和 proof-of-rotation 结构体的信息,以允许使用新旧密钥。
Android 11 添加了对 APK 签名方案 v4 的支持。此方案会在单独的文件 (apk-name.apk.idsig) 中生成一种新的签名。此方案支持 ADB 增量 APK 安装,这样会加快 APK 安装速度。v4 签名需要 v2 或 v3 签名作为补充。
ADB 增量 APK 安装
在设备上安装大型(2GB 以上)APK 可能需要很长的时间,即使应用只是稍作更改也是如此。ADB(Android 调试桥)增量 APK 安装可以安装足够的 APK 以启动应用,同时在后台流式传输剩余数据,从而加速这一过程。如果设备支持该功能,并且您安装了最新的 SDK 平台工具,adb install 将自动使用此功能。如果不支持,系统会自动使用默认安装方法。
https://developer.android.google.cn/about/versions/11/features运行以下 adb 命令以使用该功能。如果设备不支持增量安装,该命令将会失败并输出详细的解释。
adb install –incremental
在运行 ADB 增量 APK 安装之前,您必须先为 APK 签名并创建一个 APK 签名方案 v4 文件。必须将 v4 签名文件放在 APK 旁边,才能使此功能正常运行。
综上,可以看到APK v4是面向ADB即开发调试的,而如果我们没有签名变动的需求也可以不考虑APK v3,所以目前国内大部分还停留在APK v2。
build.gradle
中配置支持的签名方案1 | android { |
C:\Users\用户名\.android\debug.keystore
apksigner官网:https://developer.android.google.cn/studio/command-line/apksigner?hl=zh-cn
Android中APK签名工具之jarsigner和apksigner详解:https://www.jb51.net/article/141954.htm
Android的:https://zhuanlan.zhihu.com/p/541983756
jarsigner
是JDK提供的针对jar包签名的通用工具,位于 JDK/bin/jarsigner.exe
,仅支持V1签名apksigner
是Google 官方提供的针对 Android apk 签名及验证的专用工具,位于 Android SDK/build-tools/SDK版本/apksigner.bat
,支持apk的多种签名方案不管是 apk 包,还是 jar 包,本质都是 zip 格式的压缩包,所以它们的签名过程都差不多(仅限V1签名),以上两个工具都可以对 Android apk 包进行签名.
注意:apksigner 工具默认同时使用V1+V2+V3签名方案,以兼容 Android7.0以下系统版本
进入Android SDK/build-tools/SDK版本
,输入:
1 | .\apksigner sign --v1-signing-enabled true --v2-signing-enabled true --ks D:\apk\test.jks --in D:\apk\xiaomi-unsign.apk --out D:\apk\xiaomi-signed.apk |
参数说明:
–v1-signing-enabled <true | false>
确定 apksigner 是否会使用基于 JAR 的传统签名方案为给定的 APK 软件包签名。默认情况下,该工具会使用 –min-sdk-version 和 –max-sdk-version 的值来决定何时采用此签名方案。
–v2-signing-enabled <true | false>
确定 apksigner 是否会使用 APK 签名方案 v2 为给定的 APK 软件包签名。默认情况下,该工具会使用 –min-sdk-version 和 –max-sdk-version 的值来决定何时采用此签名方案。
–v3-signing-enabled <true | false>
确定 apksigner 是否会使用 APK 签名方案 v3 为给定的 APK 软件包签名。默认情况下,该工具会使用 –min-sdk-version 和 –max-sdk-version 的值来决定何时采用此签名方案。
–v4-signing-enabled <true | false | only>
确定 apksigner 是否会使用 APK 签名方案 v4 为给定的 APK 软件包签名。此方案会在单独的文件 (apk-name.apk.idsig) 中生成签名。如果为 true 并且 APK 未签名,则系统会根据 –min-sdk-version 和 –max-sdk-version 的值生成 v2 或 v3 签名。然后,该命令会根据已签名的 APK 的内容生成 .idsig 文件。
使用 only 仅生成 v4 签名,而不会修改 APK 及其在调用前具有的任何签名。如果 APK 没有 v2 或 v3 签名,或者签名使用的密钥不同于为当前调用提供的密钥,则 only 会失败。
默认情况下,该工具会使用 –min-sdk-version 和 –max-sdk-version 的值来决定何时采用此签名方案。
1 | .\apksigner verify -v D:\apk\xiaomi-signed.apk |
原文地址:https://juejin.cn/post/7009204672225345549
Android 7.0之前,文件的Uri以 file:///
形式提供给其他app访问。
Android 7.0之后,分享文件的Uri发生了变化。为了安全起见, file:///
形式的Uri不能正常访问。官方提供了 FileProvider
,FileProvider生成的Uri会以 content://
的形式分享给其他app使用。
在7.0以前,为了访问 file:///
形式的Uri,我们必须修改文件的权限。修改后的权限对所有app都是有效的,这样的行为是不安全的。 content://
形式的Uri让Android的文件系统更安全,对于分享的文件,接收方app只拥有临时的权限,减少了我们app内部的文件被其他app恶意操作的行为。
在manifest文件 <application></application>
标签中添加pvodier标签,配置如下。
1 | <manifest> |
android:name
指定Provider的类名,使用官方提供的androidx.core.content.FileProvider
。
android:authorities
相当于一个用于认证的暗号,在分享文件生成Uri时,会通过它的值生成对应的Uri。。值是一个域名,一般格式为 <包名>.fileprovider</包名>
。
android:exported
设置为false,FileProvider不需要公开。
android:grantUriPermissions
设置为true,这样就能授权接收端的app临时访问权限了。
在res/xml
中创建一个资源文件(如果xml目录不存在,先创建),名字随便(一般叫file_paths.xml
)。
1 | <paths xmlns:android="http://schemas.android.com/apk/res/android"> |
<paths></paths>
必须有1个或多个子标签,每个子标签代表要请求的私有文件目录。不同的子标签代表不同的目录类型。
在 <provider></provider>
标签中添加 <meta-data></meta-data>
子标签。
设置 <meta-data></meta-data>
的属性 android:name
值为 android.support.FILE_PROVIDER_PATHS
,属性 android:resouce
的值为刚才我们创建的path文件名。
<paths></paths>
的每个子标签必须有 path
属性,代表content Uris的路径。 name
不需要和path保持一样,只是一个名称。
子标签有以下几种。
1 | <files-path name="my_files" path="path" /> |
代表内部存储的files目录,与 Context.getFilesDir()
获取的路径对应。
最终生成的Uri格式为:authorities/pathname/filename
示例:
1 | content: |
1 | <cache-path name="name" path="path" /> |
代表内部存储的cache目录,与 Context.getCacheDir()
获取的路径对应。
1 | <external-path name="name" path="path" /> |
代表外部存储(sdcard)的cache目录,与 Environment.getExternalStorageDirectory()
获取的路径对应。
1 | <external-files-path name="name" path="path" /> |
代表app的外部存储的根目录,与 Context#getExternalFilesDir(String) Context.getExternalFilesDir(null)
获取的路径对应。
1 | <external-cache-path name="name" path="path" /> |
代表app外部缓存区域的根目录,与 Context.getExternalCacheDir()
获取的路径对应。
1 | <external-media-path name="name" path="path" /> |
代表app外部存储媒体区域的根目录,与 Context.getExternalMediaDirs()
获取的路径对应。
注意: 这个目录只在API 21(也就是Android 5.0)以上的系统上才存在。
为了让其他app使用Content Uri,我们的app必须提前生成Uri。
1 | File file = new File(Context.getFilesDir(), "my_log"); |
这里注意获取目录,在配置paths时我们讲了,paths的子标签必须和获取目录的代码保持对应。这里我们用的是 Context.getFilesDir()
,所以paths文件中必须包含 files-path
子标签,不然别的app获取uri时会出现异常。
最终生成Uri是使用的 FileProvider.getUriForFile()
。第一个参数就是 provider
中设置的 authorities
属性值。
1 | intent.putExtra(Intent.EXTRA_STREAM, contentUri); |
使用 Intent.setDate
或 Intent.setClipData()
。
1 | intent.setClipDataClipData.newRawUri("", contentUri) |
最后使用 startActivity(intent)
启动分享操作。
分享一般只有这读取和写入2种权限,根据需要传入 Intent.addFlags()
中。
1 | Intent intent = new Intent(Intent.ACTION_SEND); |
这是因为第三方库中存在很多重名的META-INF文件,在打包的时候去除即可
1 | android { |
在执行gradlew命令打包时遇到这个错误,肯定是https证书有问题。
解决方案:如果支持http的话就使用http
1 | Could not resolve com.bytedanceapi:ttsdk-ttmp:1.36.2.25.pcdn. |
把项目根目录的build.gradle
文件中所有的https://artifact.bytedance.com/
替换为http://artifact.bytedance.com/
即可
升级到 Java 16 以上,AndroidStudio编译遇到错误。
Unable to make field private final java.lang.String java.io.File.path accessible: module java.base does not “opens java.io” to unnamed module @fb04536
解决方案一:
gradle-wrapper
属性中的 gradle 版本更改为 7.1.1(6.x 不支持 java 16)gradle.properties
中添加以下行1 | org.gradle.jvmargs=-Xmx1536m \ |
解决方案二:
升级build-gradlew版本。 将项目根目录的 build.gradle
文件中classpath 'com.android.tools.build:gradle:4.2.2'
升级为classpath 'com.android.tools.build:gradle:7.2.1'
RecyclerView+SnapHelper实现ViewPager滑动效果
SnapHelper结合RecyclerView使用,能很方便的实现ViewPager滑动效果。SnapHelper是一个抽象类,Google内置了两个默认实现类,LinearSnapHelper和PagerSnapHelper。
使当前Item居中显示,常用场景是横向的RecyclerView, 类似ViewPager效果,但是又可以快速滑动多个条目。
1 | LinearLayoutManager manager = new LinearLayoutManager(getContext()); |
使RecyclerView像ViewPager一样的效果,每次只能滑动一页。
1 | LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); |
Update your browser to view this website correctly.&npsb;Update my browser now