Launching error on Android Mdpi Tablet: black screen shows - android

Hey I am working on Xamarin and Mvvmcross, my issue is, when I start the app on (Samsung Galaxy Tab 3) Mdpi device then it show black screen and nothing happens,
here is my code,
Splash.cs
namespace Mobile.UI.Droid
{
[Activity(
Label = "Mobile Tasks"
, MainLauncher = true
, Icon = "#drawable/icon"
,Theme = "#style/MyActionBarSplash"
, NoHistory = true)]
public class SplashScreen : MvxSplashScreenActivity
{
public SplashScreen()
: base(Resource.Layout.SplashScreen)
{
}
}
}
setup.cs
public class Setup : MvxAndroidSetup
{
Context _context;
public Setup(Context applicationContext) : base(applicationContext)
{
_context = applicationContext;
CurrentPlatform.Init();
Insights.Initialize(XamarinInsightsConstants.APIKey, applicationContext);
}
protected override IMvxAndroidViewPresenter CreateViewPresenter()
{
var presenter = new CustomDroidViewPresenter();
Mvx.RegisterSingleton(presenter);
return presenter;
}
protected override IMvxApplication CreateApp()
{
return new Core.App();
}
protected override System.Collections.Generic.IList<string> ViewNamespaces
{
get
{
var toReturn = base.ViewNamespaces;
toReturn.Add("MOBILE.Mobile.UI.Droid.Controls");
toReturn.Add("MOBILE.Mobile.UI.Droid.Utilities");
return toReturn;
}
}
protected override IMvxTrace CreateDebugTrace()
{
return new DebugTrace();
}
protected override void InitializeLastChance()
{
var errorHandler = new ErrorDisplayer(ApplicationContext);
//Cirrious.MvvmCross.Plugins.Color.PluginLoader.Instance.EnsureLoaded();
base.InitializeLastChance();
Mvx.RegisterSingleton<IDeviceDetails>(new CustomDroidDetails());
//Mvx.RegisterSingleton<ILogger>(new DroidLogger());
Mvx.RegisterSingleton<IVersionDetail>(new VersionDetail());
}
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
base.FillTargetFactories(registry);
registry.RegisterFactory(new MvxCustomBindingFactory<LinearLayout>("ShapeBackground", (view) => new ShapeBackgroundBinding(view)));
registry.RegisterFactory(new MvxCustomBindingFactory<TextView>("CustomText", (view) => new CustomTextBinding(view)));
}
}
VersionDetail.cs
public class VersionDetail : IVersionDetail
{
public string GetAppVersion()
{
var version = Application.Context.PackageManager.GetPackageInfo(Application.Context.PackageName, 0).VersionName;
return version;
}
}
CustomDroidDetails
public class CustomDroidDetails : IDeviceDetails
{
public Platform Platform
{
get { return Platform.Droid; }
}
public DeviceType DeviceType
{
get { return DeviceType.Phone; }
}
}
logcat
Error

Related

Android PowerMockito of TextUtils returns wrong result

