Как перенести проект Xamarin.android на базе MVVMCross в управляемый Intune - PullRequest
0 голосов
/ 11 июня 2019

У меня нормально работает проект Android, в его основе лежит MVVMCross.

Проблема возникла, когда меня попросили управлять политиками защиты приложений с помощью Intune.

Теперь Intune заставляет меня использовать их управляемые действия и все другие управляемые пространства имен, предоставляемые Intune SDK.

В таком случае, как я могу это сделать?

Я пытался изменить базовый класс действий на Intune, в надежде использовать общие вещи, предоставляемые Mvvmcross, такие как IOC, инъекции зависимостей.

Я настроил запуск приложения, так как Intune хочет, чтобы это означало, что не будет никакого участия в вызовах класса setup / app.cs.

Итак, я запускаю действие Splash -> и он запускает MainActivity, в MainActivity я вручную внедряю все необходимые мне зависимости.

Поскольку все эти синтаксисы выдают исключение в управляемых действиях Intune пример: Mvx.RegisterType<IDeviceInformation, DeviceInformation>();

Исключение выше бросков.

Как продолжить эту миграцию, сохранив базовую функциональность MVVMcross без изменений?

1 Ответ

1 голос
/ 11 июня 2019

В этом отношении есть несколько решений, о которых я могу подумать.

Если вам нужен только DI, вы можете добавить еще один пакет DI Manager и обработать его оттуда, что будет проще, чем конфигурировать Mvx дляделать это только.

Если вам нужны другие возможности Mvx, вам придется делать то, что Mvx делает в своих базовых классах, и реализовывать их, принимая во внимание настройку соответствующих интерфейсов для ваших базовых классов.

В Android для того, чтобы настроить и выполнить действия по настройке, вам необходимо:

  • Зарегистрировать настройки в файле приложения для Android как сделано здесь

    this.RegisterSetupType<TMvxAndroidSetup>();

  • Реализуйте свою собственную базовую деятельность, которая учитывает реализацию IMvxEventSourceActivity, например здесь , а также MvxActivity like здесь для того, чтобы события и контекст данных / обработка модели представления

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

  • Также вам придется реализовать свой собственныйвсплескнапример, здесь , который реализует IMvxSetupMonitor и в конечном итоге вызывает здесь , вызывая MvxAndroidSetupSingleton.EnsureSingletonAvailable(ApplicationContext); и инициализируя монитор.
[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>();
    }
}

Это будет охватывать основы, я думаю.

Надеюсь, это поможет вам направить вас в правильном направлении

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...