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;
}
Related
I'm having a Xamarin Forms application where I could successfully add banner ads and native ads for the android with custom renderers using Google AdMob NuGet. What I'm trying to achieve here is to make them work on IOS, I managed to do that (I suppose as I'm receiving test ads) with banner but when it comes to native, I get unified native ad and it never renders...
I'm using it inside of a custom listview data template which I thought it might cause an issue, so I tried using it in the page itself but no luck, same issue.
Here is my IOS renderer so far:
[assembly: ExportRenderer(typeof(NativeAdMobUnit), typeof(NativeAdMobUnitRenderer))]
namespace Example.iOS.Components
{
public class NativeAdMobUnitRenderer : ViewRenderer<NativeAdMobUnit, NativeExpressAdView>
{
protected override void OnElementChanged(ElementChangedEventArgs<NativeAdMobUnit> e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
return;
if (e.OldElement == null)
{
CreateAdView(this, e.NewElement.AdUnitId);
}
}
private void CreateAdView(NativeAdMobUnitRenderer renderer,String AdUnitId)
{
if (Element == null) return;
var loader = new AdLoader(
AdUnitId,
GetVisibleViewController(),
new AdLoaderAdType[] { AdLoaderAdType.UnifiedNative },
new AdLoaderOptions[] {
new NativeAdViewAdOptions {PreferredAdChoicesPosition = AdChoicesPosition.TopRightCorner}
});
var request = Request.GetDefaultRequest();
request.TestDevices = new string[] { Request.SimulatorId };
try
{
loader.Delegate = new MyAdLoaderDelegate(renderer);
Device.BeginInvokeOnMainThread(() => {
loader.LoadRequest(Request.GetDefaultRequest());
});
}
catch(Exception ex)
{
}
}
private UIViewController GetVisibleViewController()
{
var windows = UIApplication.SharedApplication.Windows;
foreach (var window in windows)
{
if (window.RootViewController != null)
{
return window.RootViewController;
}
}
return null;
}
private class MyAdLoaderDelegate : NSObject, IUnifiedNativeAdLoaderDelegate
{
private readonly NativeAdMobUnitRenderer _renderer;
public MyAdLoaderDelegate(NativeAdMobUnitRenderer renderer)
{
_renderer = renderer;
}
public void DidReceiveUnifiedNativeAd(AdLoader adLoader, UnifiedNativeAd nativeAd)
{
Debug.WriteLine("DidReceiveUnifiedNativeAd");
}
public void DidFailToReceiveAd(AdLoader adLoader, RequestError error)
{
Debug.WriteLine("DidFailToReceiveAd");
}
public void DidFinishLoading(AdLoader adLoader)
{
Debug.WriteLine("DidFinishLoading");
}
}
}
}
And that's the same but for Android which is working as expected:
[assembly: ExportRenderer(typeof(NativeAdMobUnit), typeof(NativeAdMobUnitRenderer))]
namespace Example.Droid.Renderers
{
public class NativeAdMobUnitRenderer : ViewRenderer
{
public NativeAdMobUnitRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
{
base.OnElementChanged(e);
if (Control == null)
{
NativeAdMobUnit NativeAdUnit = (NativeAdMobUnit)Element;
var adLoader = new AdLoader.Builder(Context, NativeAdUnit.AdUnitId);
var listener = new UnifiedNativeAdLoadedListener();
listener.OnNativeAdLoaded += (s, ad) =>
{
try
{
var root = new UnifiedNativeAdView(Context);
var inflater = (LayoutInflater)Context.GetSystemService(Context.LayoutInflaterService);
var adView = (UnifiedNativeAdView)inflater.Inflate(Resource.Layout.ad_unified, root);
populateUnifiedNativeAdView(ad, adView);
SetNativeControl(adView);
}
catch
{
}
};
adLoader.ForUnifiedNativeAd(listener);
var requestBuilder = new AdRequest.Builder();
adLoader.Build().LoadAd(requestBuilder.Build());
}
}
private void populateUnifiedNativeAdView(UnifiedNativeAd nativeAd, UnifiedNativeAdView adView)
{
adView.MediaView = adView.FindViewById<MediaView>(Resource.Id.ad_media);
// Set other ad assets.
adView.HeadlineView = adView.FindViewById<TextView>(Resource.Id.ad_headline);
adView.BodyView = adView.FindViewById<TextView>(Resource.Id.ad_body);
adView.CallToActionView = adView.FindViewById<TextView>(Resource.Id.ad_call_to_action);
adView.IconView = adView.FindViewById<ImageView>(Resource.Id.ad_app_icon);
adView.PriceView = adView.FindViewById<TextView>(Resource.Id.ad_price);
adView.StarRatingView = adView.FindViewById<RatingBar>(Resource.Id.ad_stars);
adView.StoreView = adView.FindViewById<TextView>(Resource.Id.ad_store);
adView.AdvertiserView = adView.FindViewById<TextView>(Resource.Id.ad_advertiser);
// The headline and mediaContent are guaranteed to be in every UnifiedNativeAd.
((TextView)adView.HeadlineView).Text = nativeAd.Headline;
// These assets aren't guaranteed to be in every UnifiedNativeAd, so it's important to
// check before trying to display them.
if (nativeAd.Body == null)
{
adView.BodyView.Visibility = ViewStates.Invisible;
}
else
{
adView.BodyView.Visibility = ViewStates.Visible;
((TextView)adView.BodyView).Text = nativeAd.Body;
}
if (nativeAd.CallToAction == null)
{
adView.CallToActionView.Visibility = ViewStates.Invisible;
}
else
{
adView.CallToActionView.Visibility = ViewStates.Visible;
((Android.Widget.Button)adView.CallToActionView).Text = nativeAd.CallToAction;
}
if (nativeAd.Icon == null)
{
adView.IconView.Visibility = ViewStates.Gone;
}
else
{
((ImageView)adView.IconView).SetImageDrawable(nativeAd.Icon.Drawable);
adView.IconView.Visibility = ViewStates.Visible;
}
if (string.IsNullOrEmpty(nativeAd.Price))
{
adView.PriceView.Visibility = ViewStates.Gone;
}
else
{
adView.PriceView.Visibility = ViewStates.Visible;
((TextView)adView.PriceView).Text = nativeAd.Price;
}
if (nativeAd.Store == null)
{
adView.StoreView.Visibility = ViewStates.Invisible;
}
else
{
adView.StoreView.Visibility = ViewStates.Visible;
((TextView)adView.StoreView).Text = nativeAd.Store;
}
if (nativeAd.StarRating == null)
{
adView.StarRatingView.Visibility = ViewStates.Invisible;
}
else
{
((RatingBar)adView.StarRatingView).Rating = nativeAd.StarRating.FloatValue();
adView.StarRatingView.Visibility = ViewStates.Visible;
}
if (nativeAd.Advertiser == null)
{
adView.AdvertiserView.Visibility = ViewStates.Invisible;
}
else
{
((TextView)adView.AdvertiserView).Text = nativeAd.Advertiser;
adView.AdvertiserView.Visibility = ViewStates.Visible;
}
adView.SetNativeAd(nativeAd);
}
}
public class UnifiedNativeAdLoadedListener : AdListener, UnifiedNativeAd.IOnUnifiedNativeAdLoadedListener
{
public void OnUnifiedNativeAdLoaded(UnifiedNativeAd ad)
{
OnNativeAdLoaded?.Invoke(this, ad);
}
public EventHandler<UnifiedNativeAd> OnNativeAdLoaded { get; set; }
}
}
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
Is it possible to add an image to the PDF document? My layout has one (Button) and one (ImageView), I would like that when I click (Button), it will open the Gallery to select the image, show it in (ImageView) and add it to the PDF document, as if it were a generator curriculum, thank you in advance.
*Using com.itextpdf:itextg:5.5.10
here is the complete code of what you wanted. Try this and let me know.
In the onCreate method:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_to_pdf);
imageView = findViewById(R.id.imageView);
galleryBtn = findViewById(R.id.gallery);
convertBtn = findViewById(R.id.convert);
galleryBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
String imageFileName = "PDF_" + timeStamp + "_";
File storageDir = getAlbumDir();
try {
pdfPath = File.createTempFile(
imageFileName, /* prefix */
".pdf", /* suffix */
storageDir /* directory */
);
} catch (IOException e) {
e.printStackTrace();
}
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(photoPickerIntent, GALLERY_INTENT);
}
});
convertBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (bitmap == null) {
Toast.makeText(ImageToPDF.this, "Please select the image from gallery", Toast.LENGTH_LONG).show();
} else {
convertToPDF(pdfPath);
}
}
});
}
Create a directory for PDF file:
private File getAlbumDir() {
File storageDir = null;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
storageDir = new File(Environment.getExternalStorageDirectory()
+ "/dcim/"
+ "Image to pdf");
if (!storageDir.mkdirs()) {
if (!storageDir.exists()) {
Log.d("CameraSample", "failed to create directory");
return null;
}
}
} else {
Log.v(getString(R.string.app_name), "External storage is not mounted READ/WRITE.");
}
return storageDir;
}
On camera activity intent result:
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == GALLERY_INTENT) {
if (resultCode == Activity.RESULT_OK && data != null) {
Uri selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
if (selectedImage != null) {
Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String imagePath = cursor.getString(columnIndex);
bitmap = BitmapFactory.decodeFile(imagePath);
imageView.setImageBitmap(bitmap);
cursor.close();
}
}
} else if (resultCode == Activity.RESULT_CANCELED) {
Log.e("Canceled", "Image not selected");
}
}
}
Now code to convert image to PDF and save to the directory:
private void convertToPDF(File pdfPath) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
PdfDocument pdfDocument = new PdfDocument();
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(width, height, 1).create();
PdfDocument.Page page = pdfDocument.startPage(pageInfo);
Canvas canvas = page.getCanvas();
Paint paint = new Paint();
paint.setColor(Color.parseColor("#ffffff"));
canvas.drawPaint(paint);
bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
paint.setColor(Color.BLUE);
canvas.drawBitmap(bitmap, 0, 0, null);
pdfDocument.finishPage(page);
try {
pdfDocument.writeTo(new FileOutputStream(pdfPath));
Toast.makeText(ImageToPDF.this, "Image is successfully converted to PDF", Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
pdfDocument.close();
}
I have an forms app where i need to pick "1 to many" images from the phone storage.
For this i use the dependency injection system.
My problem is the somewhere i get an Android.netUri that resolves to a file that do not exist... and to a file name that i have never seen before.
The kicker is that if i pick pictures that was takes within the last couple of hours this code works...
Im am at the end of my hoap, i really hope someone can point me to something that i'm doing wrong.
i start the Picker activity with:
[assembly: Dependency(typeof(ImagePickerService))]
namespace MyApp.Droid
{
public class ImagePickerService : Java.Lang.Object, IImagePickerService
{
public async Task OpenGallery()
{
try
{
var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage);
if (status != PermissionStatus.Granted)
{
if (await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Storage))
{
Toast.MakeText(CrossCurrentActivity.Current.Activity, "Need Storage permission to access to your photos.", ToastLength.Long).Show();
}
var results = await CrossPermissions.Current.RequestPermissionsAsync(new[] { Permission.Storage });
status = results[Permission.Storage];
}
if (status == PermissionStatus.Granted)
{
Toast.MakeText(CrossCurrentActivity.Current.Activity, "Pick max 20 images", ToastLength.Long).Show();
var imageIntent = new Intent(Intent.ActionPick);
imageIntent.SetType("image/*");
imageIntent.PutExtra(Intent.ExtraAllowMultiple, true);
imageIntent.SetAction(Intent.ActionPick);
CrossCurrentActivity.Current.Activity.StartActivityForResult(Intent.CreateChooser(imageIntent, "Pick pictures"), 100);
}
else if (status != PermissionStatus.Unknown)
{
Toast.MakeText(CrossCurrentActivity.Current.Activity, "Permission Denied. Can not continue, try again.", ToastLength.Long).Show();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Toast.MakeText(CrossCurrentActivity.Current.Activity, "Error. Can not continue, try again.", ToastLength.Long).Show();
}
}
}
then in my MainActivity.cs i have the OnActivityResult
I have tried to use the ContentResolver.OpenInputStream to get the image bytes with no luck, so this is commented out atm.
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == OPENGALLERYCODE && resultCode == Result.Ok)
{
List<string> images = new List<string>();
if (data != null)
{
ClipData clipData = data.ClipData;
if (clipData != null)
{
for (int i = 0; i < clipData.ItemCount; i++)
{
ClipData.Item item = clipData.GetItemAt(i);
/*
var stream = ContentResolver.OpenInputStream(item.Uri); //This throws "FileNotFound"
byte[] byteArray;
using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
byteArray = memoryStream.ToArray();
stream.Close();
stream = null;
}
stream = ContentResolver.OpenInputStream(item.Uri);
var exif = new ExifInterface(stream);
stream.Close();
*/
Android.Net.Uri uri = item.Uri;
var path = GetActualPathFromFile(uri);
if (path != null)
{
var tmpImgPath = RotateToOriginalDimention(path);
images.Add(tmpImgPath);
}
}
}
else
{
Android.Net.Uri uri = data.Data;
var path = GetActualPathFromFile(uri);
if (path != null)
{
var tmpImgPath = RotateToOriginalDimention(path);
images.Add(tmpImgPath);
}
}
MessagingCenter.Send<App, List<string>>((App)Xamarin.Forms.Application.Current, "ImagesSelected", images);
}
}
}
And the GetActualPathFromFile (also in my MainActivity.cs)
The hole func is below but i hit this part of the code and get at "FileNotFound"
(...)
else if ("content".Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase))
{
var retval2 = getDataColumn(this, uri, null, null);
if (File.Exists(retval2)) //<----------------------- This returns "false"
{
return retval2;
}
else
{
throw new Exception("file not found " + retval2);
}
}
(...)
The Hole GetActualPathFromFile
private string GetActualPathFromFile(Android.Net.Uri uri)
{
bool isKitKat = Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Kitkat;
if (isKitKat && DocumentsContract.IsDocumentUri(this, uri))
{
// ExternalStorageProvider
if (isExternalStorageDocument(uri))
{
string docId = DocumentsContract.GetDocumentId(uri);
char[] chars = { ':' };
string[] split = docId.Split(chars);
string type = split[0];
if ("primary".Equals(type, StringComparison.OrdinalIgnoreCase))
{
var retval = Android.OS.Environment.ExternalStorageDirectory + "/" + split[1];
if (File.Exists(retval))
{
return retval;
}
else
{
throw new Exception("file not found " + retval);
}
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri))
{
string id = DocumentsContract.GetDocumentId(uri);
Android.Net.Uri contentUri = ContentUris.WithAppendedId(
Android.Net.Uri.Parse("content://downloads/public_downloads"), long.Parse(id));
//System.Diagnostics.Debug.WriteLine(contentUri.ToString());
var retval = getDataColumn(this, contentUri, null, null);
if (File.Exists(retval))
{
return retval;
}
else
{
throw new Exception("file not found " + retval);
}
}
// MediaProvider
else if (isMediaDocument(uri))
{
String docId = DocumentsContract.GetDocumentId(uri);
char[] chars = { ':' };
String[] split = docId.Split(chars);
String type = split[0];
Android.Net.Uri contentUri = null;
if ("image".Equals(type))
{
contentUri = MediaStore.Images.Media.ExternalContentUri;
}
else if ("video".Equals(type))
{
contentUri = MediaStore.Video.Media.ExternalContentUri;
}
else if ("audio".Equals(type))
{
contentUri = MediaStore.Audio.Media.ExternalContentUri;
}
String selection = "_id=?";
String[] selectionArgs = new String[]
{
split[1]
};
var retval = getDataColumn(this, contentUri, selection, selectionArgs);
if (File.Exists(retval))
{
return retval;
}
else
{
throw new Exception("file not found " + retval);
}
}
}
// MediaStore (and general)
else if ("content".Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase))
{
// Return the remote address
if (isGooglePhotosUri(uri))
{
var retval = uri.LastPathSegment;
if (File.Exists(retval))
{
return retval;
}
else
{
throw new Exception("file not found " + retval);
}
}
var retval2 = getDataColumn(this, uri, null, null);
if (File.Exists(retval2))
{
return retval2;
}
else
{
throw new Exception("file not found " + retval2);
}
}
// File
else if ("file".Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase))
{
var retval = uri.Path;
if (File.Exists(retval))
{
return retval;
}
else
{
throw new Exception("file not found " + retval);
}
}
throw new Exception("file not found ");
}
public static String getDataColumn(Context context, Android.Net.Uri uri, String selection, String[] selectionArgs)
{
ICursor cursor = null;
String column = "_data";
String[] projection =
{
column
};
try
{
cursor = context.ContentResolver.Query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.MoveToFirst())
{
int index = cursor.GetColumnIndexOrThrow(column);
return cursor.GetString(index);
}
}
finally
{
if (cursor != null)
cursor.Close();
}
return null;
}
//Whether the Uri authority is ExternalStorageProvider.
public static bool isExternalStorageDocument(Android.Net.Uri uri)
{
return "com.android.externalstorage.documents".Equals(uri.Authority);
}
//Whether the Uri authority is DownloadsProvider.
public static bool isDownloadsDocument(Android.Net.Uri uri)
{
return "com.android.providers.downloads.documents".Equals(uri.Authority);
}
//Whether the Uri authority is MediaProvider.
public static bool isMediaDocument(Android.Net.Uri uri)
{
return "com.android.providers.media.documents".Equals(uri.Authority);
}
//Whether the Uri authority is Google Photos.
public static bool isGooglePhotosUri(Android.Net.Uri uri)
{
return "com.google.android.apps.photos.content".Equals(uri.Authority);
}
Found out that the real problem was that Google Photos App was not updating and was still showing images that were deleted.
After 2x reboot of the phone, Google Photos app finally updated.
So this looks more like a cache problem with Google Foto than a xamarin problem.
I have a Listview and Click Events in the respective listItems and need to get result back from the click events and populate on the List.
My BaseAdapter class is
public class RemnantListAdapter : BaseAdapter<InventorySlabs>
{
private PartialInventory context;
private List<InventorySlabs> RemnantList;
public RemnantListAdapter(PartialInventory partialInventory, List<InventorySlabs> remnantList)
{
this.context = partialInventory;
this.RemnantList = remnantList;
}
public override InventorySlabs this[int position]
{
get
{
return RemnantList[position];
}
}
public override int Count
{
get
{
return RemnantList.Count;
}
}
public override long GetItemId(int position)
{
return position;
}
public override int ViewTypeCount
{
get
{
return Count;
}
}
public override int GetItemViewType(int position)
{
return position;
}
private class remnantHolder : Object
{
public Button EditRemnant1;
public TextView Remnant1 = null;
public TextView Rem_StockNMaterial1 = null;
public TextView Rem_Dimensions1 = null;
public TextView Rem_Status1 = null;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
remnantHolder holder = null;
if (convertView == null)
{
convertView = (convertView ?? context.LayoutInflater.Inflate(Resource.Layout.remnant_list, parent, false));
holder = new remnantHolder();
holder.EditRemnant1 = convertView.FindViewById<Button>(Resource.Id.editRemnant1);
holder.Remnant1 = convertView.FindViewById<TextView>(Resource.Id.remnant1);
holder.Rem_StockNMaterial1 = convertView.FindViewById<TextView>(Resource.Id.remnant_mtrl1);
holder.Rem_Dimensions1 = convertView.FindViewById<TextView>(Resource.Id.remnant_dimens1);
holder.Rem_Status1 = convertView.FindViewById<TextView>(Resource.Id.remnant_status1);
try
{
InventorySlabs remnantModel = this.RemnantList[position];
if (remnantModel != null)
{
holder.Remnant1.Text = "#" + remnantModel.ExtSlabNo;
holder.Rem_StockNMaterial1.Text = remnantModel.SellName + "-" + remnantModel.Depth + "-" + remnantModel.Finish;
double sqft = (remnantModel.Width * remnantModel.Height) / 144;
holder.Rem_Dimensions1.Text = "(" + remnantModel.Width.ToString() + " * " + remnantModel.Height.ToString() + ")" + sqft.ToString("N2");
holder.Rem_Status1.Text = remnantModel.Status;
holder.EditRemnant1.Click += delegate (object sender, System.EventArgs args)
{
if (remnantModel != null)
{
Intent intent = new Intent(context, typeof(EditRemnant));
intent.PutExtra("OpenPopType", 2);
intent.PutExtra("SlabNo", remnantModel.ExtSlabNo);
context.StartActivityForResult(intent, 1);
}
};
}
}
catch (Exception ex)
{
var method = System.Reflection.MethodBase.GetCurrentMethod();
var methodName = method.Name;
var className = method.ReflectedType.Name;
MainActivity.SaveLogReport(className, methodName, ex);
}
convertView.Tag = holder;
}
else
{
holder = (remnantHolder)convertView.Tag;
}
return convertView;
}
public void ActivityResult(int requestCode, Result resultCode, Intent data)
{
switch (requestCode)
{
case 1:
if (data != null)
{
try
{
string remSlab = data.GetStringExtra("extSlabNo");
if (remSlab != null)
{
remnantData.Width = double.Parse(data.GetStringExtra("remWidth"));
remnantData.Height = double.Parse(data.GetStringExtra("remHeight"));
double sqft = (remnantData.Width * remnantData.Height) / 144;
Rem_Dimensions.Text = "(" + remnantData.Width.ToString() + " * " + remnantData.Height.ToString() + ")" + sqft.ToString("N2");
}
}
catch (Exception ex)
{
var method = System.Reflection.MethodBase.GetCurrentMethod();
var methodName = method.Name;
var className = method.ReflectedType.Name;
MainActivity.SaveLogReport(className, methodName, ex);
}
}
break;
}
}
}
In my Main Activity
I am calling the Result as
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
remnantListAdapter.ActivityResult(requestCode, resultCode, data);
}
After editing the details in Edit view of the ListItem and close the Popup, I am not knowing how to Pass the Values to the Holder to Update in Listview.
You could pass the positon to the new activity in the click event and pass it back with the result intent.
For example:
holder.EditRemnant1.Click += delegate (object sender, System.EventArgs args)
{
if (remnantModel != null)
{
Intent intent = new Intent(context, typeof(EditRemnant));
intent.PutExtra("OpenPopType", 2);
intent.PutExtra("SlabNo", remnantModel.ExtSlabNo);
intent.PutExtra("Position", position );
context.StartActivityForResult(intent, 1);
}
};
And in the new activity:
protected override void OnCreate(Bundle savedInstanceState)
{
Intent intent = Intent;
var position =intent.GetIntExtra("Position", -1);
base.OnCreate(savedInstanceState);
Intent data = new Intent();
String text = "extSlabNo";
data.PutExtra("extSlabNo", text);
data.PutExtra("remWidth", 10);
data.PutExtra("remHeight", 20);
data.PutExtra("Position", position);
SetResult(Result.Ok, data);
}
Then you could modify the data in the adapter according to the positon value:
public void ActivityResult(int requestCode, Result resultCode, Intent data)
{
switch (requestCode)
{
case 1:
if (data != null)
{
try
{
string remSlab = data.GetStringExtra("extSlabNo");
int position = data.GetIntExtra("Position", -1);
if (remSlab != null && position >= 0)
{
RemnantList[position].Width = data.GetIntExtra("remWidth", -1);
RemnantList[position].Height = data.GetIntExtra("remHeight", -1);
NotifyDataSetChanged();
}
}
catch (Exception ex)
{
var method = System.Reflection.MethodBase.GetCurrentMethod();
var methodName = method.Name;
var className = method.ReflectedType.Name;
MainActivity.SaveLogReport(className, methodName, ex);
}
}
break;
}
And reset the adapter in MainActivity OnActivityResult() method :
public class MainActivity : AppCompatActivity
{
RemnantListAdapter remnantListAdapter;
ListView listView;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
List<InventorySlabs> remnantList = new List<InventorySlabs>();
for(var i = 0; i < 10; i++)
{
InventorySlabs inventorySlabs = new InventorySlabs();
inventorySlabs.Depth = i.ToString();
inventorySlabs.ExtSlabNo = i.ToString();
inventorySlabs.Finish = "Finish" + i.ToString();
inventorySlabs.Height = 200;
inventorySlabs.SellName = "SellName" + i.ToString();
inventorySlabs.Status = "Status" + i.ToString();
inventorySlabs.Width = 400;
remnantList.Add(inventorySlabs);
}
listView = FindViewById<ListView>(Resource.Id.listView1);
remnantListAdapter = new RemnantListAdapter(this, remnantList);
listView.Adapter = remnantListAdapter;
}
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
remnantListAdapter.ActivityResult(requestCode, resultCode, data);
listView.Adapter = remnantListAdapter;
}
}