小米手机小游戏隐私问题解决方案

1.由于laya底层代码调用获取设备信息,导致原先启动laya引擎后才去弹出隐私政策条款的功能是过不了审核的,所以需要在android的设计一个隐私条款的弹窗,玩家同意条款后才启动laya引擎:

(1)定义隐私条款弹窗的xml文件:在layout文件夹下创建 activity_privacy_policy.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginLeft="50dp"android:layout_marginTop="100dp"android:layout_marginRight="50dp"android:layout_marginBottom="100dp"android:background="@drawable/dialog_privacy_bg"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_above="@+id/ll_btn_bottom"android:layout_marginBottom="35dp"android:gravity="center"android:orientation="vertical"tools:ignore="UnknownId"><TextViewandroid:id="@+id/tv_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:layout_marginBottom="10dp"android:text="用户使用协议"android:autoLink="all"android:textColor="@color/colorBlack"android:textSize="18sp" /><ScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginLeft="5dp"android:layout_marginRight="5dp"android:layout_marginBottom="15dp"android:fadingEdgeLength="60dp"android:requiresFadingEdge="horizontal"><TextViewandroid:id="@+id/tv_content"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginTop="10dp"android:singleLine="false"android:text=""android:textColor="@color/colorBlack"/></ScrollView><TextViewandroid:id="@+id/url_href"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="20dp"android:layout_marginTop="-238dp"android:singleLine="false"android:autoLink="all" //添加下划线android:text="《产品隐私说明》"android:textColor="@color/color_accent" /></LinearLayout><LinearLayoutandroid:id="@+id/BtnView"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentStart="true"android:layout_alignParentBottom="true"android:gravity="bottom"><Buttonandroid:id="@+id/btn_exit"android:layout_width="0dp"android:layout_height="32dp"android:layout_weight="1"android:background="@color/colorWhite"android:text="@string/privacy_exit"android:textColor="@color/colorGray"android:textSize="16sp"android:textStyle="bold" /><Viewandroid:layout_width="0.25dp"android:layout_height="40dp"android:background="@color/colorGray" /><Buttonandroid:id="@+id/btn_enter"android:layout_width="0dp"android:layout_height="32dp"android:layout_weight="1"android:background="@color/colorWhite"android:text="@string/privacy_agree"android:textColor="@color/colorOrange"android:textSize="16sp"android:textStyle="bold" /></LinearLayout></RelativeLayout>

(2)既然有弹出界面,那就有弹出界面的bg代码,所以在drawable目录下创建一个  dialog_privacy_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><!--填充设置--><solid android:color="@android:color/white" /><!--圆角设置--><corners android:radius="6dp" /></shape>

(3)然后少不了颜色设置啦,直接在values目录下的 colors.xml里面补上填充颜色:

<?xml version="1.0" encoding="utf-8"?>
<resources><color name="colorPrimary">#008577</color><color name="colorPrimaryDark">#00574B</color><color name="colorAccent">#D81B60</color><color name="colorWhite">#FFFFFFFF</color><color name="colorBlack">#FF000000</color><color name="colorGray">#878787</color><color name="colorOrange">#FFE26C25</color><color name="colorBlue">#FF036EB8</color>
</resources>

(4)颜色有了,少不了文字,所以在 values目录下的 strings.xml 里面按钮文字之类的 :

<string name="privacy_exit">退出</string>
<string name="privacy_agree">同意</string>

2.实现隐私弹窗的前提内容已经准备好了,那就少不了开始调用隐私弹窗了,在代码层面:

(1)既然只需要显示一次,那就需要保持数据,直接上保存数据的工具类:

