关于QUERY_ALL_PACKAGES权限问题

Android11之后,resolveActivity、查询某个APP是否已安装等需要特殊处理。

要么加QUERY_ALL_PACKAGES权限,要么就在清单文件中使用<queries>标签。

由于Google Play的政策:

如果您的应用不需要使用 QUERY_ALL_PACKAGES 权限,请从您的应用清单中移除该权限。如果应用需要此权限,您现在可以在 Play 管理中心内提交声明表单。

您需要提供:

1.对需要此权限的应用核心功能的说明
2.展示需要此权限的应用核心功能的短视频
如需了解您在该表单中将需要回答哪些问题以便做好准备,请参阅这篇帮助中心文章。

自 7 月 12 日起,如果缺少此声明,您将无法提交新应用和应用更新。请您务必在 7 月 12 日之前提交此声明,或者从您的应用清单中移除该权限。从 7 月 12 日起,对于不符合政策要求或未提交此声明表单的应用,我们可能会将其从 Google Play 下架。

感谢您一直以来与我们通力合作,共同努力让 Google Play 成为值得您和用户信赖的可靠平台。

如果用QUERY_ALL_PACKAGES权限,在用户看来,你调用API的时候会出现“XXX”正在查询你安装的应用列表,这样的提示。就会认为你是流氓应用。

因此我们选择使用<queries>标签:

<queries>
        <package android:name="${applicationId}" />

        <!--WhatsApp-->
        <package android:name="com.whatsapp" />
        <!--Facebook-->
        <package android:name="com.facebook.katana" />
        <!--Line客户端-->
        <package android:name="jp.naver.line.android" />
        <!--Twitter-->
        <package android:name="com.twitter.android" />
        <!--WeChat-->
        <package android:name="com.tencent.mm" />
        <!--QQ-->
        <package android:name="com.tencent.mobileqq" />
        <!--instagram-->
        <package android:name="com.instagram.android" />
        <!--Messenger-->
        <package android:name="com.facebook.orca" />

        <!--拍照应用-->
        <intent>
            <action android:name="android.media.action.IMAGE_CAPTURE" />
        </intent>

        <!--Alipay-->
        <intent>
            <action android:name="android.intent.action.VIEW" />
            <data
                android:host="*"
                android:scheme="alipays" />
        </intent>

        <!--应用商店-->
        <intent>
            <action android:name="android.intent.action.VIEW" />
            <data
                android:host="*"
                android:scheme="market" />
        </intent>
        <intent>
            <action android:name="android.intent.action.VIEW" />
            <data
                android:host="play.google.com"
                android:scheme="https" />
        </intent>

        <!--webview 中的 intent-->
        <intent>
            <action android:name="android.intent.action.VIEW" />
            <data
                android:host="*"
                android:scheme="intent" />
        </intent>
        <!--Line群-->
        <intent>
            <action android:name="android.intent.action.VIEW" />
            <data
                android:host="ti"
                android:scheme="line" />
        </intent>

    </queries>

这样一来,在使用resolveActivity或者getPackageInfo API的时候就不会出现问题了。

dump Java Thread 的几种状态及其含义

The values of the Java thread state and the internal VM thread state can be:

  • R – Runnable – the thread is able to run when given the chance.
  • CW – Condition Wait – the thread is waiting. For example, because:
    • The thread has been blocked for I/O
    • A wait() method is called to wait on a monitor being notified
    • The thread is synchronizing with another thread with a join() call
  • S – Suspended – the thread has been suspended by another thread.
  • Z – Zombie – the thread has been killed.
  • P – Parked – the thread has been parked by the new concurrency API (java.util.concurrent).
  • B – Blocked – the thread is waiting to obtain a lock that something else currently owns.

并行收集器

并行收集器也称作吞吐量优先收集器,是一种跟串行收集器类似的分代/世代收集器。跟串行收集器不同的是,并行收集器使用多线程的方式来加速垃圾回收。

使用-XX:+UseParallelGC参数开启并行收集器。默认情况下,使用此参数后,minor收集和major收集都会采用并行的方式,进一步较少垃圾回收的负载。

并行垃圾收集器的线程数量

在具有N(N大于8)个物理线程的机器上,串行收集器使用N的分数作为垃圾回收线程数量。

比例大约为5/8 * N。如果N小于8,则使用N作为线程数。在有些平台上,这个数值为5/16*N。此数值也可以通过命令行参数指定。在单处理器的机器上,并行收集器的表现可能不如Serial收集器,因为并行收集器有较高的开销,例如同步。当应用程序运行在配置了中大型堆内存的虚拟机上时,在双核环境下,并行收集略好与串行收集。在更多核的机器上,并行收集的性能优势更为显著。