I have updated to Android 31 and Android Studio Dolphin and now my tests are failing because of TextUtils.isEmpty() returns wrong result.
I have this method to mock TextUtils.isEmpty().
protected void mockTextUtilsIsEmpty() {
PowerMockito.mockStatic(TextUtils.class);
PowerMockito.when(TextUtils.isEmpty(any(CharSequence.class))).thenAnswer(invocation -> {
String val = (String) invocation.getArguments()[0];
return val == null || val.length() == 0;
});
}
This is my test class.
#RunWith(PowerMockRunner.class) #PrepareForTest(TextUtils.class)
public class CustomerDetailsPresenterTest extends BaseTest {
#Rule TrampolineSchedulerRule trampolineSchedulerRule = new TrampolineSchedulerRule();
#Mock GetCustomerUseCase getCustomerUseCase;
#Mock GetMenuItemsUseCase getMenuItemsUseCase;
#Mock RolesManager rolesManager;
#Mock CustomerDetailsPresenter.View view;
private CustomerDetailsPresenter presenter;
private final int customerId = 1;
#Before public void setUp() {
mockTextUtilsIsEmpty();
presenter = new CustomerDetailsPresenter(getCustomerUseCase, getMenuItemsUseCase, rolesManager);
presenter.setView(view);
}
#Test public void shouldDisplayCustomerWithEmptyData() {
// Given
CustomerDetails customerDetails = CustomerDetails.newBuilder()
.build();
// When
Mockito.when(getCustomerUseCase.execute(customerId)).thenReturn(Single.just(customerDetails));
presenter.getCustomerDetails(customerId);
//Then
Mockito.verify(view).showRefreshing();
Mockito.verify(view).hideRefreshing();
Mockito.verify(view).displayCustomerEmailUnknown();
Mockito.verify(view).displayCustomerNoteUnknown();
}
}
This is my actual class that I want to test.
public class CustomerDetailsPresenter implements Presenter{
private final GetCustomerUseCase getCustomerUseCase;
private final GetMenuItemsUseCase getMenuItemsUseCase;
private final RolesManager rolesManager;
private CompositeDisposable disposables;
private View view;
#Inject public CustomerDetailsPresenter(
GetCustomerUseCase getCustomerUseCase,
GetMenuItemsUseCase getMenuItemsUseCase,
RolesManager rolesManager
) {
this.getCustomerUseCase = getCustomerUseCase;
this.getMenuItemsUseCase = getMenuItemsUseCase;
this.rolesManager = rolesManager;
}
public void setView(View view) {
this.view = view;
}
public void getCustomerDetails(int id) {
disposables = RxUtil.initDisposables(disposables);
if (rolesManager.isUserReadOnly()) {
view.showScreenAsReadOnly();
}
view.showRefreshing();
Disposable disposable = getCustomerUseCase.execute(id)
.doOnSuccess(customerDetails -> view.hideRefreshing())
.subscribe(customerDetails -> {
if (customerDetails != null) {
if (TextUtils.isEmpty(customerDetails.getInvoiceEmail())) {
view.displayCustomerEmailUnknown();
} else {
view.displayCustomerEmail(customerDetails.getInvoiceEmail());
}
if (TextUtils.isEmpty(customerDetails.getBillingNote())) {
view.displayCustomerNoteUnknown();
} else {
view.displayCustomerNote(customerDetails.getBillingNote());
}
view.displayCustomerAddress(customerDetails);
view.displayLastModified(customerDetails);
} else {
view.hideCustomerSecondAndThirdPhones();
}
} else {
view.hideCustomerDetails();
}
},
view::handleError
);
disposables.add(disposable);
What could be the problem?
So, in this part, it always goes to the else part of the statement, and as you can in my unit test that should not happen since I am providing null to invoice email field.
if (TextUtils.isEmpty(customerDetails.getInvoiceEmail())) {
view.displayCustomerEmailUnknown();
} else {
view.displayCustomerEmail(customerDetails.getInvoiceEmail());
}
Any ideas?

Porting View Renderer in .net