package demo;//包名我就隐藏了
import android.content.Context;
import android.content.SharedPreferences;import java.util.Map;
/**
* 数据缓存到本地
* **/
public class DataUtils {/*** 保存在手机里的SP文件名*/public static final String FILE_NAME = "privacy_sp";/*** 保存数据*/public static void put(Context context, String key, Object obj) {SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);SharedPreferences.Editor editor = sp.edit();if (obj instanceof Boolean) {editor.putBoolean(key, (Boolean) obj);} else if (obj instanceof Float) {editor.putFloat(key, (Float) obj);} else if (obj instanceof Integer) {editor.putInt(key, (Integer) obj);} else if (obj instanceof Long) {editor.putLong(key, (Long) obj);} else {editor.putString(key, (String) obj);}editor.commit();}public static  boolean isKeep(Context context, String key, Object defaultObj){SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);if(sp.contains(key)){}return false;}/*** 获取指定数据*/@org.jetbrains.annotations.Nullablepublic static Object get(Context context, String key, Object defaultObj) {SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);if (defaultObj instanceof Boolean) {return sp.getBoolean(key, (Boolean) defaultObj);} else if (defaultObj instanceof Float) {return sp.getFloat(key, (Float) defaultObj);} else if (defaultObj instanceof Integer) {return sp.getInt(key, (Integer) defaultObj);} else if (defaultObj instanceof Long) {return sp.getLong(key, (Long) defaultObj);} else if (defaultObj instanceof String) {return sp.getString(key, (String) defaultObj);}return null;}/*** 删除指定数据*/public static void remove(Context context, String key) {SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);SharedPreferences.Editor editor = sp.edit();editor.remove(key);editor.commit();}/*** 返回所有键值对*/public static Map<String, ?> getAll(Context context) {SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);Map<String, ?> map = sp.getAll();return map;}/*** 删除所有数据*/public static void clear(Context context) {SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);SharedPreferences.Editor editor = sp.edit();editor.clear();editor.commit();}/*** 检查key对应的数据是否存在*/public static boolean contains(Context context, String key) {SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);return sp.contains(key);}
}

(2)接下来在 MainActivity.java中,onCreate方法中,判断 是否 需要拉起隐私弹窗:

/**当前表现的隐私类型:
* 1:个人信息隐私
* 2:使用条款
* 注意:一个是用户协议记录状态,一个是隐私协议记录状态。至于那个,你们自己定也可以看我的。
* **/
private int prviacyType = 1;  //在onCreate之前声明变量
/**
* 既然是保存第一次数据的。所以,执行调用隐私前,必须拿到是否同意哪个隐私内容了
* */
String isPrivacy = DataUtils.get(MainActivity.this,"privacy","0").toString();if(isPrivacy.equals("1") )
{//同意过隐私政策了,直接跳过隐私弹窗处理Log.e("showPrivacy", "同意了,直接跳过隐私弹窗处理");onAgreed();  //下次进游戏同意过隐私政策的用户直接启动laya引擎
}else if(isPrivacy.equals("0"))
{Log.e("showPrivacy", "显示用户个人信息隐私");prviacyType = 1;//这里需要在assets文件夹下,创建一个隐私政策的文本,代码通过读取这个文件,显示隐私政策的内容在界面showPrivacy("privacy.txt","隐私协议");
}

(3)当同意隐私政策后,拉取权限申请代码,和启动laya引擎的代码:

public void onAgreed(){checkAndRequestPermissions();  //申请权限MiCommplatform.getInstance().onUserAgreed(this); //小米接口同意隐私政策  告知SDK⽤⼾是否同意隐私协议MMApplication mApplication = (MMApplication) getApplication();mApplication.initSDK(this);   //调用小米登录以及初始化广告sdkcheckApkUpdate(this);      //启动laya引擎
}
/**声明权限申请相关的变量**/
private List<String> mNeedRequestPMSList = new ArrayList<>();
private static final int REQUEST_PERMISSIONS_CODE = 100;/**
* 申请 SDK 运行需要的权限
* 注意:READ_PHONE_STATE 权限是必须权限,没有这个权限 SDK 无法正常获得广告。
* WRITE_EXTERNAL_STORAGE 、ACCESS_FINE_LOCATION 是可选权限;没有不影响 SDK 获取
广告;但是如果应用申请到该权限,会显著提升应用的广告收益。
*/
private void checkAndRequestPermissions() {/*** Android Q 以下 READ_PHONE_STATE 权限是必须权限,没有这个权限 SDK 无法正常获得广告。*/mNeedRequestPMSList.add(Manifest.permission.READ_PHONE_STATE);mNeedRequestPMSList.add(Manifest.permission.READ_EXTERNAL_STORAGE);mNeedRequestPMSList.add(Manifest.permission.READ_PHONE_STATE);mNeedRequestPMSList.add(Manifest.permission.GET_ACCOUNTS);mNeedRequestPMSList.add(Manifest.permission.INTERNET);mNeedRequestPMSList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);mNeedRequestPMSList.add(Manifest.permission.INTERNET);mNeedRequestPMSList.add(Manifest.permission.ACCESS_NETWORK_STATE);mNeedRequestPMSList.add(Manifest.permission.ACCESS_WIFI_STATE);mNeedRequestPMSList.add(Manifest.permission.ACCESS_FINE_LOCATION);mNeedRequestPMSList.add(Manifest.permission.REQUEST_INSTALL_PACKAGES);//if (0 == mNeedRequestPMSList.size()) {/*** 权限都已经有了,那么直接调用 SDK 请求广告。*/} else {/*** 有权限需要申请,主动申请。*/String[] temp = new String[mNeedRequestPMSList.size()];mNeedRequestPMSList.toArray(temp);ActivityCompat.requestPermissions(this, temp,REQUEST_PERMISSIONS_CODE);}
}