阅读更多

HotSpot中的垃圾收集器

Java HotSpot虚拟机包含了三类垃圾收集器,每一类都有不同的性能特征。

串行(Serial)收集器

串行收集器在单线程中进行垃圾回收,由于没有线程之间的切换,因此垃圾回收工作相对较高效。

对单核处理器的硬件来说,串行收集器是最佳选择。因为它无法发回多核设备的优势。只适合小型应用程序。

Serial收集器在某些设备和操作系统上是默认配置,当然你也可以可以使用

-XX:+UseSerialGC

参数手动指定HotSpot虚拟机使用串行收集器。

并行(Parallel)收集器

parallel收集器也被称为 throughput collector(吞吐量优先)收集器,它与Serial收集器的主要区别在于,垃圾回收过程在多线程中进行,加速了垃圾回收过程。parallel收集器一般用于运行在多核、多线程设备上的中大型应用程序。

可以通过

-XX:+UseParallelGC

启用parallel收集器。

阅读更多

HotSpot中的“世代/分代”(Generations)概念 for Java 10

Java的优势之一是它对开发者屏蔽了复杂的内存分配和垃圾回收,但当垃圾回收成为瓶颈时,了解它的内部实现机制是有必要的。

当运行时没有任何指针指向一个对象时,那这个对象就是个“垃圾”。最直截了当的垃圾收集算法遍历所有“可达”对象,剩下所有的对象都视为“垃圾”😀。这种算法的时间消耗跟“存活”的对象数量成正比,对于持有大量“存活”对象的大型程序禁止这么干。

采用分代收集的虚拟机整合了不同的垃圾回收算法。不成熟的垃圾收集器检测堆中每个存活的对象,而分代收集则观测根据程序运行经验以最少的工作完成垃圾回收。最重要的观测属性是“weak generational hypothesis”(弱世代假设),这种状态的大多数对象都存活很短的时间。

下图中的蓝色区域是对象常规的寿命分布。X轴是以字节为单位的对象寿命,Y轴的字节数量是相应生存期的对象的总字节数。左边的断崖表示对象在创建之后很快被回收(即对象已“死”)。例如Iterator,通常指存活一次迭代。

对象寿命
阅读更多

Spine导出格式说明之——JSON格式(上)

Spine可以导出为JSON或者二进制格式。JSON可读性强、便于检查和修改但体积大;二进制可读性差,修改成本高,但文件体积小,加载速度快。

可以说Spine导出的JSON格式数据是骨骼数据实例的序列化版本。它由一系列的骨骼(bones)、插槽(slots)、皮肤(skins)和动画(animations)组成。

骨架(Skeleton)

skeleton节点存储骨架的元数据,结构如下:

阅读更多

JNI之四:JNI函数(下)

相关链接:JNI函数(上)


对象操作


AllocObject

jobject AllocObject(JNIEnv *env, jclass clazz);

不调用构造函数的情况下,分配一个新的对象。返回对象引用。

注意:java语言规范,12.6.1 实现finalize:“在对象o上调用了Object的构造方法,且构造方法调用成功,否则对象o不可终结”。因为AllocObject()未调用构造方法,所以通过此函数创建的对象不符合终结机制(finalization),不会被终结。

clazz参数不可为数组class。

阅读更多

Retrofit+OkHttp+RxJava运行时修改POST请求的URL

在使用Retrofit时,如果我们想变更某个请求的URL,GET请求的话,可以使用@Url 注解,但如果是POST请求,是不能直接这么干的。

我的做法是在Retrofit.create(XXXX.class)之前,给OkHttp添加拦截器,拦截器识别请求header中是否带着我们预先自定义的参数。在请求发起时header中增加key:NEW_HOST_URL,value为将于替换的新地址。

拦截器的代码如下:

阅读更多

在Java代码中移除ConstraintLayout的layout_constraintHeight_percent或layout_constraintWidth_percent属性

有写场景需要在Java代码中移除xml中配置的百分比属性,如:

app:layout_constraintHeight_percent="0.3"
app:layout_constraintWidth_percent="0.722"

在Java中移除以百分比属性的具体操作:

if (lp instanceof ConstraintLayout.LayoutParams) {
    ((ConstraintLayout.LayoutParams) lp).matchConstraintPercentHeight = 1f;
    ((ConstraintLayout.LayoutParams) lp).matchConstraintDefaultHeight = 0;/*spread 默认的,非percent*/
}
阅读更多