【1——Android端添加隐私协议(unity)1/3】

news2025/6/9 12:43:48

前言:这篇仅对于unity 发布Android端上架国内应用商店添加隐私协议,隐私协议是很重要的东西,没有这个东西,是不上了应用商店的。

对于仅仅添加隐私协议,我知道有三种方式,第一种和第二种基本一样
1.直接在unity里面新建PrivacyActivity.java,然后自定义一下AndroidManifest,就可以(就是直接在unity里面建java类了)(复杂度 低)
2.从Android studio 里面打出arr包,导入unity 里面使用 (复杂度 高)
3.从unity里面导出android studio 工程,在Android studio里面添加 (复杂度 高)

如何选择,这三种方法,我个人建议,如果只是添加隐私协议这种简单的需求,第一种就可以。我会实际演示这三种方式
以下是第二和第三方法的优缺点对比:

方法优点缺点
从 Android Studio 导出 AAR 包到 Unity1. 灵活性高,可以专注于 Android 原生代码的开发,而 Unity 负责游戏逻辑和渲染。 2. 适合需要在 Unity 中调用 Android 原生功能的场景,比如调用 Android 的 API 或第三方 SDK。 3. AAR 包可以独立于 Unity 项目开发和维护,便于模块化管理。1. 需要额外的步骤来确保 AAR 包与 Unity 的兼容性,比如导入 classes.jar 和处理资源文件冲突。 2. 如果需要频繁修改 Android 代码,每次都需要重新导出 AAR 包并更新 Unity 项目,流程相对繁琐。
从 Unity 导出 Android Studio 工程,在 Android Studio 里面添加1. 适合需要对 Unity 生成的 Android 项目进行深度定制的场景,比如修改 Gradle 配置、添加原生代码或第三方库。 2. 可以直接在 Android Studio 中调试和优化 Unity 生成的代码,便于解决复杂的构建问题。1. Unity 导出的 Android 工程结构复杂,包含大量自动生成的代码,可能增加开发和维护的难度。 2. 如果需要频繁在 Unity 和 Android Studio 之间切换开发,可能会导致项目文件的不一致。

因为这个字数比较多,我先介绍一下第三中,第一二种,后续会更新

三.第三种方法

从unity里面导出android studio 工程,在Android studio里面添加

步骤介绍,四步走

  • 第一步从unity打包出Android studuio 工程文件
    -在这里插入图片描述
  • 第二步 使用Android studio 打开项目
    -在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
我这里选的是Use Android Studio SDK,点击完成后,就打开了

  • 第三步,新建一个软件包,(我们把自己写逻辑代码都放在里面,比如隐私协议啊,或者微信登录支付什么的都可以放在这里,软件包的本质就是一个文件夹),具体步骤如下图
    右上角,视图选择为项目,Android studio 好几种视图模式,我们这里选择项目
    在这里插入图片描述
  • 在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 第四步,在com.companyName.projcetName,文件夹下新建一个PrivacyActvity活动,(实现我们隐私协议部分),并替换代码,具体如下图
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

package com.companyName.projectName; //这里修改为你的包名

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.TypedValue;
import android.webkit.WebView;


