我找到了Java的代码片段。我如何用C#Unity编写这样的代码?
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.fromFile(new File("link to downloaded file")),"application/vnd.android.package-archive");
startActivity(intent);
随着Unity的更新版本,它变得更加复杂Assets/Plugins/Android/res
被弃用。还有Android 9.0Android。支持v4
被合并到androidx中。核心
所有东西都被重新命名和移动。幸运的是,Unity现在在支持Android插件方面做得更好了一些,因此使用这个解决方案,您不再需要向项目中添加任何jar或aar。
请注意,Android有一堆与此安装过程相关的唠叨屏幕。每个应用程序都有一个一次性接受不受信任的版本的屏幕,如果您在设备上使用了google play,play protected会添加一堆屏幕,使您的应用程序看起来像恶意软件。(这是一件好事,因为您应该只在您拥有的信息亭模式风格的设备上执行这些操作,您可以在其中关闭Play Protect。)
增加了程序员的答案。在Unity 2019和2020中,您可以直接在Unity中编译插件,而不再需要jar文件。2019年,它需要在Assets/Plugins/Android
中,并有几个额外的文件。2020年,文件夹只需要后缀。androidlib
可以位于资产
中的任何位置。
package.androidlib
src
main
res
xml
provider_paths.xml
AndroidManifest.xml
build.gradle
AndroidManifest.xml (only for 2019)
project.properties (only for 2019)
提供者路径。xml:正如程序员所解释的。
AndroidManifest.xml:主要是为了给这个新库一个bundle ID。这不应该匹配任何其他ID;它可以是任何东西,通常是com.companyname.packagename
。请注意,它在main/
文件夹内
我们也可以在这里做其余的AndroidManifest.xml的东西,因为现在所有的AndroidManifest.xml文件都将在最终的APK中得到合并。FileProvider包已更改为androidx.core.content.FileProvider
。
我注意到你需要Android系统。准许请求安装软件包;但我不确定您是否需要像Kaushix建议的那样读取外部存储/写入外部存储。(可能在某些设备上?我认为这是项目设置所涵盖的。)-
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.anything.anythingelse">
<application>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
</manifest>
建筑gradle:这应该与你的项目目标和min SDK版本相匹配。如果更少也没关系,但target至少需要28岁才能使用androidx。
apply plugin: 'com.android.library'
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 16
targetSdkVersion 28
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0'
}
对于2019年,额外的AndroidManifest.xml和project.properties文件纯粹是为了告诉Unity构建这个文件夹而存在的。在2020年,Unity的聪明到不需要它们。
AndroidManifest。xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- This extra manifest, as well as project.properties in this folder shouldn't be necessary with the newer gradle project format. Can remove if you upgrade to 2020.1. -->
</manifest>
project.properties:
android.library=true
AndroidPostProcess。反恐精英:
我们还需要一个编辑器脚本来在主gradle文件中启用AndroidX支持,并打开Jetifier,它应该修复针对旧android.support库编译的任何其他插件。
using UnityEditor.Android;
public class AndroidPostProcess : IPostGenerateGradleAndroidProject
{
public int callbackOrder => 0;
public void OnPostGenerateGradleAndroidProject(string path)
{
string gradlePropertiesPath = path + "/gradle.properties";
string[] lines = File.ReadAllLines(gradlePropertiesPath);
StringBuilder builder = new StringBuilder();
foreach (string line in lines)
{
if (line.Contains("android.useAndroidX"))
{
continue;
}
if (line.Contains("android.enableJetifier"))
{
continue;
}
builder.AppendLine(line);
}
builder.AppendLine("android.useAndroidX=true");
builder.AppendLine("android.enableJetifier=true");
File.WriteAllText(gradlePropertiesPath, builder.ToString());
}
}
我只是想在@程序员给出的梦幻般的答案中添加一个更新,以反映AndroidSDK和Unity的变化。我希望它能对其他人有用。我正在使用SDK版本26和Unity 2017.3.1。我对几乎所有这些都是新的,所以如果我错过或误解了什么,请纠正我!
>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.company.productsomethingelse" xmlns:tools="http://schemas.android.com/tools" android:installLocation="preferExternal" android:versionName="1.0" android:versionCode="1">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application android:theme="@style/UnityThemeSelector" android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="true">
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.company.product.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="26" />
</manifest>
请注意,我还将com.company.product的第一个实例更改为com.company.productsomethingelse
虽然在构建过程中Unity给出了过时的警告——如果不推荐使用Assets/Plugins/Android/res中的Android资源,请将您的资源转移到AAR或Android库中。。要解决这个问题,请创建一个新的zip文件并放置您的AndroidManifest。xml位于zip的顶层。然后添加提供者路径。@Programmer将详细的xml放入文件夹结构res/xml/provider_path中的zip中。xml。重新命名拉链,使其更美观。aar文件扩展名,然后将其拖到Unity project Assets/Plugins文件夹中。我更改AndroidManifest的原因。com的xml条目。公司productsomethingelse是我使用com的时候。公司产品统一构建过程引发了命名冲突。我认为,因为清单现在在一个单独的aar中,所以它需要有一个不同的包名。
您可以构建一个jar/aar插件,并从C#调用它。这更容易做到。
另一种解决方案是使用AndroidJavaObject
和AndroidJavaClass
直接执行此操作,而无需插件。使用AndroidJavaObject
和AndroidJavaClass
执行此操作需要大量测试才能正确执行。下面是我用来执行此操作的。它下载一个APK然后安装它。
首先创建一个名为"TextDebug"的UI文本,以便在下载/安装过程中看到发生了什么。如果你不这样做,你必须注释掉或删除所有GameObject。查找("TextDebug")。GetComponent
void Start()
{
StartCoroutine(downLoadFromServer());
}
IEnumerator downLoadFromServer()
{
string url = "http://apkdl.androidapp.baidu.com/public/uploads/store_2/f/f/a/ffaca37aaaa481003d74725273c98122.apk?xcode=854e44a4b7e568a02e713d7b0af430a9136d9c32afca4339&filename=unity-remote-4.apk";
string savePath = Path.Combine(Application.persistentDataPath, "data");
savePath = Path.Combine(savePath, "AntiOvr.apk");
Dictionary<string, string> header = new Dictionary<string, string>();
string userAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36";
header.Add("User-Agent", userAgent);
WWW www = new WWW(url, null, header);
while (!www.isDone)
{
//Must yield below/wait for a frame
GameObject.Find("TextDebug").GetComponent<Text>().text = "Stat: " + www.progress;
yield return null;
}
byte[] yourBytes = www.bytes;
GameObject.Find("TextDebug").GetComponent<Text>().text = "Done downloading. Size: " + yourBytes.Length;
//Create Directory if it does not exist
if (!Directory.Exists(Path.GetDirectoryName(savePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(savePath));
GameObject.Find("TextDebug").GetComponent<Text>().text = "Created Dir";
}
try
{
//Now Save it
System.IO.File.WriteAllBytes(savePath, yourBytes);
Debug.Log("Saved Data to: " + savePath.Replace("/", "\\"));
GameObject.Find("TextDebug").GetComponent<Text>().text = "Saved Data";
}
catch (Exception e)
{
Debug.LogWarning("Failed To Save Data to: " + savePath.Replace("/", "\\"));
Debug.LogWarning("Error: " + e.Message);
GameObject.Find("TextDebug").GetComponent<Text>().text = "Error Saving Data";
}
//Install APK
installApp(savePath);
}
public bool installApp(string apkPath)
{
try
{
AndroidJavaClass intentObj = new AndroidJavaClass("android.content.Intent");
string ACTION_VIEW = intentObj.GetStatic<string>("ACTION_VIEW");
int FLAG_ACTIVITY_NEW_TASK = intentObj.GetStatic<int>("FLAG_ACTIVITY_NEW_TASK");
AndroidJavaObject intent = new AndroidJavaObject("android.content.Intent", ACTION_VIEW);
AndroidJavaObject fileObj = new AndroidJavaObject("java.io.File", apkPath);
AndroidJavaClass uriObj = new AndroidJavaClass("android.net.Uri");
AndroidJavaObject uri = uriObj.CallStatic<AndroidJavaObject>("fromFile", fileObj);
intent.Call<AndroidJavaObject>("setDataAndType", uri, "application/vnd.android.package-archive");
intent.Call<AndroidJavaObject>("addFlags", FLAG_ACTIVITY_NEW_TASK);
intent.Call<AndroidJavaObject>("setClassName", "com.android.packageinstaller", "com.android.packageinstaller.PackageInstallerActivity");
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
currentActivity.Call("startActivity", intent);
GameObject.Find("TextDebug").GetComponent<Text>().text = "Success";
return true;
}
catch (System.Exception e)
{
GameObject.Find("TextDebug").GetComponent<Text>().text = "Error: " + e.Message;
return false;
}
}
对于Android API 24及以上版本,由于API发生了更改,因此需要使用不同的代码。下面的C#代码基于这个Java答案。
//For API 24 and above
private bool installApp(string apkPath)
{
bool success = true;
GameObject.Find("TextDebug").GetComponent<Text>().text = "Installing App";
try
{
//Get Activity then Context
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject unityContext = currentActivity.Call<AndroidJavaObject>("getApplicationContext");
//Get the package Name
string packageName = unityContext.Call<string>("getPackageName");
string authority = packageName + ".fileprovider";
AndroidJavaClass intentObj = new AndroidJavaClass("android.content.Intent");
string ACTION_VIEW = intentObj.GetStatic<string>("ACTION_VIEW");
AndroidJavaObject intent = new AndroidJavaObject("android.content.Intent", ACTION_VIEW);
int FLAG_ACTIVITY_NEW_TASK = intentObj.GetStatic<int>("FLAG_ACTIVITY_NEW_TASK");
int FLAG_GRANT_READ_URI_PERMISSION = intentObj.GetStatic<int>("FLAG_GRANT_READ_URI_PERMISSION");
//File fileObj = new File(String pathname);
AndroidJavaObject fileObj = new AndroidJavaObject("java.io.File", apkPath);
//FileProvider object that will be used to call it static function
AndroidJavaClass fileProvider = new AndroidJavaClass("android.support.v4.content.FileProvider");
//getUriForFile(Context context, String authority, File file)
AndroidJavaObject uri = fileProvider.CallStatic<AndroidJavaObject>("getUriForFile", unityContext, authority, fileObj);
intent.Call<AndroidJavaObject>("setDataAndType", uri, "application/vnd.android.package-archive");
intent.Call<AndroidJavaObject>("addFlags", FLAG_ACTIVITY_NEW_TASK);
intent.Call<AndroidJavaObject>("addFlags", FLAG_GRANT_READ_URI_PERMISSION);
currentActivity.Call("startActivity", intent);
GameObject.Find("TextDebug").GetComponent<Text>().text = "Success";
}
catch (System.Exception e)
{
GameObject.Find("TextDebug").GetComponent<Text>().text = "Error: " + e.Message;
success = false;
}
return success;
}
编辑:
如果出现例外情况:
尝试调用虚拟方法'android.content.res.XmlResourceParserandroid.content.pm.packageItemInfo.loadXmlMetaData(android. content.pm.PackageManager.java.lang.Strin g)'
你几乎不需要做什么。
1.将"android-support-v4.jar"从您的"AndroidSDK/附加功能/android/support/v4/android-support-v4.jar"目录复制到您的"UnityProject/资产/插件/Android"目录。
2.在UnityProject/Assets/Plugins/Android目录中创建一个名为“AndroidManifest.xml”的文件,并将下面的代码放入其中。
确保用自己的软件包名称替换“com.company.product”。有两个例子出现了这种情况。必须同时更换这两个部件:
这些可以在package=“com.company.product”和android:authorities=“com.company.product.fileprovider”中找到。不要更改或删除“文件提供程序”,也不要更改任何其他内容。
以下是“AndroidManifest.xml”文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.company.product" xmlns:tools="http://schemas.android.com/tools" android:installLocation="preferExternal" android:versionName="1.0" android:versionCode="1">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application android:theme="@style/UnityThemeSelector" android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="true">
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.company.product.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23" />
</manifest>
3.在“UnityProject/Assets/Plugins/Android/res/xml”目录中创建一个名为“provider_paths.xml”的新文件,并将下面的代码放入其中。如您所见,您必须创建一个res,然后创建一个xml文件夹。
确保用自己的软件包名称替换“com.company.product”。它只出现过一次。
以下是你应该放入这个"provider_paths.xml"文件的内容:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!--<external-path name="external_files" path="."/>-->
<external-path path="Android/data/com.company.product" name="files_root" />
<external-path path="." name="external_storage_root" />
</paths>
首先你需要安装Golang,关于Golang的安装,参见官方文档 install instructions。 下载 你需要获取Gitea的源码,最方便的方式是使用 go 命令。执行以下命令: go get -d -u code.gitea.io/gitea cd $GOPATH/src/code.gitea.io/gitea 然后你可以选择编译和安装的版本,当前你有多个选择。如果你想编译 mas
使用指南 - 代码安装 - 安装方法 - 如何手动安装代码 只有在正确地添加了百度统计代码后,才能获取尽可能准确的流量数据,代码安装过程中需要注意以下几点: 代码的安装位置要正确,请将异步分析代码安装在标签</head>标记前。 一个页面中不要重复安装相同的代码,统计有去重规则,一般不会重复计算。一段代码生效后,另外一段代码就会废弃,但建议只安装一段代码。 不要对代码有任何编辑操作,随意编辑代码会
使用指南 - 代码安装 - 安装方法 - 如何自动安装代码 如果您是直接向空间提供商购买的网站,请向该空间提供商询问您网站的FTP用户名和密码。 如果您是委托建站公司为您建立的网站,请提前询问建站公司,网站的FTP用户名和密码,一般该类公司在建站完成后,都会以邮件形式向您发送网站FTP用户名和密码,请您仔细查询以获得您网站的FTP用户名和密码。 如果您网站有专门人员进行管理,请向他们询问,以获得网
我正在尝试从源代码处安装Rundeck。我尝试了Linux的三种不同发行版(Debian、Red Hat和SUSE发行版)。所有人都有失败的经历。在继续之前,我安装make命令、Java和Git。“make”命令在我尝试过的每一个Linux发行版上都是失败的。“./gradlew build”命令也没有成功。 配置项目:生成版本3.2.7-快照 任务:rundeckapp:grails-spa:r
我是全栈开发者(PHP JS)。 我想要一个后端VS代码和一个前端VS代码。 我在教程中看到了一个绿色的VS代码,但我不知道如何将两个VS代码安装在一起。
本书面向的是已经对Go语言有一定的经验,希望能了解它的底层机制的用户。因此,只推荐从源代码安装Go。 Go源码安装 在Go的源代码中,有些部分是用Plan 9 C和AT&T汇编写的,因此假如你要想从源码安装,就必须安装C的编译工具。 在Mac系统中,只要你安装了Xcode,就已经包含了相应的编译工具。 在类Unix系统中,需要安装gcc等工具。例如Ubuntu系统可通过在终端中执行sudo apt