【问题标题】:Error: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser错误:java.lang.NullPointerException:尝试调用虚拟方法'android.content.res.XmlResourceParser
【发布时间】:2017-07-13 12:31:22
【问题描述】:

我收到此错误。我是 android studio 新手,我需要创建此插件以便统一在运行时安装 apk

错误 - 尝试在空对象引用上调用虚拟方法 'android.content.Context Android.content.Context.getApplicationContext()'

插件类 -

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;
}

}

上下文类 -

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>

插件包装器:

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;
    }
}
}

编辑

【问题讨论】:

  • 在这里纠正android:name=".ContextClass"&gt;
  • 如何调用InstallApp 函数?如果来自 C#,请也发布该代码。
  • @Programmer 是的,我是从 C# 调用它...我已经添加了上面的代码
  • 我认为你也应该添加 C# 标签。我很高兴您决定使用 Java 和 C# 来执行此操作。我会在不需要 Java 的那个版本上提供帮助,但我没有正确的版本。我现在看到了问题,很快就会给出我的答案。
  • @Programmer 谢谢你.. 我很感激 :)

标签: c# android unity3d android-context android-fileprovider


【解决方案1】:

Contect from Java 插件是null。如果需要,必须将 Unity 的上下文发送到 Java 插件。

添加另一个接收Context 的参数,然后使用来自参数的上下文而不是来自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 和您要传递给函数的路径发送。

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 null 问题应该已经消失了。

编辑:

如果遇到异常:

尝试调用虚方法 'android.content.res.XmlResourceParser android.content.pm.packageItemInfo.loadXmlMetaData(android.c‌​ontent.pm.PackageMan‌​ager.java.lang.Strin‌​g)'

你必须做的事情很少。

1.将“.jar”插件放入您的UnityProject/Assets/Plugins/Android目录。

2.从您的“AndroidSDK/extras/android/support/v4/android-support-v4.jar”中复制“android-support-v4.jar” 将目录复制到您的 “UnityProject/Assets/Plugins/Android” 目录。

3.在您的UnityProject/Assets/Plugins/Android目录中创建一个名为“AndroidManifest.xml”的文件,并将以下代码放入其中。

确保将 "com.company.product" 替换为您自己的软件包名称。有 2 个出现这种情况的实例。您必须同时替换它们:

这些可以在 package="com.company.product"android:authorities="com.company.product.fileprovider" 中找到。不要更改或删除 "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>

4.在您的“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>

就是这样。

【讨论】:

  • 遗憾的是,我没有 gear-vr,所以我真的可能无法提供帮助,因为我无法重新创建该问题。不要忘记accept我的其他答案。同时,我认为您应该尝试其他论坛,例如thisthat。如果我发现任何东西,我会留下答案。
猜你喜欢
  • 1970-01-01
  • 2018-01-19
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 2018-04-03
  • 2020-10-31
  • 2018-09-07
  • 1970-01-01
相关资源
最近更新 更多