public class PrivacyActivity extends Activity implements DialogInterface.OnClickListener {
    private static final String PREFS_NAME = "PlayerPrefs"; // SharedPreferences的文件名
    private static final String PRIVACY_ACCEPTED_KEY = "PrivacyAcceptedKey"; // 用于存储用户是否同意隐私政策的键

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 检查用户是否已经同意隐私政策
        if (getPrivacyAccept()) {
            // 如果已经同意,直接进入Unity主Activity
            enterUnityActivity();
            return;
        }
        // 如果未同意,显示隐私政策对话框
        showPrivacyDialog();
    }

    private String buildPrivacyHtml() {
        // 在这里设置隐私政策和用户协议的链接,修改为你的
        String userAgreementUrl = "https://blog.csdn.net/weixin_45478456?type=blog";
        String privacyPolicyUrl = "https://blog.csdn.net/weixin_45478456?type=blog";

        // 动态生成隐私政策的HTML内容
        return "欢迎使用本应用,在使用本应用前,请您充分阅读并理解 " +
                "<a href=\"" + userAgreementUrl + "\">《用户协议》</a>和" +
                "<a href=\"" + privacyPolicyUrl + "\">《隐私政策》</a>各条;" +
                "<br/>" +
                "1.保护用户隐私是本应用的一项基本政策,本应用不会泄露您的个人信息;" +
                "<br/>" +
                "2.我们会根据您使用的具体功能需要,收集必要的用户信息(如申请设备信息,存储等相关权限);" +
                "<br/>" +
                "3.在您同意App隐私政策后,我们将进行集成SDK的初始化工作,会收集您的android_id、Mac地址、IMEI和应用安装列表,以保障App正常数据统计和安全风控;" +
                "<br/>" +
                "4.为了方便您的查阅,您可以通过“设置-关于我们”重新查看该协议;" +
                "<br/>" +
                "5.您可以阅读完整版的隐私保护政策了解我们申请使用相关权限的情况,以及对您个人隐私的保护措施。";
    }

    private void showPrivacyDialog() {
        // 创建一个WebView用于显示隐私政策的HTML内容
        WebView webView = new WebView(this);
        webView.loadData(buildPrivacyHtml(), "text/html", "utf-8");

        // 创建一个不可取消的对话框
        AlertDialog.Builder privacyDialog = new AlertDialog.Builder(this);
        privacyDialog.setCancelable(false);
        privacyDialog.setView(webView); // 设置WebView为对话框的内容视图
        privacyDialog.setTitle("提示"); // 设置对话框标题
        // 设置“拒绝”按钮,并指定点击事件监听器
        privacyDialog.setNegativeButton("拒绝", this);
        // 设置“同意”按钮,并指定点击事件监听器
        privacyDialog.setPositiveButton("同意", this);
        // 创建并显示对话框
        privacyDialog.create().show();
    }

    @Override
    public void onClick(DialogInterface dialogInterface, int i) {
        // 处理对话框按钮点击事件
        switch (i) {
            case AlertDialog.BUTTON_POSITIVE:
                // 如果点击了“同意”按钮
                setPrivacyAccept(true); // 保存用户同意隐私政策的状态
                enterUnityActivity(); // 进入Unity主Activity
                break;
            case AlertDialog.BUTTON_NEGATIVE:
                // 如果点击了“拒绝”按钮
                finish(); // 结束当前Activity,退出应用
                break;
        }
    }

    private void enterUnityActivity() {
        // 创建一个Intent,用于启动Unity主Activity
        Intent unityAct = new Intent();
        unityAct.setClassName(this, "com.unity3d.player.UnityPlayerActivity");
        startActivity(unityAct);
    }

    private void setPrivacyAccept(boolean accepted) {
        // 使用SharedPreferences保存用户是否同意隐私政策的状态
        SharedPreferences.Editor prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE).edit();
        prefs.putBoolean(PRIVACY_ACCEPTED_KEY, accepted);
        prefs.apply(); // 提交更改
    }

    private boolean getPrivacyAccept() {
        // 从SharedPreferences中获取用户是否同意隐私政策的状态,默认为false
        SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
        return prefs.getBoolean(PRIVACY_ACCEPTED_KEY, false);
    }

}

代码关键处都注释了,不懂,拿代码直接问AI就好

  • 第五步,替换AndroidManifest.xml里的内容,具体如图,代码在图下面(!注意,这里的内容和第一个,第二个方法里的不同)
    在这里插入图片描述
    在这里插入图片描述
    AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.INTERNET" />

    <uses-feature android:glEsVersion="0x00030000" />
    <uses-feature
        android:name="android.hardware.vulkan.version"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.touchscreen"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.touchscreen.multitouch"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.touchscreen.multitouch.distinct"
        android:required="false" />

    <application android:extractNativeLibs="true">
        <activity
            android:name="com.companyName.projectName.PrivacyActivity"
            android:exported="true">
            <!-- 添加以下 intent-filter -->
            <intent-filter>
                <category android:name="android.intent.category.LAUNCHER" />
                <action android:name="android.intent.action.MAIN" />
            </intent-filter>
        </activity>

        <meta-data
            android:name="unity.splash-mode"
            android:value="0" />
        <meta-data
            android:name="unity.splash-enable"
            android:value="True" />
        <meta-data
            android:name="unity.launch-fullscreen"
            android:value="True" />
        <meta-data
            android:name="unity.render-outside-safearea"
            android:value="True" />
        <meta-data
            android:name="notch.config"
            android:value="portrait|landscape" />
        <meta-data
            android:name="unity.auto-report-fully-drawn"
            android:value="true" />

        <activity
            android:name="com.unity3d.player.UnityPlayerActivity"
            android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density"
            android:exported="true"
            android:hardwareAccelerated="false"
            android:launchMode="singleTask"
            android:resizeableActivity="false"
            android:screenOrientation="fullUser"
            android:theme="@style/UnityThemeSelector">
            <meta-data
                android:name="unityplayer.UnityActivity"
                android:value="true" />
            <meta-data
                android:name="notch_support"
                android:value="true" />
        </activity>
    </application>