(4)显示 隐私弹窗:

 /*** 前置内容都设定了,那就开始调用弹出隐私,并且根据调用的隐私内容去加载隐私内容回来并且展示出来。* */public void showPrivacy(String privacyFileName,String title)    {//加载当前要显示的隐私内容文本String str = initAssets(privacyFileName);//布局ui界面信息final View inflate = LayoutInflater.from(this).inflate(R.layout.activity_privacy_policy, null);TextView tv_title = (TextView) inflate.findViewById(R.id.tv_title);//设置隐私内容抬头tv_title.setText(title);//显示隐私内容,因为文本布局,需要美观,所以内容用需要使用换行符,但加载回来的内容用\n的话无法真正做到换行,只能在文本中用<br/>作为换行符,然后进行替换成\nTextView tv_content = (TextView) inflate.findViewById(R.id.tv_content);tv_content.setText(str.replace("<br/>", "\n"));tv_content.setText(Html.fromHtml(str));   //这里把读取的str按照html格式显示出来//获取同意和退出两个按钮并且添加事件TextView url_href = (TextView) inflate.findViewById(R.id.url_href);TextView btn_exit = (TextView) inflate.findViewById(R.id.btn_exit);TextView btn_enter = (TextView) inflate.findViewById(R.id.btn_enter);Log.e("showPrivacy", "开始弹出隐私界面111");//开始弹出隐私界面final Dialog dialog = new AlertDialog.Builder(this).setView(inflate).show();//对话框弹出后点击或按返回键不消失dialog.setCancelable(false);Log.e("showPrivacy", "开始弹出隐私界面2222");WindowManager m = getWindowManager();Display defaultDisplay = m.getDefaultDisplay();final WindowManager.LayoutParams params = dialog.getWindow().getAttributes();params.width = (int) (defaultDisplay.getWidth() * 0.90);dialog.getWindow().setAttributes(params);dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);url_href.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Log.e("showPrivacy", "点击跳转url界面");//打开一下新的ActivityIntent intent = new Intent(MainActivity.this,SecretUrlActivity.class) ;startActivity(intent);}});//退出按钮事件btn_exit.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {dialog.dismiss();exitGame();finish();}});//同意按钮事件btn_enter.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {dialog.dismiss();
//                if(prviacyType == 1)
//                {
//                    prviacyType = 2;
//                    //保存隐私同意状态
//                    DataUtils.put(MainActivity.this,"privacy","1");
//                    //显示下一个隐私内容
//                    showPrivacy("policy.txt","使用条款");
//                }else if(prviacyType == 2)
//                {
//                    DataUtils.put(MainActivity.this,"policy","1");
//                    //两个隐私内容都确定后,开始执行下一步
//                    onAgreed();
//                }DataUtils.put(MainActivity.this,"privacy","1");//两个隐私内容都确定后,开始执行下一步onAgreed();}});}

这里需要在assets文件夹下,创建一个隐私政策的文本,代码通过读取这个文件,显示隐私政策的内容在界面中:

(5)读取txt文件的代码如下:

/**
* 从assets下的txt文件中读取数据
*/
public String initAssets(String fileName) {Log.e("initAssets", "从assets下的txt文件中读取数据");String str = null;try {InputStream inputStream = getAssets().open(fileName);str = getString(inputStream);} catch (IOException e1) {e1.printStackTrace();}return str;
}public static String getString(InputStream inputStream) {InputStreamReader inputStreamReader = null;try {inputStreamReader = new InputStreamReader(inputStream, "UTF-8");} catch (UnsupportedEncodingException e1) {e1.printStackTrace();}BufferedReader reader = new BufferedReader(inputStreamReader);StringBuffer sb = new StringBuffer("");String line;try {while ((line = reader.readLine()) != null) {sb.append(line);sb.append("");}} catch (IOException e) {e.printStackTrace();}return sb.toString();
}

(6)另外在点击 xml中的一个 TextView元素的时候,这里注册了一个点击事件,会打开新的Activity,这个新的Activity是一个用于显示隐私条款详情的 网页:

TextView url_href = (TextView) inflate.findViewById(R.id.url_href);url_href.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Log.e("showPrivacy", "点击跳转url界面");Intent intent = new Intent(MainActivity.this,SecretUrlActivity.class) ;startActivity(intent);}
});

