使用activityInfo.LoadXmlMetaData()读取元数据文件时出错

时间:2017-09-25 07:37:43

标签: xamarin.forms xamarin.android

在xamarin.android中实现weakfulIntentService。 读取元数据文件时出现问题 在BroadCastReceiver中读取metadatafile xml文件时输出null。

** XmlReader reader = activityInfo.LoadXmlMetaData(packageManager,WAKEFUL_META_DATA); **

广播接收器

SELECT * from holidays JOIN holiday_info ON holidays.holiday_id = holiday_info.holiday_id

清单

 namespace Squarelabs.Droid
{
[BroadcastReceiver]
public class AlarmReceiver : BroadcastReceiver
{
    private static string WAKEFUL_META_DATA = "squrelabs.inspection";
    public override void OnReceive(Context context, Intent intent)
    {
        WakefulIntentService.IAlarmListener alarmListener = 
        GetListener(context);

        if (alarmListener != null)
        {
            if (intent.Action == null)
            {

                alarmListener.SendWakefulWork(context);
            }
            else
            {
                WakefulIntentService.ScheduleAlarms(alarmListener, context, true);
            }
        }
    }

    private WakefulIntentService.IAlarmListener GetListener(Context context)
    {
        PackageManager packageManager = context.PackageManager;
        ComponentName componentName = new ComponentName(context, Class);

        try
        {
            ActivityInfo activityInfo = packageManager.GetReceiverInfo(componentName, PackageInfoFlags.MetaData);

            XmlReader reader = activityInfo.LoadXmlMetaData(packageManager, WAKEFUL_META_DATA);

            while (reader!=null)
            {
                if (reader.IsStartElement())
                {
                    if (reader.Name == "WakefulIntentService")
                    {
                        string className = reader.Value;
                        Class cls = Java.Lang.Class.ForName(className);
                        return ((WakefulIntentService.IAlarmListener)cls.NewInstance());
                    }
                }
                reader.MoveToNextAttribute();
            }

       } catch (NameNotFoundException e) {
        throw new RuntimeException("Cannot find own info???", e);
       } catch (XmlPullParserException e) {
        throw new RuntimeException("Malformed metadata resource XML", e);
       } catch (IOException e) {
        //throw new RuntimeException("Could not read resource XML", e);
       } catch (ClassNotFoundException e) {
        throw new RuntimeException("Listener class not found", e);
       } catch (IllegalAccessException e) {
        throw new RuntimeException("Listener is not public or lacks public constructor", e);
       } catch (InstantiationException e) {
        throw new RuntimeException("Could not create instance of listener", e);
      }
        return (null);
    }
}

资源中的xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto" android:versionCode="2" android:versionName="1.9.5" package="squrelabs.inspection">
<uses-sdk android:minSdkVersion="15" />

  <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  <uses-permission android:name="android.permission.WAKE_LOCK" />
  <uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
  <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

  <application android:label="Squarelabs" android:icon="@drawable/icon">
<receiver android:name="AlarmReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
   <meta-data android:name="squrelabs.inspection" android:resource="@xml/wakeful" />
</receiver>
</application>

请帮助我解决这个问题。

1 个答案:

答案 0 :(得分:0)

  

读取元数据文件时出现问题。在BroadCastReceiver中读取metadatafile xml文件时输出null。

您可以在MetaData上添加属性AlarmReceiver,并更改android:resource="@xml/wakeful"代码以直接从字符串加载资源。例如:

[MetaData("mTag", Value = "@string/WakefulIntentService")]

字符串资源是这样的:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="app_name">MetaDataDemo</string>
  <string name="WakefulIntentService">squrelabs.inspection.Droid.AppListener </string>

</resources>

然后你的最终目的是获得((WakefulIntentService.IAlarmListener)cls.NewInstance()),你可以替换代码:

        ActivityInfo activityInfo = packageManager.GetReceiverInfo(componentName, PackageInfoFlags.MetaData);

        XmlReader reader = activityInfo.LoadXmlMetaData(packageManager, WAKEFUL_META_DATA);

        while (reader!=null)
        {
            if (reader.IsStartElement())
            {
                if (reader.Name == "WakefulIntentService")
                {
                    string className = reader.Value;
                    Class cls = Java.Lang.Class.ForName(className);
                    return ((WakefulIntentService.IAlarmListener)cls.NewInstance());
                }
            }
            reader.MoveToNextAttribute();
        }

使用:

ComponentName cn = new ComponentName(context, Class);  
ActivityInfo info = context.PackageManager.GetReceiverInfo(cn, PackageInfoFlags.MetaData);
System.String mTag = info.MetaData.GetString("mTag"); 
Class cls = Java.Lang.Class.ForName(mTag);
return cls.NewInstance();

更新

尝试用var listener = ReflectionHelper.CreateInstance<WakefulIntentService.IAlarmListener>("Demo.AppListener", Assembly.GetExecutingAssembly().FullName);替换此代码,然后像这样更改字符串WakefulIntentService

<string name="WakefulIntentService">yournamespace.AppListener</string>

ReflectionHelper是这样的:

public static class ReflectionHelper
{

    public static T CreateInstance<T>(string fullName, string assemblyName)
    {
        string path = fullName + "," + assemblyName;
        Type o = Type.GetType(path);
        object obj = Activator.CreateInstance(o, true);
        return (T)obj;
    }

    public static T CreateInstance<T>(string assemblyName, string nameSpace, string className)
    {
        try
        {
            string fullName = nameSpace + "." + className;
            object ect = Assembly.Load(assemblyName).CreateInstance(fullName);
            return (T)ect;

        }
        catch
        {
            return default(T);
        }
    }
}