MediaPicker Not Working with Xamarin.Forms - xamarin

I am new to xamarin.in my project open gallery for select image for this i have used IMediaPicker interface.my code as below:
IMediaPicker mediaPicker;
ImageSource imageSource;
async void OnTapEntertainer(object sender, EventArgs args)
{
await TakePicture();
}
private async Task TakePicture()
{
mediaPicker = DependencyService.Get<IMediaPicker>();
imageSource = null;
var mediaFile = await mediaPicker.SelectPhotoAsync(new CameraMediaStorageOptions
{
DefaultCamera = CameraDevice.Front,
MaxPixelDimension = 400
});
imageSource = ImageSource.FromStream(() => mediaFile.Source);
Imgmn.Source = imageSource;
}
I got mediaPicker is null value in this code.Please help me to solve this issue.
I have added capability required for perform function.

To use MediaPicker item from XLabs please double check you have comleted all the items below:
Add a reference to XLabs.IoC to all of your projects (PCL, Android, iOS, etc.)
Initialize Resolver using the following code snippet:
var resolverContainer = new SimpleContainer();
resolverContainer.Register<IMediaPicker, MediaPicker>()
.Register<IDependencyContainer>(t => resolverContainer);
Resolver.SetResolver(resolverContainer.GetResolver());
Put this code before Xamarin.Forms.Forms.Init method for each platform in your solution.
Use var mediaPicker = Resolver.Resolve<IMediaPicker>(); to get the instance.

As per the comments following process resolves the issue:
Add Dependency Service class in .Droid library project to resolve IMediaPicker as given in example and use [assembly:Xamarin.Forms.Dependency(typeof(MediaPicker))] Reference

Related

How to update badge count while app is open?

I am using BottomNavigationBar plugin and it works fine.
My problem is I want to update badge count when notification is received while app is in running mode(i.e. open). I am using Setting Plugin for Xamarin and store count in that. On app initialize it display counts properly. But when my app is open I am changing value of Setting and immediately change the value of badge. How's that can be possible?
Where is several ways to do this.
First, if you are using Xamarin forms then you can use MessagingCenter. It is cross platform Event Bus implementation.
I used Xamarin.Form. Example for sending message
public MainPage()
{
InitializeComponent();
var count = 0;
_button.Clicked += (sender, args) =>
{
MessagingCenter.Send<MainPage, int>(this, "MyMessage", count++);
};
}
Example of reciever
public App()
{
InitializeComponent();
var mp = new MainPage();
MainPage = new MainPage();
MessagingCenter.Subscribe<MainPage, int>(this, "MyMessage", (sender, arg) => {
MainPage.DisplayAlert("MyMessage", $"Hit Count: {arg}", "ok");
});
}
There is more info and examples if you check Link
Second, add event to your settings class, and invoke it in your setter

XamarinForms FFImageLoading CachedImage issue

I'm getting a .PNG image file from an API like so
public static async Task<CachedImage> GetImage(string UserID)
{
var URL = "assumeThisUrlPointsToServer"
HttpClient client = new HttpClient();
Stream stream = await client.GetStreamAsync(URL);
return new CachedImage { Source = ImageSource.FromStream(() => stream) };
}
and I am getting a file back and I am displaying it like so
<ffimageloading:CachedImage HeightRequest="52" Margin="13,0,16,0" Source="{Binding SourceOfReturnedCachedImage}"/>
Unfortunately, this is not working (blank). How do I get it to work?
Additional details : if I change it to an Image instead of CachedImage, then it works.
Now the funny thing is that if i specify a URI instead of downloading a file, like so,
return new CachedImage { Source = ImageSource.FromUri('http://www.website.com/image.png')};
Then it (CachedImage) works!
Stream is disposed after every image load, you must modify your code to:
public static async Task<CachedImage> GetImage(string UserID)
{
var URL = "assumeThisUrlPointsToServer"
HttpClient client = new HttpClient();
return new CachedImage { Source = ImageSource.FromStream(() => {
return await client.GetStreamAsync(URL);
})};
}
So xamarin provides a simple way to view images, you can just give the url of the image as the source of image/cachedimage so
<ffimageloading:CachedImage HeightRequest="52" Margin="13,0,16,0" Source="{Binding ImageURL}"/>
Where ImageURL is the URL I was downloading the image from

How to show all images from a folder in Xamarin Cross-Platform app?