</manifest>
  • 第六步,打包测试,我这里用的是雷电模拟器测试,步骤如下
    先打开雷电模拟器
    在这里插入图片描述

在这里插入图片描述
等待一会,就可以在模拟器里看到了
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
这样子就OK啦

如果想打包出正式版本,打包出apk的话,大致步骤如下图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
填写好之后,无脑下一步
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
成功后,去下图项目这个文件夹就可以找到apk
在这里插入图片描述

至此,结束,如果简单添加隐私协议个人推荐第一种或者直接使用我打包好的第二种方法的arr包。我使用第三种只是因为公司电脑环境复杂,无法打包出来,修了一天,试了N多种方法没解决,又不能重装,所以才使用第三种。 如果有任何疑问,可以私信联系我,尽量回复。个人拙作,欢迎斧正、转载。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux之概述和安装vm虚拟机

文章目录 操作系统概述硬件和软件操作系统常见操作系统 初识LinuxLinux的诞生Linux内核Linux发行版 虚拟机介绍虚拟机 VMware WorkStation安装虚拟化软件VMware WorkStation 安装查看VM网络连接设置VM存储位置 在VMware上安装Linux(发行版CentOS7)安装包获取CentOS7 安装 Mac系…

LeetCode热题100--19.删除链表的倒数第N个结点--中等

1. 题目 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&#xff1a;[] 示例…

git学习与使用(远程仓库、分支、工作流)

文章目录 前言简介git的工作流程git的安装配置git环境&#xff1a;git config --globalgit的基本使用新建目录初始化仓库&#xff08;repository&#xff09;添加到暂存区新增/修改/删除 文件状态会改变 提交到仓库查看提交&#xff08;commit&#xff09;的历史记录git其他命令…

《Android 应用开发基础教程》——第十四章:Android 多线程编程与异步任务机制(Handler、AsyncTask、线程池等)

目录 第十四章&#xff1a;Android 多线程编程与异步任务机制&#xff08;Handler、AsyncTask、线程池等&#xff09; &#x1f538; 14.1 为什么需要多线程&#xff1f; &#x1f538; 14.2 Handler Thread 模型 ✦ 使用 Handler 与 Thread 进行线程通信 ✦ 简要说明&am…

【JVM 01-引言入门篇】

JVM 引言篇01 笔记记录 1. 什么是JVM&#xff1f;2. 学习JVM有什么用&#xff1f;3. 常见的JVM4. 学习路线 学习资料来源-b站黑马 1. 什么是JVM&#xff1f; 定义&#xff1a;Java虚拟机&#xff08;Java Virtual Machine 简称JVM&#xff09;是运行所有Java程序的抽象计算机&a…

Pandas数据规整

&#xff08;1&#xff09;层次化索引 1.创建带层次化索引的df 第一种&#xff0c;直接创建 import pandas as pd import numpy as npdata pd.Series(np.random.randn(9),index [[a, a, a, b, b, c, c, d, d],[1, 2, 3, 1, 3, 1, 2, 2, 3]]) print(data) # a 1 -0.6416…

ThreadLocal线程本地变量在dubbo服务使用时候遇到的一个坑

我昨天遇到一个问题&#xff0c;就是我springboot项目里面有一个提供代办服务审核的dubbo接口&#xff0c;这个接口给房源项目调用&#xff0c;但是碰到一个问题就是&#xff0c;房源项目每天凌晨5点会查询满足条件过期的数据&#xff0c;然后调用我这边的代办审核dubbo接口&am…

从 0 到 1:Spring Boot 与 Spring AI 深度实战(基于深度求索 DeepSeek)

在人工智能技术与企业级开发深度融合的今天&#xff0c;传统软件开发模式与 AI 工程化开发的差异日益显著。作为 Spring 生态体系中专注于 AI 工程化的核心框架&#xff0c;Spring AI通过标准化集成方案大幅降低 AI 应用开发门槛。本文将以国产大模型代表 ** 深度求索&#xff…

upload-labs通关笔记-第20关 文件上传之杠点绕过

