I'm using camera2basic, when I change flash parameter on runtime it not working and load first parameter when app loading.
example : when I set auto-flash in hardcode it worked when I change it to Off in my app it not work and flash parameter is auto-flash yet.
I want to set flash parameter in application not hardcode. How can i do it?
**//Camera2BasicFragment.cs**
public void CaptureStillPicture()
{
try
{
var activity = Activity;
if (null == activity || null == mCameraDevice)
{
return;
}
// This is the CaptureRequest.Builder that we use to take a picture.
if (stillCaptureBuilder == null)
stillCaptureBuilder = mCameraDevice.CreateCaptureRequest(CameraTemplate.StillCapture);
stillCaptureBuilder.AddTarget(mImageReader.Surface);
SetFlash(stillCaptureBuilder);
// Orientation
int rotation = (int)activity.WindowManager.DefaultDisplay.Rotation;
stillCaptureBuilder.Set(CaptureRequest.JpegOrientation, GetOrientation(rotation));
mCaptureSession.StopRepeating();
mCaptureSession.Capture(stillCaptureBuilder.Build(), new CameraCaptureStillPictureSessionCallback(this), null);
}
catch (CameraAccessException e)
{
e.PrintStackTrace();
}
}
ControlAEMode AeFlashMode = ControlAEMode.Off;
public void SetFlash(CaptureRequest.Builder requestBuilder)
{
if (mFlashSupported)
{
requestBuilder.Set(CaptureRequest.ControlAeMode, (int)AeFlashMode);
}
}
-------------------------------
**//CameraCaptureSessionCallback.cs**
public override void OnConfigured(CameraCaptureSession session)
{
// The camera is already closed
if (null == owner.mCameraDevice)
{
return;
}
// When the session is ready, we start displaying the preview.
owner.mCaptureSession = session;
try
{
// Auto focus should be continuous for camera preview.
owner.SetFocus(owner.mPreviewRequestBuilder);
// Flash is automatically enabled when necessary.
owner.SetFlash(owner.mPreviewRequestBuilder);
// Finally, we start displaying the camera preview.
owner.mPreviewRequest = owner.mPreviewRequestBuilder.Build();
owner.mCaptureSession.SetRepeatingRequest(owner.mPreviewRequest,
owner.mCaptureCallback, owner.mBackgroundHandler);
}
catch (CameraAccessException e)
{
e.PrintStackTrace();
}
}
You can add following code to your CameraCaptureSessionCallback.cs
public void ISFlashOpenOrClose(bool isTorchOn)
{
owner.mCaptureSession = this.session;
if (isTorchOn)
{
owner.mPreviewRequestBuilder.Set(CaptureRequest.FlashMode, (int)ControlAEMode.On);
// owner.mPreviewRequestBuilder.Set(CaptureRequest.FlashMode, (int)FlashMode.Off);
// mPreviewSession.SetRepeatingRequest(mPreviewBuilder.build(), null, null);
owner.mPreviewRequest = owner.mPreviewRequestBuilder.Build();
owner.mCaptureSession.SetRepeatingRequest(owner.mPreviewRequest,
owner.mCaptureCallback, owner.mBackgroundHandler);
// isTorchOn = false;
}
else
{
owner.mPreviewRequestBuilder.Set(CaptureRequest.ControlAeMode, (int)ControlAEMode.Off);
owner.mPreviewRequest = owner.mPreviewRequestBuilder.Build();
owner.mCaptureSession.SetRepeatingRequest(owner.mPreviewRequest,
owner.mCaptureCallback, owner.mBackgroundHandler);
}
}
Here is all of code about CameraCaptureSessionCallback.cs
public class CameraCaptureSessionCallback : CameraCaptureSession.StateCallback
{
private readonly Camera2BasicFragment owner;
CameraCaptureSession session;
public CameraCaptureSessionCallback(Camera2BasicFragment owner)
{
if (owner == null)
throw new System.ArgumentNullException("owner");
this.owner = owner;
}
public override void OnConfigureFailed(CameraCaptureSession session)
{
owner.ShowToast("Failed");
}
private bool isTorchOn;
public override void OnConfigured(CameraCaptureSession session)
{
// The camera is already closed
if (null == owner.mCameraDevice)
{
return;
}
this.session = session;
// When the session is ready, we start displaying the preview.
owner.mCaptureSession = session;
try
{
// Auto focus should be continuous for camera preview.
owner.mPreviewRequestBuilder.Set(CaptureRequest.ControlAfMode, (int)ControlAFMode.ContinuousPicture);
// Flash is automatically enabled when necessary.
owner.SetAutoFlash(owner.mPreviewRequestBuilder);
// Flash is automatically enabled when necessary.
// owner.SetFlash(owner.mPreviewRequestBuilder);
// Finally, we start displaying the camera preview.
owner.mPreviewRequest = owner.mPreviewRequestBuilder.Build();
owner.mCaptureSession.SetRepeatingRequest(owner.mPreviewRequest,
owner.mCaptureCallback, owner.mBackgroundHandler);
}
catch (CameraAccessException e)
{
e.PrintStackTrace();
}
}
public void ISFlashOpenOrClose(bool isTorchOn)
{
owner.mCaptureSession = this.session;
if (isTorchOn)
{
owner.mPreviewRequestBuilder.Set(CaptureRequest.FlashMode, (int)ControlAEMode.On);
// owner.mPreviewRequestBuilder.Set(CaptureRequest.FlashMode, (int)FlashMode.Off);
// mPreviewSession.SetRepeatingRequest(mPreviewBuilder.build(), null, null);
owner.mPreviewRequest = owner.mPreviewRequestBuilder.Build();
owner.mCaptureSession.SetRepeatingRequest(owner.mPreviewRequest,
owner.mCaptureCallback, owner.mBackgroundHandler);
// isTorchOn = false;
}
else
{
owner.mPreviewRequestBuilder.Set(CaptureRequest.ControlAeMode, (int)ControlAEMode.Off);
owner.mPreviewRequest = owner.mPreviewRequestBuilder.Build();
owner.mCaptureSession.SetRepeatingRequest(owner.mPreviewRequest,
owner.mCaptureCallback, owner.mBackgroundHandler);
}
}
}
}
You can change it by ISFlashOpenOrClose method at runtime.
Related
In my xamarin.forms app, I created a custom camera by using Camera view and custom renders. Everything works fine. In android after the photo capture I can check whether the taken photo contains a face or not.It is done by using Camera.IFaceDetectionListener. My question is how can I achieve this in iOS? I know there is vision API. But I don't want the live face tracking. I just simply want to check whether the taken photo contains face. Any help is appreciated.
My iOS CameraPreview
public class UICameraPreview : UIView, IAVCaptureMetadataOutputObjectsDelegate
{
AVCaptureVideoPreviewLayer previewLayer;
public AVCaptureDevice[] videoDevices;
CameraOptions cameraOptions;
public AVCaptureStillImageOutput stillImageOutput;
public AVCaptureDeviceInput captureDeviceInput;
public AVCaptureDevice device;
public event EventHandler<EventArgs> Tapped;
public AVCaptureSession CaptureSession { get; set; }
public bool IsPreviewing { get; set; }
public AVCaptureStillImageOutput CaptureOutput { get; set; }
public UICameraPreview(CameraOptions options)
{
cameraOptions = options;
IsPreviewing = false;
Initialize();
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
if (previewLayer != null)
previewLayer.Frame = Bounds;
}
public override void TouchesBegan(NSSet touches, UIEvent evt)
{
base.TouchesBegan(touches, evt);
OnTapped();
}
protected virtual void OnTapped()
{
var eventHandler = Tapped;
if (eventHandler != null)
{
eventHandler(this, new EventArgs());
}
}
void Initialize()
{
CaptureSession = new AVCaptureSession();
previewLayer = new AVCaptureVideoPreviewLayer(CaptureSession)
{
Frame = Bounds,
VideoGravity = AVLayerVideoGravity.ResizeAspectFill
};
videoDevices = AVCaptureDevice.DevicesWithMediaType(AVMediaType.Video);
var cameraPosition = (cameraOptions == CameraOptions.Front) ? AVCaptureDevicePosition.Front : AVCaptureDevicePosition.Back;
device = videoDevices.FirstOrDefault(d => d.Position == cameraPosition);
if (device == null)
{
return;
}
NSError error;
captureDeviceInput = new AVCaptureDeviceInput(device, out error);
CaptureSession.AddInput(captureDeviceInput);
var dictionary = new NSMutableDictionary();
dictionary[AVVideo.CodecKey] = new NSNumber((int)AVVideoCodec.JPEG);
stillImageOutput = new AVCaptureStillImageOutput()
{
OutputSettings = new NSDictionary()
};
CaptureSession.AddOutput(stillImageOutput);
Layer.AddSublayer(previewLayer);
CaptureSession.StartRunning();
IsPreviewing = true;
}
// Photo Capturing
public async Task CapturePhoto()
{
try
{
var videoConnection = stillImageOutput.ConnectionFromMediaType(AVMediaType.Video);
var sampleBuffer = await stillImageOutput.CaptureStillImageTaskAsync(videoConnection);
var jpegData = AVCaptureStillImageOutput.JpegStillToNSData(sampleBuffer);
var photo = new UIImage(jpegData);
var rotatedPhoto = RotateImage(photo, 180f);
var img = rotatedPhoto;
CALayer layer = new CALayer
{
ContentsScale = 1.0f,
Frame = Bounds,
Contents = rotatedPhoto.CGImage //Contents = photo.CGImage,
};
CaptureSession.StopRunning();
photo.SaveToPhotosAlbum((image, error) =>
{
if (!string.IsNullOrEmpty(error?.LocalizedDescription))
{
Console.Error.WriteLine($"\t\t\tError: {error.LocalizedDescription}");
}
});
}
catch (Exception ex)
{
}
//MainPage.UpdateSource(UIImageFromLayer(layer).AsJPEG().AsStream());
//MainPage.UpdateImage(UIImageFromLayer(layer).AsJPEG().AsStream());
}
}
My CameraPreviewRenderer
public class CameraPreviewRenderer : ViewRenderer<CameraPreview, UICameraPreview>, IAVCaptureMetadataOutputObjectsDelegate
{
UICameraPreview uiCameraPreview;
AVCaptureSession captureSession;
AVCaptureDeviceInput captureDeviceInput;
AVCaptureStillImageOutput stillImageOutput;
protected override void OnElementChanged(ElementChangedEventArgs<CameraPreview> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
// Unsubscribe
uiCameraPreview.Tapped -= OnCameraPreviewTapped;
}
if (e.NewElement != null)
{
if (Control == null)
{
uiCameraPreview = new UICameraPreview(e.NewElement.Camera);
SetNativeControl(uiCameraPreview);
MessagingCenter.Subscribe<Camera_Popup>(this, "CaptureClick", async (sender) =>
{
try
{
// Using messeging center to take photo when clicking button from shared code
var data = new AVCaptureMetadataOutputObjectsDelegate();
await uiCameraPreview.CapturePhoto();
}
catch (Exception ex)
{
return;
}
});
}
MessagingCenter.Subscribe<Camera_Popup>(this, "RetryClick", (sender) =>
{
Device.BeginInvokeOnMainThread(() =>
{
uiCameraPreview.CaptureSession.StartRunning();
uiCameraPreview.IsPreviewing = true;
});
});
MessagingCenter.Subscribe<Camera_Popup>(this, "FlipClick", (sender) =>
{
try
{
var devicePosition = uiCameraPreview.captureDeviceInput.Device.Position;
if (devicePosition == AVCaptureDevicePosition.Front)
{
devicePosition = AVCaptureDevicePosition.Back;
}
else
{
devicePosition = AVCaptureDevicePosition.Front;
}
uiCameraPreview.device = uiCameraPreview.videoDevices.FirstOrDefault(d => d.Position == devicePosition);
uiCameraPreview.CaptureSession.BeginConfiguration();
uiCameraPreview.CaptureSession.RemoveInput(uiCameraPreview.captureDeviceInput);
uiCameraPreview.captureDeviceInput = AVCaptureDeviceInput.FromDevice(uiCameraPreview.device);
uiCameraPreview.CaptureSession.AddInput(uiCameraPreview.captureDeviceInput);
uiCameraPreview.CaptureSession.CommitConfiguration();
}
catch (Exception ex)
{
var abc = ex.InnerException.Message;
}
});
uiCameraPreview.Tapped += OnCameraPreviewTapped;
}
}
void OnCameraPreviewTapped(object sender, EventArgs e)
{
if (uiCameraPreview.IsPreviewing)
{
uiCameraPreview.CaptureSession.StopRunning();
uiCameraPreview.IsPreviewing = false;
}
else
{
uiCameraPreview.CaptureSession.StartRunning();
uiCameraPreview.IsPreviewing = true;
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Control.CaptureSession.Dispose();
Control.Dispose();
}
base.Dispose(disposing);
}
}
The CoreImage framework has CIDetector that provides image detectors for faces, QR codes, text, .... in which you pass in an image and you get a specific "feature set" back.
Example from Xamarin docs:
var imageFile = "photoFace2.jpg";
var image = new UIImage(imageFile);
var context = new CIContext ();
var detector = CIDetector.CreateFaceDetector (context, true);
var ciImage = CIImage.FromCGImage (image.CGImage);
var features = detector.GetFeatures (ciImage);
Console.WriteLine ("Found " + features.Length + " faces");
re: https://learn.microsoft.com/en-us/dotnet/api/CoreImage.CIDetector?view=xamarin-ios-sdk-12
How can I implement a video recorder inside an application using xamarin forms?
You can use Xamarin.Plugin.Media. If it is not flexible enough for you, then you need to implement the video recorder using the native APIs. In which case you probably shouldn't be doing Xamarin.Forms at all, but if you insist that is the way.
Do you want to achieve the result like following GIF(Over 2M, SO cannot allow upload it )?
https://imgur.com/a/kpMl2ed
I achieve it in android by custom rendere. Here is code.
First of all, we should MediaRecorder to record the video.
public void startRecord(SurfaceView surfaceView)
{
Device.BeginInvokeOnMainThread(() => {
string path = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/test.mp4";
recorder = new MediaRecorder();
//If you want to rotate the video screen, you can use following code
//Camera camera = Camera.Open();
//Camera.Parameters parameters = camera.GetParameters();
//parameters.SetPreviewSize(640, 480);
//parameters.SetPictureSize(640, 480);
//camera.SetParameters(parameters);
//camera.SetDisplayOrientation(90);
//camera.Unlock();
//recorder.SetCamera(camera);
recorder.SetVideoSource(VideoSource.Camera);
recorder.SetAudioSource(AudioSource.Mic);
recorder.SetOutputFormat(OutputFormat.Default);
recorder.SetVideoEncoder(VideoEncoder.Default);
recorder.SetAudioEncoder(AudioEncoder.Default);
recorder.SetOutputFile(path);
recorder.SetPreviewDisplay(surfaceView.Holder.Surface);
recorder.Prepare();
recorder.Start();
});
}
If you want to achieve the record the video inside the application, you should use custom renderer to view. Use SurfaceView to see the camera view.First of all. please create a CameraPreview
public sealed class CameraPreview : ViewGroup, ISurfaceHolderCallback
{
public SurfaceView surfaceView;
ISurfaceHolder holder;
Camera.Size previewSize;
IList<Camera.Size> supportedPreviewSizes;
Camera camera;
IWindowManager windowManager;
MediaRecorder recorder;
public bool IsPreviewing { get; set; }
public Camera Preview {
get { return camera; }
set {
camera = value;
if (camera != null) {
supportedPreviewSizes = Preview.GetParameters().SupportedPreviewSizes;
RequestLayout();
}
}
}
public CameraPreview (Context context)
: base (context)
{
surfaceView = new SurfaceView (context);
AddView (surfaceView);
windowManager = Context.GetSystemService (Context.WindowService).JavaCast<IWindowManager>();
IsPreviewing = false;
holder = surfaceView.Holder;
holder.AddCallback (this);
MessagingCenter.Subscribe<string>("111", "Hi", (expense) =>
{
startRecord(surfaceView);
});
MessagingCenter.Subscribe<string>("1112", "Hi2", (expense) =>
{
stopRecord(surfaceView);
});
}
private void stopRecord(SurfaceView surfaceView)
{
recorder.Stop();
recorder.Release();
}
public void startRecord(SurfaceView surfaceView)
{
Device.BeginInvokeOnMainThread(() => {
string path = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/test.mp4";
recorder = new MediaRecorder();
//If you want to rotate the video screen, you can use following code
//Camera camera = Camera.Open();
//Camera.Parameters parameters = camera.GetParameters();
//parameters.SetPreviewSize(640, 480);
//parameters.SetPictureSize(640, 480);
//camera.SetParameters(parameters);
//camera.SetDisplayOrientation(90);
//camera.Unlock();
//recorder.SetCamera(camera);
recorder.SetVideoSource(VideoSource.Camera);
recorder.SetAudioSource(AudioSource.Mic);
recorder.SetOutputFormat(OutputFormat.Default);
recorder.SetVideoEncoder(VideoEncoder.Default);
recorder.SetAudioEncoder(AudioEncoder.Default);
recorder.SetOutputFile(path);
recorder.SetPreviewDisplay(surfaceView.Holder.Surface);
recorder.Prepare();
recorder.Start();
});
}
protected override void OnMeasure (int widthMeasureSpec, int heightMeasureSpec)
{
int width = ResolveSize (SuggestedMinimumWidth, widthMeasureSpec);
int height = ResolveSize (SuggestedMinimumHeight, heightMeasureSpec);
SetMeasuredDimension (width, height);
if (supportedPreviewSizes != null) {
previewSize = GetOptimalPreviewSize (supportedPreviewSizes, width, height);
}
}
protected override void OnLayout (bool changed, int l, int t, int r, int b)
{
var msw = MeasureSpec.MakeMeasureSpec (r - l, MeasureSpecMode.Exactly);
var msh = MeasureSpec.MakeMeasureSpec (b - t, MeasureSpecMode.Exactly);
surfaceView.Measure (msw, msh);
surfaceView.Layout (0, 0, r - l, b - t);
}
public void SurfaceCreated (ISurfaceHolder holder)
{
try {
if (Preview != null) {
Preview.SetPreviewDisplay (holder);
}
} catch (Exception ex) {
System.Diagnostics.Debug.WriteLine (#" ERROR: ", ex.Message);
}
}
public void SurfaceDestroyed (ISurfaceHolder holder)
{
if (Preview != null) {
Preview.StopPreview ();
}
}
public void SurfaceChanged (ISurfaceHolder holder, Android.Graphics.Format format, int width, int height)
{
var parameters = Preview.GetParameters ();
parameters.SetPreviewSize (previewSize.Width, previewSize.Height);
RequestLayout ();
//If you want to rotate the video screen, you can use following code
//switch (windowManager.DefaultDisplay.Rotation) {
//case SurfaceOrientation.Rotation0:
// camera.SetDisplayOrientation (90);
// break;
//case SurfaceOrientation.Rotation90:
// camera.SetDisplayOrientation (0);
// break;
//case SurfaceOrientation.Rotation270:
// camera.SetDisplayOrientation (180);
// break;
//}
Preview.SetParameters (parameters);
Preview.StartPreview ();
IsPreviewing = true;
}
Camera.Size GetOptimalPreviewSize (IList<Camera.Size> sizes, int w, int h)
{
const double AspectTolerance = 0.1;
double targetRatio = (double)w / h;
if (sizes == null) {
return null;
}
Camera.Size optimalSize = null;
double minDiff = double.MaxValue;
int targetHeight = h;
foreach (Camera.Size size in sizes) {
double ratio = (double)size.Width / size.Height;
if (Math.Abs (ratio - targetRatio) > AspectTolerance)
continue;
if (Math.Abs (size.Height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.Abs (size.Height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = double.MaxValue;
foreach (Camera.Size size in sizes) {
if (Math.Abs (size.Height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.Abs (size.Height - targetHeight);
}
}
}
return optimalSize;
}
}
Then, Here is custom renderer.
[assembly: ExportRenderer(typeof(CustomRenderer.CameraPreview), typeof(CameraPreviewRenderer))]
namespace CustomRenderer.Droid
{
public class CameraPreviewRenderer : ViewRenderer
{
CameraPreview cameraPreview;
public CameraPreviewRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<CustomRenderer.CameraPreview> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
// Unsubscribe
cameraPreview.Click -= OnCameraPreviewClicked;
}
if (e.NewElement != null)
{
if (Control == null)
{
cameraPreview = new CameraPreview(Context);
SetNativeControl(cameraPreview);
}
Control.Preview = Camera.Open((int)e.NewElement.Camera);
// Subscribe
cameraPreview.Click += OnCameraPreviewClicked;
}
}
void OnCameraPreviewClicked(object sender, EventArgs e)
{
if (cameraPreview.IsPreviewing)
{
cameraPreview.Preview.StopPreview();
cameraPreview.IsPreviewing = false;
}
else
{
cameraPreview.Preview.StartPreview();
cameraPreview.IsPreviewing = true;
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Control.Preview.Release();
}
base.Dispose(disposing);
}
}
}
If you want to know how to achieve Camera Preview in the IOS or UWP, you can refer to this link.
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/view
Here is code in github.
https://github.com/851265601/FormsRecordVideoInside
Above way to achieve it, it a bit complexed. I suggest you to use the Xam.Plugin.Media to achieve it. Here is running GIF. it cannot see the video preview in the application, but you do not need to use custom renderer to achieve it just serveral lines code.
private async void PlayStopButtonText_Clicked(object sender, EventArgs e)
{
// throw new NotImplementedException();
var file = await CrossMedia.Current.TakeVideoAsync(new StoreVideoOptions
{
SaveToAlbum = true,Directory = "Sample"
});
//Get the public album path
if (file == null)
return;
await DisplayAlert("File Location", file.AlbumPath, "OK");
}
In the android, add the following permission.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
Here is running GIF(Over 2M, SO cannot allow upload it ).
https://imgur.com/a/9WE4szZ
For retrieve location i have used GoogleAPIClient with FusedLocationProvider API.
These functions are in onCreate() method.
createLocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
gpsChecker();
Full Code
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
public void gpsChecker() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(
AddVisitActivity.this, 1000);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
break;
}
}
});
}
For run time permissions i did this.
protected void startLocationUpdates() {
if (ActivityCompat.shouldShowRequestPermissionRationale
(AddVisitActivity.this, android.Manifest.permission.ACCESS_FINE_LOCATION)) {
Snackbar.make(findViewById(android.R.id.content),
"Please Grant Permissions",
Snackbar.LENGTH_INDEFINITE).setAction("ENABLE",
new View.OnClickListener() {
#Override
public void onClick(View v) {
if (ActivityCompat.checkSelfPermission(AddVisitActivity.this, android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(AddVisitActivity.this,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_CODE_LOCATION);
} else {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, AddVisitActivity.this);
Log.d(TAG, "Location update started ...: ");
}
}
}).show();
} else {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_CODE_LOCATION);
} else {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
Log.d(TAG, "Location update started ...: ");
}
}
}
For checking if the GPS enabled or not in setting screen using gpsChecker() with request code 1000 and in onActivityResult() i have done this.
if (requestCode == 1000) {
switch (resultCode) {
case Activity.RESULT_OK:
Log.i(TAG, "User agreed to make required location settings changes.");
startLocationUpdates();
break;
case Activity.RESULT_CANCELED:
Log.i(TAG, "User chose not to make required location settings changes.");
finish();
break;
}
}
While i execute this code in some devices its working and in some device the location request automatically set to Device Only or Battery Saving though i have set mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
Note : Mi Note 4, Vivo V9 Pro, Mi Note 5 Pro and some other device getting the issue
So what should i need to change in my code so will it work proper with the High Accuracy?
Finally solved by changing
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
to
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
and change
private static final long INTERVAL = 1000 * 60 * 60;
private static final long FASTEST_INTERVAL = 1000 * 5;
interval time to 30 minutes and fastest interval to 5 seconds means once get location in 5 seconds after then new location will be get in 30 minutes.
Try this solutin with GPS Provider and make sure that your GPS service is ON.
static final int LOCATION_INTERVAL = 1000;
static final float LOCATION_DISTANCE = 10f;
//put this in onCreate();
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
mprovider = locationManager.getBestProvider(criteria, false);
if (mprovider != null && !mprovider.equals("")) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
Location location = locationManager.getLastKnownLocation(mprovider);
locationManager.requestLocationUpdates(mprovider, LOCATION_INTERVAL, LOCATION_DISTANCE, this);
if (location != null)
onLocationChanged(location);
else
Toast.makeText(getBaseContext(), "No Location Provider Found Check Your Code", Toast.LENGTH_SHORT).show();
}
//put this LocationListener after onCreate();
public LocationListener mLocationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
if (location != null) {
Log.e(String.format("%f, %f", location.getLatitude(), location.getLongitude()), "");
Log.e("Location available", "Location available");
locationManager.removeUpdates(mLocationListener);
} else {
Log.e("Location is null", "Location is null");
}
current_latitude = location.getLatitude();
current_longitude = location.getLongitude();
/* LatLng latLng = new LatLng(current_latitude, current_longitude);
points.add(latLng);
redrawLine();*/
Log.e("current_latitude", String.valueOf(current_latitude));
Log.e("current_longitude", String.valueOf(current_longitude));
if (location.hasSpeed()) {
//progressBarCircularIndeterminate.setVisibility(View.GONE);
String speed = String.format(Locale.ENGLISH, "%.0f", location.getSpeed() * 3.6) + "km/h";
SpannableString s = new SpannableString(speed);
s.setSpan(new RelativeSizeSpan(0.25f), s.length() - 4, s.length(), 0);
txt_current_speed.setText(s);
}
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
};
I am using web service for showing image in imageview. But web service image show in SYSTEM.BYTE[] Format. So how to Convert or display the image in imageview in xamarin android application??
Webservice.asmx:
[WebMethod(MessageName = "BindHospName", Description = "Bind Hospital Name Control")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
[System.Xml.Serialization.XmlInclude(typeof(GetHospName))]
public string BindHosp(decimal SpecID)
{
JavaScriptSerializer objJss = new JavaScriptSerializer();
List<GetHospName> HospName = new List<GetHospName>();
try
{
ConnectionString();
cmd = new SqlCommand("select b.HID,b.HospName,b.Logo from HospitalRegBasic b inner join HospitalRegClinical c on b.HID=c.HID " +
"where b.EmailActivationCode <> '' and b.EmailActivationStatus = 1 and b.Status = 1 and c.SPEC_ID = #SpecID ", conn);
cmd.Parameters.AddWithValue("#SpecID", SpecID);
dr = cmd.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
var getHosp = new GetHospName
{
HospID = dr["HID"].ToString(),
HospName = dr["HospName"].ToString(),
HospLogo = dr["Logo"].ToString()
};
HospName.Add(getHosp);
}
}
dr.Close();
cmd.Dispose();
conn.Close();
}
catch (Exception)
{
throw;
}
return objJss.Serialize(HospName);
}
Class.cs:
namespace HSAPP
{
class ContListViewHospNameClass : BaseAdapter<GetHospNames>
{
List<GetHospNames> objList;
Activity objActivity;
public ContListViewHospNameClass (Activity objMyAct, List<GetHospNames> objMyList) : base()
{
this.objActivity = objMyAct;
this.objList = objMyList;
}
public override GetHospNames this[int position]
{
get
{
return objList[position];
}
}
public override int Count
{
get
{
return objList.Count;
}
}
public override long GetItemId(int position)
{
return position;
}
public static Bitmap bytesToBitmap(byte[] imageBytes)
{
Bitmap bitmap = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
return bitmap;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = objList[position];
if (convertView == null)
{
convertView = objActivity.LayoutInflater.Inflate(Resource.Layout.ContListViewHospName, null);
}
convertView.FindViewById<TextView>(Resource.Id.tvHospID).Text = item.HospID;
convertView.FindViewById<TextView>(Resource.Id.tvHospName).Text = item.HospName;
byte[] img =item.HospLogo;
Bitmap bitmap = BitmapFactory.DecodeByteArray(img, 0, img.Length);
convertView.FindViewById<ImageView>(Resource.Id.imgLogo).SetImageBitmap(bitmap);
return convertView;
}
}
}
This is JSON Code:
private void BindControl_BindHospCompleted(object sender, BindControl.BindHospCompletedEventArgs e)
{
jsonValue = e.Result.ToString();
if (jsonValue == null)
{
Toast.MakeText(this, "No Data For Bind", ToastLength.Long).Show();
return;
}
try
{
JArrayValue = JArray.Parse(jsonValue);
list = new List<GetHospNames>();
int count = 0;
while (count < JArrayValue.Count)
{
GetHospNames getHospName = new GetHospNames(JArrayValue[count]["HospID"].ToString(), JArrayValue[count]["HospName"].ToString(),JArrayValue[count]["Logo"]);
list.Add(getHospName);
count++;
}
listView.Adapter = new ContListViewHospNameClass(this, list);
}
catch (Exception ex)
{
Toast.MakeText(this, ex.ToString(), ToastLength.Long).Show();
}
}
public static void SetImageFromByteArray (byte[] iArray, UIImageView imageView)
{
if (iArray != null && iArray.Length > 0) {
Bitmap bitmap = BitmapFactory.DecodeByteArray (iArray, 0, iArray.Length);
imageView.SetImageBitmap (bitmap);
}
}
That's it. If this is not working, your byte array may not be a valid image.
public static bool IsValidImage(byte[] bytes)
{
try {
using(MemoryStream ms = new MemoryStream(bytes))
Image.FromStream(ms);
}
catch (ArgumentException) {
return false;
}
return true;
}
I have got a problem with back button in MVVMCross when using zxing barcode scanner. Unfortunetly, when I press back button, there is an error: Java.Lang.NullPointerException: Attempt to invoke virtual method 'long android.graphics.Paint.getNativeInstance()' on a null object reference
When I comment metohs scan() weverything is ok.
Someone know what's going wrong?
This is my fragment scann view class:
public class ScannView : MvxFragmentActivity, IBarcodeFragmentOptions
{
protected ScannViewModel MainViewModel
{
get { return ViewModel as ScannViewModel; }
}
public static ZXingScannerFragment scanFragment;
protected override void OnResume()
{
base.OnResume();
try
{
if (scanFragment == null)
{
scanFragment = new ZXingScannerFragment();
SupportFragmentManager.BeginTransaction()
.Replace(Resource.Id.frameScanner, scanFragment)
.Commit();
}
scan();
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
protected override void OnPause()
{
try
{
scanFragment?.StopScanning();
base.OnPause();
}catch(Exception ex)
{
Console.WriteLine(ex);
}
}
protected override void OnRestart()
{
base.OnRestart();
}
public void ToogleFlashLight(bool on)
{
if (scanFragment != null)
scanFragment.SetTorch(on);
}
public void scan()
{
try
{
// var results = await CrossPermissions.Current.RequestPermissionsAsync(Plugin.Permissions.Abstractions.Permission.Camera);
// var status = results[Plugin.Permissions.Abstractions.Permission.Camera];
// if (status == Plugin.Permissions.Abstractions.PermissionStatus.Granted)
// {
var opts = new MobileBarcodeScanningOptions
{
PossibleFormats = new List<ZXing.BarcodeFormat> {
ZXing.BarcodeFormat.QR_CODE
},
CameraResolutionSelector = availableResolutions => {
foreach (var ar in availableResolutions)
{
Console.WriteLine("Resolution: " + ar.Width + "x" + ar.Height);
}
return null;
}
};
scanFragment?.StartScanning(opts,result =>
{
if (result == null || string.IsNullOrEmpty(result.Text))
{
RunOnUiThread(() => Toast.MakeText(this, "Anulowanie skanowanie", ToastLength.Long).Show());
return;
}
MainViewModel.ScannedCode = result.Text; //ChangePropertyToEmpty();
RunOnUiThread(() => Toast.MakeText(this, "Zeskanowano: " + result.Text, ToastLength.Short).Show());
});
// }
}catch(Exception ex)
{
Debug.WriteLine(ex);
}
}
protected override void OnViewModelSet()
{
MobileBarcodeScanner.Initialize(Application);
base.OnViewModelSet();
SetContentView(Resource.Layout.layout_scann);
}
}
And here in my viewmdoel I have simple method to close current viewmodel:
public void ButtonBackClick()
{
Close(this);
}