I am using VS 2017 to create a cross platform (UWP, Android, iOS) Xamarin app. I am trying to show all images from a folder on device as thumbnails (similar to gallery app, sample screenshot attached).
I have looked into WrapLayout sample code provided on Xamarin website (Link), but it's loading all images from internet using JSON
protected override async void OnAppearing()
{
base.OnAppearing();
var images = await GetImageListAsync();
foreach (var photo in images.Photos)
{
var image = new Image
{
Source = ImageSource.FromUri(new Uri(photo + string.Format("?width={0}&height={0}&mode=max", Device.OnPlatform(240, 240, 120))))
};
wrapLayout.Children.Add(image);
}
}
async Task<ImageList> GetImageListAsync()
{
var requestUri = "https://docs.xamarin.com/demo/stock.json";
using (var client = new HttpClient())
{
var result = await client.GetStringAsync(requestUri);
return JsonConvert.DeserializeObject<ImageList>(result);
}
}
I have also looked into Xamarin Media Plugin (Link), but it shows only one image at a time. Sample code -
await CrossMedia.Current.Initialize();
var file = await CrossMedia.Current.PickPhotoAsync();
if (file == null)
return;
MainImage.Source = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
file.Dispose();
return stream;
});
But I am unable to find a way to implement these two (or any other methods) in such a way that I can create my own gallery section in my app.
You need to create an Activity in your specific platform. This activity will be launched as an intent throught your PCL project using, for instance, Dependency Services.
In this custom Activity you should have a GridView which fills its source from the current directory if the file fits your restrictions, such a specific extension, size, etc.
Finally, to get the selected image you just send the image path or whatever you need to the PCL project with DependencyService.

Set Image.Source to file in external storage in Xamarin.Forms

I have a picture of item in external storage (that was saved by intent in my app). I want to display this picture in Image view in my shared project.
Image.Source takes object of ImageSource type. I tried ImageSource.FromFile, ImageSource.FromStream and even ImageSource.FromUri. The result is always that image is not displayed (no error or exception). I validated that the path to file is correct by first opening it with File.Open one line above.
What is the correct way of displaying pictures from normal storage, not from assets/resources/etc?
This code does not work:
var path = "/storage/emulated/0/Pictures/6afbd8c6-bb1e-49d3-838c-0fa809e97cf1.jpg" //in real app the path is taken from DB
var image = new Image() {Aspect = Aspect.AspectFit, WidthRequest = 200, HeightRequest = 200};
image.Source = ImageSource.FromFile(path);
Your Xamarin Forms PCL don't know what its a URI from Android beacuse its platform specific, so:
ImageSource.FromFile(path);
won't work.
In that case you are handling platform specific features, that is loading an image from Android.
I suggest this approach:
Create an interface on Xamarin Forms PCL like:
public interface IPhoto
{
Task<Stream> GetPhoto ();
}
Then in Android you implement that interface and register the implementation in DependencyService:
[assembly: Xamarin.Forms.Dependency(typeof(PhotoImplementation))]
namespace xpto
{
public class PhotoImplementation : Java.Lang.Object, IPhoto
{
public async Task<Stream> GetPhoto()
{
// Open the photo and put it in a Stream to return
var memoryStream = new MemoryStream();
using (var source = System.IO.File.OpenRead(path))
{
await source.CopyToAsync(memoryStream);
}
return memoryStream;
}
}
}
In the Xamarin Forms PCL code get the image:
var image = ImageSource.FromStream ( () => await DependencyService.Get<IPhoto>().GetPhoto());
For more detail you can consult this.
NOTE1: This will work on iOS if you implement the interface IPhoto too.
NOTE2: There exist a helpful library for this kind of features from Xamarin-Forms-Labs called Camera.
UPDATE (Shared Project solution)
As requested in the comments, to use this in a Shared Project instead of PCL we could do this.
1 - Place the IPhotoInterface in the Shared Project.
2 - Implement the interface in Android/iOS project:
public class PhotoImplementation : IPhoto
{
public async Task<Stream> GetPhoto()
{
// Open the photo and put it in a Stream to return.
}
}
3 - Use it in the Shared Project:
IPhoto iPhotoImplementation;
#if __ANDROID__
iPhotoImplementation = new shared_native.Droid.GetPicture();
#elif __IOS__
iPhotoImplementation = new shared_native.iOS.GetPicture();
#endif
var image = ImageSource.FromStream ( () => await iPhotoImplementation.GetPhoto());
NOTE: shared_native is the namespace of my solution and Droid/iOS are the projects for Android and iOS.

Geofence is not being triggered in the background in windows phone 8.1