I am currently migrating my Xamarin.Forms app to .NET MAUI, and having a difficulty in migrating view renderer. In .NET MAUI I am using camera2 in my app, and using the renderer for same.
My Xamarin forms code is
public class CameraRecordV3 : View
{
public static readonly BindableProperty StartProperty = BindableProperty.Create(
"Start", typeof(int), typeof(int), 6000);
public int Start
{
set { SetValue(StartProperty, value); }
get { return (int)GetValue(StartProperty); }
}
}
using iVue.Views;
using System.ComponentModel;
using Microsoft.Maui.Controls.Platform;
using Microsoft.Maui.Controls.Handlers.Compatibility;
namespace iVue.Platforms.Android.Renderers;
public class CameraRecordRenderer_V3 : ViewRenderer<CameraRecordV3, CameraRecordControl_V3>
{
private CameraRecordControl_V3 _cameraControl;
private DisplayTimeHelper _displayTimeHelper = new DisplayTimeHelper();
public CameraRecordRenderer_V3(Context context)
: base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<CameraRecordV3> e)
{
base.OnElementChanged(e);
if (Control == null)
{
_cameraControl = new CameraRecordControl_V3(Context, e.NewElement);
SetNativeControl(_cameraControl);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
var model = (CameraRecordV3)sender;
base.OnElementPropertyChanged(sender, e);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_cameraControl.Dispose();
if(Control != null)
Control.Dispose();
}
}
}
CameraRecordControl_V3 is a viewgroup which contains a native view for android, which contains buttons and camera
public class CameraRecordControl_V3 : ViewGroup
{
public CameraRecordControl_V3(Context context, CameraRecordV3 vm) : base(context)
{
_activity = this.Context as Activity;
_view = _activity.LayoutInflater.Inflate(Resource.Layout.CameraRecordLayoutV2, this, false);
AddView(_view);
_toolbar = (Toolbar)_view.FindViewById(Resource.Id.toolbar);
textureView = (AutoFitTextureView)_view.FindViewById(Resource.Id.textureview)
_questionTitleView = (Button)_view.FindViewById(Resource.Id.Start);
}
}
I tried using handler in .net maui but no luck with it.
My Maui Code is as follows
public interface ICameraRecordV3 : IView
{
public int StartTime { get; }
}
public partial class CameraRecordV3Handler
{
public static PropertyMapper<ICameraRecordV3, CameraRecordV3Handler> CustomMapper
= new PropertyMapper<ICameraRecordV3, CameraRecordV3Handler>(ViewHandler.ViewMapper)
{
[nameof(ICameraRecordV3.StartTime)] = MapStartTime,
};
public CameraRecordV3Handler() : base(CustomMapper)
{
}
public CameraRecordV3Handler(PropertyMapper mapper = null) : base(mapper ?? CustomMapper)
{
}
}
public class CameraRecordV3 : View, ICameraRecordV3
{
public static readonly BindableProperty StartProperty = BindableProperty.Create(
"StartTime", typeof(int), typeof(int), 6000);
public int Start
{
set { SetValue(StartTimeProperty, value); }
get { return (int)GetValue(StartTimeProperty); }
}
}
//Platform Specific code
public partial class CameraRecordV3Handler : ViewHandler<ICameraRecordV3, CameraRecordControl_V3>
{
private CameraRecordControl_V3 _cameraControl;
protected override CameraRecordControl_V3 CreatePlatformView()
{
_cameraControl = new CameraRecordControl_V3(Context, null);
return _cameraControl;
}
protected override void ConnectHandler(CameraRecordControl_V3 platformView)
{
base.ConnectHandler(platformView);
}
private static void MapStartTime(CameraRecordV3Handler handler, ICameraRecordV3 arg2)
{
handler.PlatformView?.UpdateStartTime(arg2.StartTime);
}
}
//MauiProgram
builder.ConfigureMauiHandlers(handlers =>
{
#if __ANDROID__
handlers.AddHandler(typeof(CameraRecordV3), typeof(iVue.Handlers.CameraRecordV3Handler));
#endif
});
You can continue to use CustomRenderer in MAUI, you just need to Remove any ExportRenderer directives as they won't be needed in .NET MAUI. And then configure each renderer using conditional compilation for each platform. You can replace handlers.AddCompatibilityRenderer with handlers.AddHandler in the documentation. Using handlers.AddCompatibilityRenderer will cause a crash.

How can i pass an IDialogInterfaceOnDismissListener without my application crashing?

I've got an issue with my Xamarin.Android application regarding IDialogInterfaceOnDismissListener.
My repro sample:
public enum ConfirmationResult
{
Cancel,
Yes,
No
}
public interface IDialogService
{
Task<ConfirmationResult> ConfirmAsync(string title, string message, string acceptText, string declineText);
}
public class DialogService : IDialogService
{
class DismissDelegateListener : IDialogInterfaceOnDismissListener, IDialogInterfaceOnCancelListener
{
private Action _callback;
public DismissDelegateListener()
{
}
public DismissDelegateListener(Action callback)
{
_callback = callback;
}
public void Dispose()
{
_callback = null;
}
public IntPtr Handle { get; }
public void OnCancel(IDialogInterface dialog)
{
_callback?.Invoke();
}
public void OnDismiss(IDialogInterface dialog)
{
_callback?.Invoke();
}
}
private readonly WeakReference<Context> _activity;
public DialogService(Context activity)
{
_activity = new WeakReference<Context>(activity);
}
public async Task<ConfirmationResult> ConfirmAsync(string title, string message, string acceptText, string declineText)
{
Context target;
if (!_activity.TryGetTarget(out target))
return ConfirmationResult.Cancel;
TaskCompletionSource<ConfirmationResult> tcs = new TaskCompletionSource<ConfirmationResult>();
var builder = new AlertDialog.Builder(target);
var d = builder
.SetTitle(title)
.SetMessage(message)
.SetPositiveButton(acceptText, (sender, args) =>
{
tcs.SetResult(ConfirmationResult.Yes);
(sender as AlertDialog)?.Dispose();
})
.SetNegativeButton(declineText, (sender, args) =>
{
tcs.SetResult(ConfirmationResult.No);
(sender as AlertDialog)?.Dispose();
})
// if this line is uncommented my application crashes once the dialog is opened
// .SetOnCancelListener(new DismissDelegateListener(() => { tcs.SetResult(ConfirmationResult.Cancel); }))
.Create();
d.Show();
return await tcs.Task;
}
}
As soon as i call SetOnCancelListener my application will crash with the error message System.InvalidCastException: Specified cast is not valid.
To me everything appears to be correct - i am passing an implementation of the requested interface and my implementation isn't all that difficult either.
Does this problem ring a bell to anyone?
Deriving from Java.Lang.Object was the solution.
class DismissDelegateListener : Java.Lang.Object, IDialogInterfaceOnDismissListener, IDialogInterfaceOnCancelListener
//class DismissDelegateListener : IDialogInterfaceOnDismissListener, IDialogInterfaceOnCancelListener
{
private Action _callback;
public DismissDelegateListener()
{
}
public DismissDelegateListener(Action callback)
{
_callback = callback;
}
protected override void Dispose(bool disposing)
{
_callback = null;
base.Dispose(disposing);
}
public void OnCancel(IDialogInterface dialog)
{
_callback?.Invoke();
}
public void OnDismiss(IDialogInterface dialog)
{
_callback?.Invoke();
}
}