系列目录 upload-labs通关笔记-第1关 文件上传之前端绕过&#xff08;3种渗透方法&#xff09; upload-labs通关笔记-第2关 文件上传之MIME绕过-CSDN博客 upload-labs通关笔记-第3关 文件上传之黑名单绕过-CSDN博客 upload-labs通关笔记-第4关 文件上传之.htacess绕过-CSDN…

Vscode +Keil Assistant编译报错处理

Vscode Keil Assistant编译报错处理 1.报错图片内容 所在位置 行:1 字符: 25 chcp.com 65001 -Command & c:\Users\92170.vscode\extensions\cl.keil-a … ~ 不允许使用与号(&)。& 运算符是为将来使用而保留的&#xff1b;请用双引号将与号引起来(“&”)&…

VSCode C/C++ 开发环境完整配置及一些扩展用途(自用)update:2025/3/31

这里主要记录了一些与配置相关的内容。由于网上教程众多&#xff0c;部分解决方法并不能完全契合我遇到的问题&#xff0c;因此我选择以自己偏好的方式&#xff0c;对 VSCode 进行完整的配置&#xff0c;并记录在使用过程中遇到的问题及解决方案。后续内容也会持续更新和完善。…

Docker系列(二):开机自启动与基础配置、镜像加速器优化与疑难排查指南

引言 docker 的快速部署与高效运行依赖于两大核心环节&#xff1a;基础环境搭建与镜像生态优化。本期博文从零开始&#xff0c;系统讲解 docker 服务的管理配置与镜像加速实践。第一部分聚焦 docker 服务的安装、权限控制与自启动设置&#xff0c;确保环境稳定可用&#xff1b…

a16z:AI带来了全新的9种开发软件的模式

非常有启发的9条新兴模式&#xff0c;推荐给已经上手 vibeCoding 的读者们。 开发者正在将 AI 从简单的工具转变为构建软件的新基础。许多核心概念&#xff0c;如版本控制、模板、文档&#xff0c;甚至用户的定义&#xff0c;都在被重新思考。代理&#xff08;Agent&#xff09…

在 Excel 使用macro————仙盟创梦IDE

Dim filePath As StringDim fileContent As StringDim lines() As StringDim dataArray() As StringDim lineCount As LongDim maxCols As LongDim i As Long, j As Long 文件路径filePath "" 检查文件是否存在If Dir(filePath) "" ThenMsgBox "文件…

鸿蒙devEco studio如何创建模拟器

官网原文链接&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-emulator-create 操作步骤 点击菜单栏的Tools > Device Manager&#xff0c;点击右下角的Edit设置模拟器实例的存储路径Local Emulator Location&#xff0c;Mac默认存储在~/…

鸿蒙路由参数传递

页面test.ets 代码如下&#xff1a; import router from ohos.router Entry Component struct Test {State message: string Hello WorldState username: string huState password: string 1build() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWe…

springboot 控制层调用业务逻辑层,注入报错,无法自动装配 解决办法

报错&#xff1a; 解决&#xff1a;愿意是业务逻辑层&#xff0c;即service层的具体实现类没有加注解Service导致的&#xff0c;加上解决了&#xff01;&#xff01;

MySQL:11_事务

事务 一.CURD不加控制&#xff0c;会有什么问题&#xff1f; 二.什么是事务&#xff1f; 事务就是一组DML语句组成&#xff0c;这些语句在逻辑上存在相关性&#xff0c;这一组DML语句要么全部成功&#xff0c;要么全部失败&#xff0c;是一个整体。MySQL提供一种机制&#xf…

Linux中的文件系统和软硬连接

磁盘的访问方式 CHS&#xff08;柱面&#xff0c;磁头&#xff0c;扇区&#xff09; 法&#xff08;磁盘硬件查找&#xff09;&#xff1a; 确定柱面&#xff08;C&#xff09; 磁头臂移动到对应的柱面位置。例如&#xff0c;柱面号为 5&#xff0c;则磁头移动到第 5 个磁道组…

Spring AI:Java开发者的AI开发新利器

目录 一、引言 二、Spring AI 是什么 三、核心功能与特性 3.1 统一的 API 抽象 3.2 丰富的模型支持 3.3 低代码集成 3.4 结构化数据输出 3.5 流式数据响应 四、应用场景 4.1 智能客服系统 4.2 图像识别应用 4.3 数据分析与预测 五、快速上手 5.1 环境搭建 5.2 创…