I'm trying to implement geofencing in Windows phone 8.1. First I wanted to create a sample Project to understand how it Works, but i couldnt make it works. What I'm trying to achieve is basically, I'll set the coordinates and close the app by pressing back button and it will trigger a toast notification when the phone is in the area of interest.
I've created a blank Windows phone(silverlight) 8.1 Project(geofence_test_01) and added a Windows RT Component Project(BackgroundTask) into the same solution. Added a reference for BackgroundTask in the geofence_test_01 Project.
ID_CAP_LOCATION is enabled in the app manifest.
MainPage.xaml has only one button to start geofencing.
<Button Name="btnStart" Content="Start" Click="btnStart_Click"/>
In btnSave_Click, I call a method which creates the geofence and registers the background task.
private void btnStart_Click(object sender, RoutedEventArgs e)
{
Init_BackgroundGeofence();
registerBackgroundTask();
}
private async Task Init_BackgroundGeofence()
{
//----------------- Crating Geofence ---------------
var geofenceMonitor = GeofenceMonitor.Current;
var geoId = "building9";
var positionBuilding9 = new BasicGeoposition()
{
Latitude = 47.6397,
Longitude = -122.1289
};
var geofence = new Geofence(geoId, new Geocircle(positionBuilding9, 100),
MonitoredGeofenceStates.Entered | MonitoredGeofenceStates.Exited,
false, TimeSpan.FromSeconds(10));
geofenceMonitor.Geofences.Add(geofence);
}
private async Task registerBackgroundTask()
{
//----------------- Register Background Task ---------------
var backgroundAccessStatus =
await BackgroundExecutionManager.RequestAccessAsync();
var geofenceTaskBuilder = new BackgroundTaskBuilder
{
Name = "GeofenceBackgroundTask",
TaskEntryPoint = "BackgroundTask.GeofenceBackgroundTask"
};
var trigger = new LocationTrigger(LocationTriggerType.Geofence);
geofenceTaskBuilder.SetTrigger(trigger);
var geofenceTask = geofenceTaskBuilder.Register();
}
And finally, in BackgroundTask, I've the following code:
namespace BackgroundTask
{
public sealed class GeofenceBackGroundTask : IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance)
{
var geofenceMonitor = GeofenceMonitor.Current;
var geoReports = geofenceMonitor.ReadReports();
var geoId = "building9";
foreach (var geofenceStateChangeReport in geoReports)
{
var id = geofenceStateChangeReport.Geofence.Id;
var newState = geofenceStateChangeReport.NewState;
if (id == geoId && newState == GeofenceState.Entered)
{
//------ Call NotifyUser method when Entered -------
notifyUser();
}
}
}
private void notifyUser()
{
var toastTemplate = ToastTemplateType.ToastText02;
var toastXML = ToastNotificationManager.GetTemplateContent(toastTemplate);
var textElements = toastXML.GetElementsByTagName("text");
textElements[0].AppendChild(toastXML.CreateTextNode("You are in!"));
var toast = new ToastNotification(toastXML);
ToastNotificationManager.CreateToastNotifier().Show(toast);
}
}
}
I get no error when building and deploying this in the emulator. I set a breakpoint in the backgroundTask but I've not seen that part of code is called yet. It never hits the breakpoint. I test it by using Additional Tools of the emulator, in Location tab, by clicking somewhere in my geofence area on the map, waiting for a while, but it never hits the breakpoint. Hope somebody can tell me what i am missing here...
I've checked these following links to build this application:
http://www.jayway.com/2014/04/22/windows-phone-8-1-for-developers-geolocation-and-geofencing/
Geofence in the Background Windows Phone 8.1 (WinRT)
Toast notification & Geofence Windows Phone 8.1
http://java.dzone.com/articles/geofencing-windows-phone-81
Thanks
You can download the project here:
https://drive.google.com/file/d/0B8Q_biJCWl4-QndYczR0cjNhNlE/view?usp=sharing
---- Some clues
Thanks to Romasz, I've checked the Lifecycle events and i see "no background tasks" even after registerBackgroundTask() is executed.... Apparently there is something wrong/missing in registerBackgroundTask() method.
I've tried to build my sample (it was easier for me to build a new one) basing on your code and it seems to be working. You can take a look at it at my GitHub.
There are couple of things that may have gone wrong in your case:
remember to add capabilities in WMAppManifest file (IS_CAP_LOCATION) and Package.appxmanifest (Location)
check the names (of namespaces, classes and so on) in BackgroundTask
check if your BackgroundTask project is Windows Runtime Componenet and is added to your main project as a reference
I know you have done some of this things already, but take a look at my sample, try to run it and maybe try to build your own from the very beginning.
Did you add your background task in the Package.appxmanifest under Declarations with the correct supported task types (Namely Location)?

Resources