(7)这个新的Activity,SecretUrlActivity.java 代码如下:

package demo;import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.ViewGroup;import com.cszs.jgdnc.mi.R;import demo.SecretUrlView;public class SecretUrlActivity  extends Activity {public ViewGroup urlView_container;private SecretUrlView urlView = null;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.url_layout) ;InitUrlSecretView();}public void InitUrlSecretView(){if(urlView!=null){urlView.showUrlView();return;}//      final View inflate2 = LayoutInflater.from(this).inflate(R.layout.url_layout,null);
//      this.urlView_container =  (ViewGroup)inflate2.findViewById(R.id.view_url_container);this.urlView_container =  findViewById(R.id.view_url_container);urlView = new SecretUrlView(this);}public  void toMainActivity(){Intent intent = new Intent(SecretUrlActivity.this,MainActivity.class) ;startActivity(intent) ;}
}

(8)这个SecretUrlActivity对应的布局文件,在layout文件夹中创建url_layout.xml,如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"xmlns:app="http://schemas.android.com/apk/res-auto"><FrameLayoutandroid:id="@+id/view_url_container"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginLeft="0dp"android:layout_marginTop="0dp"android:layout_marginRight="0dp"android:layout_marginBottom="0dp"android:background="#FFFFFF"><WebViewandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:id="@+id/wv"android:layout_alignParentLeft="true"android:layout_alignParentStart="true"android:layout_alignParentTop="true" /><ImageViewandroid:id="@+id/view_url_close"android:layout_width="32dp"android:layout_height="32dp"android:layout_marginStart="9dp"android:layout_marginTop="20dp"android:layout_marginEnd="400dp"android:contentDescription="关闭按钮"android:src="@drawable/float_hide_tip_sel"app:layout_constraintBottom_toTopOf="@+id/view_feedBox_image"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.78"app:layout_constraintStart_toEndOf="@+id/view_feedBox_image"app:layout_constraintTop_toTopOf="parent"app:layout_constraintVertical_bias="0.0" /></FrameLayout></RelativeLayout>

(9)这个新的Activity,也就是 SecretUrlActivity,创建一个View类 SecretUrlView.java:用于显示网页

