如何将基于MVVMCross的Xamarin.android项目迁移到Intune托管的项目中

时间:2019-06-11 09:43:45

标签: xamarin xamarin.android mvvmcross intune

我有一个运行良好的android项目,它的核心使用MVVMCross。

当我被要求使用Intune管理应用保护策略时,问题就来了。

现在,Intune强迫我使用其托管活动以及Intune SDK提供的所​​有其他托管命名空间。

在这种情况下,我该如何进行呢?

我试图将活动基类更改为Intune的活动,以期使用Mvvmcross提供的常规功能,例如IOC,依赖项注入。

我按Intune的要求定制了应用程序启动,这意味着不会涉及任何setup / app.cs类调用。

所以我启动了Splash活动->并启动了MainActivity,在MainActivity中,我手动注入了我需要的所有依赖项。

因为所有这些语法都在Intune托管活动下引发异常 示例:Mvx.RegisterType<IDeviceInformation, DeviceInformation>();

以上引发异常。

如何继续进行此迁移,以保持MVVMcross基本功能完整?

1 个答案:

答案 0 :(得分:1)

我可以想到一些解决方案。

如果只需要DI,则可以添加另一个DI管理器程序包并从那里处理它,这比将Mvx配置为仅执行此操作要简单。

如果您需要Mvx的其他功能,则必须执行Mvx在其基类中所做的工作,并考虑到为基类设置适当的接口来实现它们。

在Android中,为了使设置和活动正常运行,您必须:

  • 完成here

    后,将设置注册到您的android应用文件中

    this.RegisterSetupType<TMvxAndroidSetup>();

  • 实施您自己的基本活动,该活动考虑到here之类的IMvxEventSourceActivityhere之类的MvxActivity的实现,以使事件发生以及数据上下文/视图模型处理

[Register("mvvmcross.platforms.android.views.base.MvxEventSourceActivity")]
public abstract class MvxEventSourceActivity
        : Activity, IMvxEventSourceActivity
{
    protected MvxEventSourceActivity()
    {
    }

    protected MvxEventSourceActivity(IntPtr javaReference, JniHandleOwnership transfer)
        : base(javaReference, transfer)
    {
    }

    protected override void OnCreate(Bundle bundle)
    {
        CreateWillBeCalled.Raise(this, bundle);
        base.OnCreate(bundle);
        CreateCalled.Raise(this, bundle);
    }

    protected override void OnDestroy()
    {
        DestroyCalled.Raise(this);
        base.OnDestroy();
    }

    protected override void OnNewIntent(Intent intent)
    {
        base.OnNewIntent(intent);
        NewIntentCalled.Raise(this, intent);
    }

    protected override void OnResume()
    {
        base.OnResume();
        ResumeCalled.Raise(this);
    }

    protected override void OnPause()
    {
        PauseCalled.Raise(this);
        base.OnPause();
    }

    protected override void OnStart()
    {
        base.OnStart();
        StartCalled.Raise(this);
    }

    protected override void OnRestart()
    {
        base.OnRestart();
        RestartCalled.Raise(this);
    }

    protected override void OnStop()
    {
        StopCalled.Raise(this);
        base.OnStop();
    }

    public override void StartActivityForResult(Intent intent, int requestCode)
    {
        StartActivityForResultCalled.Raise(this, new MvxStartActivityForResultParameters(intent, requestCode));
        base.StartActivityForResult(intent, requestCode);
    }

    protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
    {
        ActivityResultCalled.Raise(this, new MvxActivityResultParameters(requestCode, resultCode, data));
        base.OnActivityResult(requestCode, resultCode, data);
    }

    protected override void OnSaveInstanceState(Bundle outState)
    {
        SaveInstanceStateCalled.Raise(this, outState);
        base.OnSaveInstanceState(outState);
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            DisposeCalled.Raise(this);
        }
        base.Dispose(disposing);
    }

    public event EventHandler DisposeCalled;

    public event EventHandler<MvxValueEventArgs<Bundle>> CreateWillBeCalled;

    public event EventHandler<MvxValueEventArgs<Bundle>> CreateCalled;

    public event EventHandler DestroyCalled;

    public event EventHandler<MvxValueEventArgs<Intent>> NewIntentCalled;

    public event EventHandler ResumeCalled;

    public event EventHandler PauseCalled;

    public event EventHandler StartCalled;

    public event EventHandler RestartCalled;

    public event EventHandler StopCalled;

    public event EventHandler<MvxValueEventArgs<Bundle>> SaveInstanceStateCalled;

    public event EventHandler<MvxValueEventArgs<MvxStartActivityForResultParameters>> StartActivityForResultCalled;

    public event EventHandler<MvxValueEventArgs<MvxActivityResultParameters>> ActivityResultCalled;
}
[Register("mvvmcross.platforms.android.views.MvxActivity")]
public abstract class MvxActivity
    : MvxEventSourceActivity
    , IMvxAndroidView
{
    protected View _view;

    protected MvxActivity(IntPtr javaReference, JniHandleOwnership transfer)
        : base(javaReference, transfer)
    {
    }

    protected MvxActivity()
    {
        BindingContext = new MvxAndroidBindingContext(this, this);
        this.AddEventListeners();
    }

    public object DataContext
    {
        get { return BindingContext.DataContext; }
        set { BindingContext.DataContext = value; }
    }

    public IMvxViewModel ViewModel
    {
        get
        {
            return DataContext as IMvxViewModel;
        }
        set
        {
            DataContext = value;
            OnViewModelSet();
        }
    }

    public void MvxInternalStartActivityForResult(Intent intent, int requestCode)
    {
        StartActivityForResult(intent, requestCode);
    }

    public IMvxBindingContext BindingContext { get; set; }

    public override void SetContentView(int layoutResId)
    {
        _view = this.BindingInflate(layoutResId, null);

        SetContentView(_view);
    }

    protected virtual void OnViewModelSet()
    {
    }

    protected override void AttachBaseContext(Context @base)
    {
        if (this is IMvxSetupMonitor)
        {
            // Do not attach our inflater to splash screens.
            base.AttachBaseContext(@base);
            return;
        }
        base.AttachBaseContext(MvxContextWrapper.Wrap(@base, this));
    }

    private readonly List<WeakReference<Fragment>> _fragList = new List<WeakReference<Fragment>>();

    public override void OnAttachFragment(Fragment fragment)
    {
        base.OnAttachFragment(fragment);
        _fragList.Add(new WeakReference<Fragment>(fragment));
    }

    public List<Fragment> Fragments
    {
        get
        {
            var fragments = new List<Fragment>();
            foreach (var weakReference in _fragList)
            {
                if (weakReference.TryGetTarget(out Fragment f))
                {
                    if (f.IsVisible)
                        fragments.Add(f);
                }
            }

            return fragments;
        }
    }

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        ViewModel?.ViewCreated();
    }

    protected override void OnDestroy()
    {
        base.OnDestroy();
        ViewModel?.ViewDestroy(IsFinishing);
    }

    protected override void OnStart()
    {
        base.OnStart();
        ViewModel?.ViewAppearing();
    }

    protected override void OnResume()
    {
        base.OnResume();
        ViewModel?.ViewAppeared();
    }

    protected override void OnPause()
    {
        base.OnPause();
        ViewModel?.ViewDisappearing();
    }

    protected override void OnStop()
    {
        base.OnStop();
        ViewModel?.ViewDisappeared();
    }
}