mvvmcross xamarin android activity Show strange behavoir

I have two Activities like
[Activity(Label = "View for FirstViewModel", MainLauncher = true)]
public class FirstView : MvxActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.FirstView);
}
}
[Activity(Label = "View for SecondViewModel", MainLauncher = false)]
public class SecondView : MvxActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.SecondView);
}
}
and two ViewModels
public class FirstViewModel
: MvxViewModel
{
private string _hello = "Hello MvvmCross 1";
public FirstViewModel()
{
}
public string Hello
{
get { return _hello; }
set { _hello = value; RaisePropertyChanged(() => Hello); }
}
public ICommand Next
{
get
{
return new MvxCommand(() => ShowViewModel<SecondViewModel>());
}
}
}
public class SecondViewModel : MvxViewModel
{
public SecondViewModel()
{
}
private string _hello = "Hello MvvmCross 2";
public string Hello
{
get { return _hello; }
set { _hello = value; RaisePropertyChanged(() => Hello); }
}
public ICommand Back
{
get
{
return new MvxCommand(() => ShowViewModel<FirstViewModel>());
}
}
}
I'm trying just two switch back and forth between them. the back step just does not work. Logging looks okay to me. Using the same VMs with an WPF project works just fine. So what the problem with androids activities?
Thanks in advance!
MH

MVVMCross: Binding Two Way doesn't update viewmodel

I'm trying to bind a property in a custom control in a Xamarin.Android project.
public class MyControl : RelativeLayout
{
public ObservableCollection<string> MyProperty { get; set; }
}
When MyProperty is updated in the ViewModel side, it updates fine the MyProperty in the View. However, nothing happens if I update the MyProperty in the View (I'd like to get the updated value in the ViewModel).
The binding:
public class MyControlMyPropertyTargetBinding : MvxAndroidTargetBinding
{
private bool _subscribed;
protected MyControl MyControl
{
get { return (MyControl)Target; }
}
public MyControlMyPropertyTargetBinding(MyControl target)
: base(target)
{
}
protected override void SetValueImpl(object target, object value)
{
var myControl = (MyControl)target;
myControl.MyProperty = (ObservableCollection<string>)value;
}
public override Type TargetType
{
get { return typeof(ObservableCollection<string>); }
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.TwoWay; }
}
public override void SubscribeToEvents()
{
base.SubscribeToEvents();
var myControl = MyControl;
if (myControl == null || myControl.MyProperty == null)
return;
myControl.MyProperty.CollectionChanged += MyPropertyOnCollectionChanged;
_subscribed = true;
}
private void MyPropertyOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
{
FireValueChanged(MyControl.MyProperty);
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (isDisposing)
{
var myControl = MyControl;
if (myControl != null && myControl.MyProperty!= null && _subscribed)
{
myControl.MyProperty.CollectionChanged -= MyPropertyOnCollectionChanged;
_subscribed = false;
}
}
}
}
Setup.cs:
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
registry.RegisterCustomBindingFactory<MyControl>("MyProperty", myProperty => new MyControlMyPropertyTargetBinding(myProperty));
}
protected override IList<Assembly> AndroidViewAssemblies
{
get
{
var assemblies = base.AndroidViewAssemblies;
assemblies.Add(typeof(MyControl).Assembly);
return assemblies;
}
}
Update: The same control binded on Windows Phone works two way perfectly. The control itself is into an external reference.
Does someone know what I missed?
Edit 1: I updated target binding with collection changed subscription but nothing's fired. The ObservableCollection is updated programatically by code, not by user input.

Categories

Resources