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

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

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

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">




    <LinearLayout
        android: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">


        <TextView
            android: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" />


        <ScrollView
            android: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">


            <TextView
                android: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>


        <TextView
            android: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>


    <LinearLayout
        android:id="@+id/BtnView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentBottom="true"
        android:gravity="bottom">


        <Button
            android: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" />


        <View
            android:layout_width="0.25dp"
            android:layout_height="40dp"
            android:background="@color/colorGray" />


        <Button
            android: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 复制代码
<?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 复制代码
<?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 里面按钮文字之类的 :

XML 复制代码
<string name="privacy_exit">退出</string>
<string name="privacy_agree">同意</string>

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

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

java 复制代码
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.Nullable
    public 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方法中,判断 是否 需要拉起隐私弹窗:

java 复制代码
/**当前表现的隐私类型:
* 1:个人信息隐私
* 2:使用条款
* 注意:一个是用户协议记录状态,一个是隐私协议记录状态。至于那个,你们自己定也可以看我的。
* **/
private int prviacyType = 1;  //在onCreate之前声明变量
java 复制代码
/**
* 既然是保存第一次数据的。所以,执行调用隐私前,必须拿到是否同意哪个隐私内容了
* */
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引擎的代码:

java 复制代码
public void onAgreed(){
    checkAndRequestPermissions();  //申请权限
    MiCommplatform.getInstance().onUserAgreed(this); //小米接口同意隐私政策  告知SDK⽤⼾是否同意隐私协议

    MMApplication mApplication = (MMApplication) getApplication();
    mApplication.initSDK(this);   //调用小米登录以及初始化广告sdk
    checkApkUpdate(this);      //启动laya引擎
}
java 复制代码
/**声明权限申请相关的变量**/
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)显示 隐私弹窗:

java 复制代码
 /**
     * 前置内容都设定了,那就开始调用弹出隐私,并且根据调用的隐私内容去加载隐私内容回来并且展示出来。
     * */
    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/>作为换行符,然后进行替换成\n
        TextView 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() {
            @Override
            public void onClick(View v) {
                Log.e("showPrivacy", "点击跳转url界面");
                //打开一下新的Activity
                Intent intent = new Intent(MainActivity.this,SecretUrlActivity.class) ;
                startActivity(intent);
            }
        });


        //退出按钮事件
        btn_exit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog.dismiss();
                exitGame();
                finish();
            }
        });
        //同意按钮事件
        btn_enter.setOnClickListener(new View.OnClickListener() {
            @Override
            public 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文件的代码如下:

java 复制代码
/**
* 从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是一个用于显示隐私条款详情的 网页:

java 复制代码
TextView url_href = (TextView) inflate.findViewById(R.id.url_href);

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

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

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;


    @Override
    protected 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 复制代码
<?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">




    <FrameLayout
        android: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">




        <WebView
            android: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" />




        <ImageView
            android: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:用于显示网页

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() {

            @Override
            public void onClick(View v) {
                //点击关闭后隐藏该界面
                mView.setVisibility(View.GONE);
                sActivity.toMainActivity();
            }
        });
    }

    public void showUrlView(){
        mView.setVisibility(View.VISIBLE);
    }

    public  void  hideUrlView(){
        mView.setVisibility(View.GONE);
    }

}
相关推荐
事后不诸葛4 小时前
安卓音频之dumpsys audio
framework·安卓·audio
神洛华9 小时前
Y3地图制作1:水果缤纷乐、密室逃脱
编辑器·游戏引擎·游戏程序
真鬼1232 天前
植物大战僵尸杂交版v3.0.2最新版本(附下载链接)
游戏程序
赵大仁6 天前
在M系列芯片的Mac上使用Uniapp开发的依赖安装指南
前端·windows·macos·ios·小程序·uni-app·安卓
7yewh6 天前
LeetCode 力扣 热题 100道(二十一)接雨水(C++)
开发语言·数据结构·c++·算法·leetcode·安卓
西农小陈6 天前
Python-基于Pygame的小游戏(滑雪大冒险)(一)
python·游戏·pycharm·游戏程序·pygame
我想睡到自然醒₍˄·͈༝·͈˄*₎◞ ̑9 天前
【Android】EventBus——进行良好的组件通信
android·java·microsoft·android-studio
RogerLHJ13 天前
cocos creator 的 widget组件的使用及踩坑
typescript·游戏引擎·游戏程序·cocos2d
画个太阳作晴天14 天前
Android13应用在后台录音无声音
android·framework·android-studio·录音
码码哈哈0.014 天前
一个直接看央视频道的软件,可直接安装到TV
安卓