Error: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser

匿名 (未验证) 提交于 2019-12-03 02:33:02

问题:

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

Error - Attempt to invoke virtual method 'android.content.Context Android.content.Context.getApplicationContext()' on a null object reference

Plugin Class -

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 -

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

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

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

EDIT - Plugin Class

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

Plugin Wrapper -

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

EDIT

回答1:

The Contect from Java plugin is null. If you need it, you have to send Unity's context to the Java plugin.

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#:

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

You may have other unrelated error but the Context null problem should be gone.

EDIT:

If you get the Exception:

You have to do few things.

1.Put the ".jar" Plugin your UnityProject/Assets/Plugins/Android directory.

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.Create a file called "AndroidManifest.xml" in your UnityProject/Assets/Plugins/Android directory and put the code below into it.

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:

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.

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

Make sure to replace "com.company.product" with your own package name. It only appeared once.

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> 

That's it.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!