public abstract class MvxActivity<TViewModel>
    : MvxActivity
    , IMvxAndroidView<TViewModel> where TViewModel : class, IMvxViewModel
{
    public new TViewModel ViewModel
    {
        get { return (TViewModel)base.ViewModel; }
        set { base.ViewModel = value; }
    }
}

  • 此外,您还必须实施自己的启动活动,例如here,该活动实现IMvxSetupMonitor,并且最终通过调用MvxAndroidSetupSingleton.EnsureSingletonAvailable(ApplicationContext);来调用设置here并初始化监视器。
[Register("mvvmcross.platforms.android.views.MvxSplashScreenActivity")]
public abstract class MvxSplashScreenActivity
    : MvxActivity, IMvxSetupMonitor
{
    protected const int NoContent = 0;

    private readonly int _resourceId;

    private Bundle _bundle;

    public new MvxNullViewModel ViewModel
    {
        get { return base.ViewModel as MvxNullViewModel; }
        set { base.ViewModel = value; }
    }

    protected MvxSplashScreenActivity(int resourceId = NoContent)
    {
        RegisterSetup();
        _resourceId = resourceId;
    }

    protected MvxSplashScreenActivity(IntPtr javaReference, JniHandleOwnership transfer)
        : base(javaReference, transfer)
    {
    }

    protected virtual void RequestWindowFeatures()
    {
        RequestWindowFeature(WindowFeatures.NoTitle);
    }

    protected override void OnCreate(Bundle bundle)
    {
        RequestWindowFeatures();

        _bundle = bundle;

        var setup = MvxAndroidSetupSingleton.EnsureSingletonAvailable(ApplicationContext);
        setup.InitializeAndMonitor(this);

        base.OnCreate(bundle);

        if (_resourceId != NoContent)
        {
            // Set our view from the "splash" layout resource
            // Be careful to use non-binding inflation
            var content = LayoutInflater.Inflate(_resourceId, null);
            SetContentView(content);
        }
    }

    private bool _isResumed;

    protected override void OnResume()
    {
        base.OnResume();
        _isResumed = true;
        var setup = MvxAndroidSetupSingleton.EnsureSingletonAvailable(ApplicationContext);
        setup.InitializeAndMonitor(this);
    }

    protected override void OnPause()
    {
        _isResumed = false;
        var setup = MvxAndroidSetupSingleton.EnsureSingletonAvailable(ApplicationContext);
        setup.CancelMonitor(this);
        base.OnPause();
    }

    public virtual async Task InitializationComplete()
    {
        if (!_isResumed)
            return;

        await RunAppStartAsync(_bundle);
    }

    protected virtual async Task RunAppStartAsync(Bundle bundle)
    {
        if (Mvx.IoCProvider.TryResolve(out IMvxAppStart startup))
        {
            if(!startup.IsStarted)
            {
                await startup.StartAsync(GetAppStartHint(bundle));
            }
            else
            {
                Finish();
            }
        }
    }

    protected virtual object GetAppStartHint(object hint = null)
    {
        return hint;
    }

    protected virtual void RegisterSetup()
    {
    }
}

public abstract class MvxSplashScreenActivity<TMvxAndroidSetup, TApplication> : MvxSplashScreenActivity
        where TMvxAndroidSetup : MvxAndroidSetup<TApplication>, new()
        where TApplication : class, IMvxApplication, new()
{
    protected MvxSplashScreenActivity(int resourceId = NoContent) : base(resourceId)
    {
    }

    protected override void RegisterSetup()
    {
        this.RegisterSetupType<TMvxAndroidSetup>();
    }
}

这将涵盖我认为的基本知识。

希望它可以帮助您指引正确的方向