前言
根据工信部【2020】文件:重点整治APP、SDK未告知用户收集个人信息的目的、方式、范围且未经用户同意,私自收集用户个人信息的行为。APP、SDK非服务所必须或无合理应用场景,特别是在静默状态下或在后台运行时,超范围手机使用个人信息的行为。在这一背景下,国内各大应用商店开始对上架的应用开展隐私合规检测,对提交到应用市场的App进行了整改,只有符合法律法规及应用隐私合规上架标准要求的app才能顺利上架并展示给用户下载使用。
存在的问题
-
未经用户同意,违规收集个人信息;
-
APP未见向用户明示个人信息收集的目的、方式和范围,违规使用个人信息;
-
APP第一次启动需明确提示隐私政策和用户注册协议;
-
强制用户使用定向推送功能;
-
APP强制、频繁、过度索取权限;
-
APP频繁自启动和关联启动;
-
欺骗误导用户提供个人信息等。
-
APP存在频繁自启动和关联启动
-
第三方SDK未做说明
-
隐私政策内容无开发者名称和联系方式
-
未提供注销功能
-
存在广告营销隐私政策未做说明
-
存在功能不可用问题或点击无响应问题
......
React Native App启动页违规收集用户信息
问题

应用在不同意隐私政策之前违规获取了收集设备信息,初步分析com.facebook.react.bridge有可能会引起这个获取ANDROID ID的问题
论证
由于com.facebook.react.bridge是react-native框架层面自带,为了排除其他因素的影响,我新建了一个React Native(版本0.64.3)的空工程,运行App发现还是会有获取ANDROID ID的问题:
结论
得到的结论是由React Native框架自带的库引起,改造框架层面的东西不现实,于是我考虑从原生方式实现启动页的加载逻辑
解决思路
原生端实现
在路径android/app/src/main/java/包名路径,目录下新建文件CommonDialog.java
package com.caih.gxsinglewindow;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.StyleRes;
/**
* 创建自定义的Dialog
*/
public class CommonDialog extends Dialog {
private Button yes;//确定按钮
private Button no;//取消按钮
private TextView titleTV;//消息标题文本
private TextView message;//消息提示文本
private String titleStr;//从外界设置的title文本
private CharSequence messageStr;//从外界设置的消息文本
//确定文本和取消文本的显示的内容
private String yesStr, noStr;
private noButtonOnclickListener noButtonOnclickListener;//取消按钮被点击了的监听器
private yesButtonOnclickListener yesButtonOnclickListener;//确定按钮被点击了的监听器
private messageOnclickListener messageOnclickListener;//确定按钮被点击了的监听器
public CommonDialog(@NonNull Context context, @StyleRes int themeResId) {
super(context, themeResId);
}
public CommonDialog(@NonNull Context context) {
super(context);
}
/**
* 设置取消按钮的显示内容和监听
*
* @param str
* @param noButtonOnclickListener
*/
public void setNoOnclickListener(String str, noButtonOnclickListener noButtonOnclickListener) {
if (str != null) {
noStr = str;
}
this.noButtonOnclickListener = noButtonOnclickListener;
}
/**
* 设置确定按钮的显示内容和监听
*
* @param str
* @param yesButtonOnclickListener
*/
public void setYesOnclickListener(String str, yesButtonOnclickListener yesButtonOnclickListener) {
if (str != null) {
yesStr = str;
}
this.yesButtonOnclickListener = yesButtonOnclickListener;
}
public void setMessageOnclickListener(messageOnclickListener messageOnclickListener) {
this.messageOnclickListener = messageOnclickListener;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.common_dialog);
//空白处不能取消动画
setCanceledOnTouchOutside(false);
//初始化界面控件
initView();
//初始化界面数据
initData();
//初始化界面控件的事件
initEvent();
}
/**
* 初始化界面控件
*/
private void initView() {
yes = findViewById(R.id.yes);
no = findViewById(R.id.no);
titleTV = (TextView) findViewById(R.id.title);
message = (TextView) findViewById(R.id.message);
}
/**
* 初始化界面控件的显示数据
*/
private void initData() {
//如果用户自定了title和message
if (titleStr != null) {
titleTV.setText(titleStr);
}
message.setMovementMethod(LinkMovementMethod.getInstance());
if (messageStr != null) {
message.setText(messageStr);
}
//如果设置按钮文字
if (yesStr != null) {
yes.setText(yesStr);
}
if (noStr != null) {
no.setText(noStr);
}
}
/**
* 初始化界面的确定和取消监听
*/
private void initEvent() {
//设置确定按钮被点击后,向外界提供监听
yes.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (yesButtonOnclickListener != null) {
yesButtonOnclickListener.onYesClick();
}
}
});
//设置取消按钮被点击后,向外界提供监听
no.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (noButtonOnclickListener != null) {
noButtonOnclickListener.onNoClick();
}
}
});
/*message.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(messageOnclickListener != null){
String url = "https://www.baidu.com/";
messageOnclickListener.messageClick(url);
}
}
});*/
}
/**
* 从外界Activity为Dialog设置标题
*
* @param title
*/
public void setTitle(String title) {
titleStr = title;
}
/**
* 从外界Activity为Dialog设置message
*
* @param message
*/
public void setMessage(CharSequence message) {
messageStr = message;
}
public interface noButtonOnclickListener {
public void onNoClick();
}
public interface yesButtonOnclickListener {
public void onYesClick();
}
public interface messageOnclickListener{
public void messageClick(String url);
}
}
同级目录下新建文件tempactivity.java,编写弹窗内容和二次弹窗
package com.caih.gxsinglewindow;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.style.CharacterStyle;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
public class TempActivity extends Activity {
//
private SharedPreferences.Editor editor;
// 隐私条款对话框
private CommonDialog privacyDialog;
// 隐私条款二次确认对话框
private CommonDialog secondDialog;
private String userRegisterPolicyUrl = "https://www.baidu.com/";
private String privacyPolicyUrl = "https://www.baidu.com/";
@Override
protected void onCreate(Bundle savedInstanceState) {
// Set the theme to AppTheme BEFORE onCreate to support
// coloring the background, status bar, and navigation bar.
// This is required for expo-splash-screen.
setTheme(R.style.AppTheme);
super.onCreate(null);
checkIfAgreePrivacy();
}
// 判断是否同意隐私条款
private void checkIfAgreePrivacy() {
SharedPreferences preferences = getPreferences(MODE_PRIVATE);
boolean ifAgree = preferences.getBoolean("ifAgreePrivacy", false);
// 如果没同意过隐私条款,初始化隐私条款对话框,弹出隐私条款
if (!ifAgree) {
initPrivacyDialog();
initSecondDialog();
privacyDialog.show();
} else {
// 已同意,跳转到主页面
// 传值
Intent intent = new Intent(TempActivity.this, MainActivity.class);
// 跳转页面
startActivity(intent);
finish();
}
}
/**
* 隐私协议
*/
private void initPrivacyDialog() {
privacyDialog = new CommonDialog(TempActivity.this);
privacyDialog.setContentView(R.layout.common_dialog);
// 隐私条款同意按钮事件
privacyDialog.setYesOnclickListener("同意", new CommonDialog.yesButtonOnclickListener() {
@Override
public void onYesClick() {
SharedPreferences preferences = getPreferences(MODE_PRIVATE);
editor = preferences.edit();
editor.putBoolean("ifAgreePrivacy", true);
editor.commit();
privacyDialog.dismiss();
// 跳转到真正首页
Intent intent = new Intent(TempActivity.this, MainActivity.class);
// 跳转页面
startActivity(intent);
finish();
}
});
// 隐私条款不同意按钮事件
privacyDialog.setNoOnclickListener("不同意", new CommonDialog.noButtonOnclickListener() {
@Override
public void onNoClick() {
privacyDialog.dismiss();
// 弹出二次确认框
secondDialog.show();
}
});
// 隐私条款协议按钮事件
privacyDialog.setMessageOnclickListener(new CommonDialog.messageOnclickListener() {
@Override
public void messageClick(String url) {
if (url == null || url.isEmpty()) {
return;
}
// 传值
Intent intent = new Intent(TempActivity.this, WebViewActivity.class);
intent.putExtra("url", url);
// 跳转页面
startActivity(intent);
}
});
privacyDialog.setTitle("温馨提示");
String messageStr = "亲爱的用户,感谢您使用app!\n" +
"为了更好地保护您的权益,同时遵守相关监管要求,在您使用服务前,请仔细阅读《用户注册协议》和《app平台隐私政策》,\n" +
"以便您能更好地行驶个人权利和保护个人信息,特向您说明如下:\n" +
"1、为向您提供基本服务,我们会遵循正当、合法、必要的原则收集和使用必要的信息;\n" +
"2、为实现消息推送,我们需要获取本机识别码权限;为xx协同功能,我们需要获取相机权限和录音权限;" +
"为办理xx业务,我们需要获取本地存储读写权限、地理位置和相册权限;" +
"所有获取权限描述和用途在隐私协议中有详细说明;\n" +
"3、未经您的授权同意,我们不会将您的信息提供给第三方;\n" +
"4、您可以查询、更正、删除您的个人信息,我们也提供账号注销的渠道。\n" +
"如您同意此协议,请点击“同意”并开始使用我们的服务,如您无法认同此协议,很遗憾,我们将无法为您提供服务。";
SpannableStringBuilder style = new SpannableStringBuilder();
style.append(messageStr);
// 用户注册协议点击区域
ClickableSpan span1 = new ClickableSpan() {
@Override
public void onClick(@NonNull View view) {
startWebView(userRegisterPolicyUrl);
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(Color.parseColor("#26B3A3"));
}
};
style.setSpan(span1, 53, 60, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
// 隐私政策点击区域
ClickableSpan span2 = new ClickableSpan() {
@Override
public void onClick(@NonNull View view) {
startWebView(privacyPolicyUrl);
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(Color.parseColor("#26B3A3"));
}
};
style.setSpan(span2, 61, 72, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
CharacterStyle span = new CharacterStyle() {
@Override
public void updateDrawState(TextPaint textPaint) {
}
};
// 第2点获取授权部分部分加粗
style.setSpan(new StyleSpan(Typeface.BOLD), 161, 172, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
style.setSpan(new StyleSpan(Typeface.BOLD), 185, 196, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
style.setSpan(new StyleSpan(Typeface.BOLD), 211, 224, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
style.setSpan(new StyleSpan(Typeface.BOLD), 239, 249, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
// 最后一段样式
style.setSpan(new ForegroundColorSpan(Color.parseColor("#999999")), 336, messageStr.length(),
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
privacyDialog.setMessage(style);
privacyDialog.getWindow().setBackgroundDrawableResource(R.drawable.dialog_shape);
}
/**
* 二次确认框
*/
private void initSecondDialog() {
secondDialog = new CommonDialog(TempActivity.this);
secondDialog.setContentView(R.layout.common_dialog);
// 查看协议按钮事件
secondDialog.setYesOnclickListener("查看协议", new CommonDialog.yesButtonOnclickListener() {
@Override
public void onYesClick() {
startWebView(privacyPolicyUrl);
secondDialog.dismiss();
privacyDialog.show();
}
});
// 退出应用按钮事件
secondDialog.setNoOnclickListener("退出应用", new CommonDialog.noButtonOnclickListener() {
@Override
public void onNoClick() {
secondDialog.dismiss();
finish();
}
});
secondDialog.setTitle("您需要同意本隐私政策才能继续使用APP");
SpannableStringBuilder style = new SpannableStringBuilder();
String messageStr = "如你不同意本隐私协议,很遗憾我们将无法为您提供服务。";
style.append(messageStr);
style.setSpan(new ForegroundColorSpan(Color.parseColor("#999999")), 0, messageStr.length(),
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
secondDialog.setMessage(style);
secondDialog.getWindow().setBackgroundDrawableResource(R.drawable.dialog_shape);
}
private void startWebView(String url) {
// 传值
Intent intent = new Intent(TempActivity.this, WebViewActivity.class);
intent.putExtra("url", url);
// 跳转页面
startActivity(intent);
}
}
同级目录下,新建webview承载网页WebViewActivity.java
package com.caih.gxsinglewindow;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.webkit.WebSettings;
import android.webkit.WebView;
import androidx.annotation.Nullable;
public class WebViewActivity extends Activity {
private WebView webView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//加载webView布局
setContentView(R.layout.web_view);
Intent intent = this.getIntent();
String url = intent.getStringExtra("url");
//获取webView对象
webView = findViewById(R.id.webView);
//webView初始化属性
webView.getSettings().setJavaScriptEnabled(true);//设置WebView属性,能够执行Javascript脚本
webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
webView.getSettings().setLayoutAlgorithm( WebSettings.LayoutAlgorithm.NORMAL);
webView.getSettings().setAllowFileAccess(true); //设置可以访问文件
webView.getSettings().setBuiltInZoomControls(false); //设置支持缩放
webView.getSettings().setSupportZoom(true);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setAppCacheEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setDatabaseEnabled(true);
//加载页面
webView.loadUrl(url);
}
}
在路径android/app/src/main/res/drawable-xxhdpi,目录下新建文件dialog_shape.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/white" />
<corners android:radius="20dp"/>
</shape>
在路径android/app/src/main/res/layout,目录下新建文件common_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/dialog_shape">
<LinearLayout
android:layout_width="280dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@color/white"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:textAlignment="center"
android:text="温馨提示"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="bold"/>
<TextView
android:id="@+id/message"
android:clickable="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
android:layout_gravity="center"
android:textColor="#111111"
android:text=""
android:layout_marginTop="3dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="bottom"
android:orientation="horizontal">
<Button
android:id="@+id/no"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="10dp"
android:background="@color/white"
android:gravity="center"
android:lines="1"
android:text="不同意"
android:textColor="#999999"
android:textSize="16sp"
style="@style/Widget.AppCompat.Button.Borderless"/>
<View
android:layout_width="1px"
android:layout_height="match_parent"
android:background="#E4E4E4"/>
<Button
android:id="@+id/yes"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginRight="10dp"
android:background="@color/white"
android:gravity="center"
android:lines="1"
android:text="同意"
android:textColor="#26B3A3"
android:textSize="16sp"
style="@style/Widget.AppCompat.Button.Borderless"/>
</LinearLayout>
</LinearLayout>
</ScrollView>
在路径android/app/src/main/res/layout,目录下新建文件web_view.xml
<?xml version="2.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"></WebView>
</LinearLayout>
在路径android/app/src/main/res/layout,目录下新建文件colors.xml
<resources>
<color name="splashscreen_background">#ffffff</color>
<color name="iconBackground">#ffffff</color>
<color name="colorPrimary">#023c69</color>
<color name="colorPrimaryDark">#ffffff</color>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>
最后修改AndroidManifest.xml配置文件
<activity android:name=".TempActivity" android:exported="true" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
</intent-filter>
</activity>
<activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:screenOrientation="portrait">
<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="myapp"/>
<data android:scheme="com.caih.gxsinglewindow"/>
</intent-filter>
</activity>
<!-- 增加隐私协议的activity -->
<activity android:name=".WebViewActivity"></activity>
未提供注销功能
问题
解决思路
在App我的tab页提供注销功能入口,此功能比较简单,按需求业务来定,此处代码省略
隐私政策网址内无开发者名称
问题
解决思路
修改隐私政策网页内容
如:xx公司(以下简称“我们”)作为本应用的运营者和开发者......
存在用户权限敏感信息行为,且未在隐私政策上说明
问题
解决思路
如:为了向您提供xx功能所需相关文件上传服务,经您同意开启相机/摄像头和设备图片/文件读取权限后,我们将通过您的设备相机/摄像头获取您的照片信息,或收集您相册(图片库/视频库)中上传的图片/视频信息。请您知晓,即使您已同意开启相机/摄像头和设备图片/文件读取权限,我们也仅会在您主动使用更换头像功能时才会获取您的照片信息,或收集您相册(图片库/视频库)中上传的图片/视频信息。
为了向您提供xx功能扫码查询服务,经您同意开启相机/摄像头权限后,我们将收集您的拍摄内容。请您知晓,即使您已同意开启相机/摄像头权限,我们也仅会在您主动开启客户端内相机或录制视频功能时,才会通过调取相机/摄像头权限获取照片信息。
未提供测试账号
问题
解决思路
app增加账号密码登录功能
集成xx等第三方SDK,且未在应用内的隐私政策说明
问题
解决思路
如:为向您提供良好的软件服务,我们集成了极光推送SDK、第三方厂商推送SDK(小米、华为、oppo、vivo)和第三方expo.modules、ReactNative modules SDK,相关信息具体如下:
| SDK名称 | 极光推送 SDK |
|---|---|
| 开发者名称 | xx公司 |
| 使用目的 | 为 APP 用户提供信息推送服务 |
| 收集个人信息类型 | 设备参数及系统信息(设备类型、设备型号、系统版本、及相关硬件信息):用于识别用户的设备类型、设备型号、系统版本等,确保消息准确下发; 设备标识符(IMEI、IDFA、Android ID、GID、 MAC地址、OAID、VAID、AAID、IMSI、MEID、UAID、SN、ICCID、SIM信息):用于识别唯一用户,保证推送的精准送达及推送信息的准确统计; 网络信息(IP 地址、WiFi 信息、基站信息、DNS地址、DHCP地址、SSID、BSSID)与位置信息(经纬度):用于优化SDK与极光服务器的网络连接请求,保证服务的稳定性和连续性,同时实现区域推送功能; 软件安装列表信息(应用崩溃信息、通知开关状态、APP 应用列表及活跃状态、APP 应用页面信息、APP 功能事件相关信息):当一个设备有多个 APP 的推送链路同时活跃时,我们采用合并链路技术,随机合并成一条链路,以达到为用户节省电省流量的目的。 |
| 可能调用的权限 | 访问网络状态、获取设备信息、写入设备存储、获取地理位置信息、读取软件安装列表 |
| 数据处理方式 | 通过去标识化、加密传输及其他安全方式 |
存在定向推送或广告精准营销功能
问题
解决
按修改建议解决
提交的隐私标签与实际情况不符
问题
解决
明确在隐私政策网页中说明每个权限和个人信息的使用目的
存在点击无响应问题
问题
解决
某些功能在有些机型可能会有bug,按修改建议解决
app存在频繁自启动和关联启动
问题
小米应用市场审核不通过:app存在频繁自启动和关联启动
论证
经日志分析,极光推送SDK引起
解决思路
隐私政策网页增加自启动和关联启动说明
如:
- 为确保本应用处于关闭退出或者后台运行状态下可以正常接收客户端推送的引航调度功能消息,本应用须使用(自启动)能力,将存在一定频率通过系统发送广播唤醒本应用自启动行为,是因实现引航调度功能及服务所必要的。
- 为了带给您更好的系统通道消息通知,应用引入了华为HMS SDK、小米推送SDK、OPPO推送SDK和vivo推送SDK,关联了自启动功能,目的是您退出APP后,也能正常接收到引航调度系统通知消息。
- 在您未同意用户协议和隐私政策前,我们不会自动启动应用及引航调度消息推送服务,在您同意用户协议和隐私政策后,才打开此服务,如您不想接收APP系统消息推送,可通过手机设置-通知管理进行关闭,我们非常重视用户在使用APP过程中的用户体验和服务。
修改AndroidManifest.xml配置文件
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="包名">
// 改为
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="包名">
<!-- 移除相应的组件,处理小米应用商店上架审核不通过问题:APP存在自启动和关联启动 start-->
<receiver android:name="cn.jpush.android.service.PushReceiver" android:enabled="true" android:exported="false" tools:node="replace">
<intent-filter android:priority="1000">
<action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" />
<category android:name="包名" />
</intent-filter>
</receiver>
<receiver android:name="cn.jpush.android.service.AlarmReceiver" tools:node="remove"/>
<receiver android:name="com.xiaomi.push.service.receivers.NetworkStatusReceiver" android:exported="true" tools:node="remove">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<!-- 处理小米应用商店上架审核不通过问题:APP存在自启动和关联启动 end-->
应用内未提供个性化推送开启和关闭功能(vivo应用市场)
问题
解决
按修改建议
隐私政策内容缺少开发者联系方式
解决
隐私政策网页增加内容:
如何联系我们
如您对本隐私政策或您个人信息的相关事宜有任何问题、意见或建议,您可邮箱联系我们:您的邮箱。