package demo;import android.content.Intent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;import com.cszs.jgdnc.mi.R;import demo.Constants;
import demo.MainActivity;
import demo.SecretUrlActivity;public class SecretUrlView {private SecretUrlActivity sActivity;private static String TAG = "SecretUrlView";private View mView;private WebView wv;public SecretUrlView(SecretUrlActivity sActivity) {this.sActivity = sActivity;this.init();}public void init(){mView = (ViewGroup) sActivity.urlView_container;wv=(WebView)mView.findViewById(R.id.wv);WebSettings ws=wv.getSettings();ws.setJavaScriptEnabled(true);wv.loadUrl("https://res.wqop2018.com/app/web/privacy/v3/privacy.html?app_name=" + Constants.APP_NAME + "&company="+Constants.COMPANY+"&package_name="+Constants.PACKAGE_NAME);wv.setWebViewClient(new WebViewClient());mView.findViewById(R.id.view_url_close).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//点击关闭后隐藏该界面mView.setVisibility(View.GONE);sActivity.toMainActivity();}});}public void showUrlView(){mView.setVisibility(View.VISIBLE);}public  void  hideUrlView(){mView.setVisibility(View.GONE);}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/307745.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WEB 3D技术 three.js 色彩空间讲解

上文 WEB 3D技术 three.js 设置环境贴图 高光贴图 场景设置 光照贴图 我们讲了基础材质的各种纹理 但是 我们的图片 到了界面场景中 好像绿的程度有点不太一样了 这里的话 涉及到我们的色彩空间 他有两种 一种是线性的 一种是 sRGB类型的 线性呢 就是根据光照强度 去均匀分…

6130 树的最长路

思路&#xff1a;树的最长路问题可以通过两次 DFS 求解&#xff0c;具体思路如下&#xff1a; 1.第一次 DFS 求树的直径 以任意一个点为起点进行深度优先遍历&#xff08;DFS&#xff09;&#xff0c;找到与该点距离最远的点 u 。 以 u 为起点进行 DFS &#xff0c;找到与 u 距…

【开源项目】智慧交通~超经典开源项目实景三维数字孪生高速

数字孪生高速运营管理平台&#xff0c;以提升高速公路管理水平和方便出行为主要目标&#xff0c;充分利用云计算、AI、大数据等&#xff0c;实现对高速公路控制、指挥、运营的智能化。飞渡科技以实景三维数据为基础&#xff0c;基于大数据、高分遥感、数据分析以及数据融合等前…

智慧启航:机场管理系统的革新与飞机航天展馆的视觉盛宴

随着科技的飞速发展&#xff0c;我们的生活方式正在不断地被改变和提升。而在航空领域&#xff0c;这种变化则更加明显。从机场的智慧管理系统大屏&#xff0c;到飞机航天展馆的三维可视化&#xff0c;再到飞机涡轮发动机的3D模型&#xff0c;科技的力量正在带我们进入一个前所…

如何确保云中高可用?聊聊F5分布式云DNS负载均衡

在当今以应用为中心的动态化市场中&#xff0c;企业面临着越来越大的压力&#xff0c;不仅需要提供客户所期望的信息、服务和体验&#xff0c;而且要做到快速、可靠和安全。DNS是网络基础设施的重要组成部分&#xff0c;拥有一个可用的、智能的、安全和可扩展的DNS基础设施是至…

121. 买卖股票的最佳时机(Java)

给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔交易中获取的最大利润。…

【办公软件】Excel双坐标轴图表

在工作中整理测试数据&#xff0c;往往需要一个图表展示两个差异较大的指标。比如共有三个数据&#xff0c;其中两个是要进行对比的温度值&#xff0c;另一个指标是两个温度的差值&#xff0c;这个差值可能很小。 举个实际的例子&#xff1a;数据如下所示&#xff0c;NTC检测温…

C++的多继承和虚继承

目录 多继承的定义和用法定义多继承多继承中派生类对象的内存布局访问基类成员多继承带来的问题 虚继承虚继承的语法虚继承对象的内存布局虚继承中的构造虚继承的缺点 多继承的定义和用法 C支持多继承&#xff0c;即一个派生类可以有多个基类。 很多时候&#xff0c;单继承就…

MySQL日期查询 今天、明天、本月、下月、星期、本周第一天、本周最后一天、本周七天日期

文章目录 今天日期明天日期本月第一天本月最后一天下个月第一天当前月已过几天当前月天数当前月所有日期获取星期本周第一天本周最后一天获取本周的七天日期 今天日期 select curdate()明天日期 select DATE_SUB(curdate(),INTERVAL -1 DAY) AS tomorrow本月第一天 select d…

2023年度总结(找到工作)

转眼2023年结束了&#xff0c;今天已经12月29日了。从2022年12月25日考研失败后&#xff0c;2023年就变成了找工作以及上班度日的时光了。针对2023年&#xff0c;我想对自己所说的是&#xff1a;终于找到工作了。作为一个普通的专升本&#xff0c;考研落榜生来说&#xff0c;能…

JavaScript(简写js)常用事件举例演示

目录 1.窗口事件onblur :失去焦点onfocus:获得焦点onload:窗口加载事件onresize:窗口大小缩放事件 二、表单事件oninput &#xff1a;当文本框内容改变时 &#xff0c;立即将改变内容 输出在控制台onchange&#xff1a; 内容改变事件onclick&#xff1a;鼠标单击时触发此事件 三…

模版匹配历劫之路2-探究空间金字塔对于匹配速度的影响

1 方法一 在合适的金字塔层数上&#xff0c;低步长旋转角度&#xff0c;逐层缩小旋转范围&#xff0c;达到提高匹配速度的效果 金字塔越高&#xff0c;模版越模糊&#xff0c;但是只要模版不会被降级很严重&#xff0c;那么模版的边缘方向不会受到太大的影响。高层级别的金字塔…