问题描述
我收到此错误.我是android studio的新手,我需要创建此插件以统一在运行时安装apk
I am getting this error.I am new to android studio and i need to create this plugin for unity to install an apk at runtime
错误-尝试在空对象引用上调用虚拟方法'android.content.Context Android.content.Context.getApplicationContext()'
Error - Attempt to invoke virtual method 'android.content.Context Android.content.Context.getApplicationContext()' on a null object reference
插件类-
package com.example.unitypluginappinstall;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.content.FileProvider;
import java.io.File;
public class PluginClass extends Activity {
static String errMessage;
public static String InstallApp(String ApkPath){
try {
errMessage = "test";
File toInstall = new File(ApkPath);
Uri apkUri = FileProvider.getUriForFile(ContextClass.context(),
ContextClass.context().getApplicationContext().getPackageName() +
".fileprovider", toInstall);
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData(apkUri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
ContextClass.context().startActivity(intent);
}
catch (Exception e){
errMessage = e.getMessage();
}
return errMessage;
}
}
ContextClass-
ContextClass -
package com.example.unitypluginappinstall;
import android.app.Application;
import android.content.Context;
public class ContextClass extends Application {
private static ContextClass instance;
public ContextClass(){
instance = this;
}
public static ContextClass instance(){
return instance;
}
public static Context context() {
return instance.getApplicationContext();
}
}
清单文件-
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.unitypluginappinstall">
<application android:allowBackup="true" android:label="@string/app_name"
android:supportsRtl="true">
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths"></meta-data>
</provider>
android:name=".ContextClass">
</application>
PluginWrapper:
PluginWrapper:
public class PluginWrapper : MonoBehaviour {
string savePath;
void Start () {
savePath = Path.Combine(Application.persistentDataPath, "data");
savePath = Path.Combine(savePath, "applaunchtest.apk");
Install();
}
void Install(){
try
{
//Install APK
GameObject.Find("TextDebug").GetComponent<Text().text"Installing...";
var plugin = new
AndroidJavaClass("com.example.unitypluginappinstall.PluginClass");
GameObject.Find("TextDebug").GetComponent<Text>().text =
plugin.CallStatic<string>("InstallApp", savePath);
}
catch(Exception e)
{
GameObject.Find("TextDebug").GetComponent<Text>().text = e.Message;
}
}
}
编辑-插件类
package com.example.unitypluginappinstall;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.content.FileProvider;
import java.io.File;
public class PluginClass extends Activity {
static String errMessage;
public static String InstallApp(Context context, String ApkPath){
try {
errMessage = "test";
File toInstall = new File(ApkPath);
Uri apkUri = FileProvider.getUriForFile(context,
context.getApplicationContext().getPackageName() +
".fileprovider", toInstall);
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData(apkUri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(intent);
}
catch (Exception e){
errMessage = e.getMessage();
}
return errMessage;
}
}
插件包装-
public class PluginWrapper : MonoBehaviour {
string savePath;
void Start () {
savePath = Path.Combine(Application.persistentDataPath, "data");
savePath = Path.Combine(savePath, "applaunchtest.apk");
Install();
}
void Install(){
try
{
//Install APK
AndroidJavaClass unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject unityActivity = unityClass.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject unityContext = unityActivity.Call<AndroidJavaObject>("getApplicationContext");
GameObject.Find("TextDebug").GetComponent<Text().text"Installing...";
var plugin = new
AndroidJavaClass("com.example.unitypluginappinstall.PluginClass");
GameObject.Find("TextDebug").GetComponent<Text>().text =
plugin.CallStatic<string>("InstallApp",unityContext, savePath);
}
catch(Exception e)
{
GameObject.Find("TextDebug").GetComponent<Text>().text = e.Message;
}
}
}
编辑
推荐答案
来自Java插件的Contect是null
.如果需要,您必须将Unity的上下文发送到Java插件.
The Contect from Java plugin is null
. If you need it, you have to send Unity's context to the Java plugin.
添加另一个接收Context
的参数,然后使用该参数中的Context而不是Android.content.Context.getApplicationContext()
中的那个.
Add a another parameter that receives the Context
then use that Context from the parameter not the one from Android.content.Context.getApplicationContext()
.
Java:
public static String InstallApp(Context context, String ApkPath){
try {
errMessage = "test";
File toInstall = new File(ApkPath);
Uri apkUri = FileProvider.getUriForFile(context,
context.getPackageName() +
".fileprovider", toInstall);
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData(apkUri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(intent);
}
catch (Exception e){
errMessage = e.getMessage();
}
return errMessage;
}
C#:
发送Unity Context
和要传递给函数的路径.
Send the Unity Context
and the path you want to pass to the function.
void Install()
{
try
{
GameObject.Find("TextDebug").GetComponent<Text>().text = "Installing...";
//Get Unity Context
AndroidJavaClass unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject unityActivity = unityClass.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject unityContext = unityActivity.Call<AndroidJavaObject>("getApplicationContext");
AndroidJavaClass plugin = new AndroidJavaClass("com.example.unitypluginappinstall.PluginClass");
string result = plugin.CallStatic<string>("InstallApp", unityContext, savePath);
}
catch (Exception e)
{
GameObject.Find("TextDebug").GetComponent<Text>().text = e.Message;
}
}
您可能还有其他不相关的错误,但Context
空问题应该消失了.
You may have other unrelated error but the Context
null problem should be gone.
如果出现异常:
您必须要做的几件事.
1 .将".jar"插件插入您的 UnityProject/Assets/Plugins/Android 目录.
1.Put the ".jar" Plugin your UnityProject/Assets/Plugins/Android directory.
2 .从您的"AndroidSDK/extras/android/support/v4/android-support-v4.jar"中复制"android-support-v4.jar" 目录到您的"UnityProject/Assets/Plugins/Android" 目录.
2.Copy "android-support-v4.jar" from your "AndroidSDK/extras/android/support/v4/android-support-v4.jar" directory to your "UnityProject/Assets/Plugins/Android" directory.
3 .在 UnityProject/Assets/Plugins/Android 目录中创建一个名为"AndroidManifest.xml"的文件,并将下面的代码放入其中.
3.Create a file called "AndroidManifest.xml" in your UnityProject/Assets/Plugins/Android directory and put the code below into it.
请确保将"com.company.product" 替换为您自己的程序包名称.出现了 2 个实例.您必须同时替换它们:
Make sure to replace "com.company.product" with your own package name. There are 2 instances where this appeared. You must replace both of them:
可在 package ="com.company.product" 和 android:authorities ="com.company.product.fileprovider" 中找到.不要更改或删除文件提供程序" ,也不要更改其他任何内容.
These are found in package="com.company.product" and android:authorities="com.company.product.fileprovider". Don't change or remove the "fileprovider" and don't change anything else.
这是"AndroidManifest.xml"文件:
Here is the "AndroidManifest.xml" file:
<?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>
4 .在"UnityProject/Assets/Plugins/Android/res/xml" provider_paths.xml "的新文件. >目录,并将代码放在下面.如您所见,您必须先创建一个 res 文件夹,然后创建一个 xml 文件夹.
4.Create a new file called "provider_paths.xml" in your "UnityProject/Assets/Plugins/Android/res/xml" directory and put the code below in it. As you can see, you have to create a res and then an xml folder.
请确保将"com.company.product" 替换为您自己的程序包名称.它只会一次出现.
Make sure to replace "com.company.product" with your own package name.It only appeared once.
这是您应放入此" provider_paths.xml "文件中的内容:
Here is what you should put into this "provider_paths.xml" file:
<?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>
就是这样.
这篇关于错误:java.lang.NullPointerException:尝试调用虚拟方法'android.content.res.XmlResourceParser的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!