What i am trying to achieve is my canvas to be saved as image in isolated storage and that image then be used as lock screen.
The problem is that it happens only once,after that when the canvas is updated and when i try changing the lock screen with new image, it is not updated. I tried the following code :
Uri uri;
async private void LockScreen_Click(object sender, EventArgs e)
{
bitmap = null;
bitmap = new WriteableBitmap((int)bgCanvas.Width, (int)bgCanvas.Height);
bitmap.Render(bgCanvas,null);
bitmap.Invalidate();
using(IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
{
//Delete old background file from isolated storage
if (iso.FileExists("Background"))
{
iso.DeleteFile("Background");
}
//Save canvas to isolated storage
using (IsolatedStorageFileStream isostream = iso.CreateFile("Background"))
{
Extensions.SaveJpeg(bitmap, isostream, bitmap.PixelWidth, bitmap.PixelHeight, 0, 100);
//isostream.Close();
}
}
//Access isolated storage file and put as lock screen
try
{
var isProvider = Windows.Phone.System.UserProfile.LockScreenManager.IsProvidedByCurrentApplication;
if (!isProvider)
{
var permission = await Windows.Phone.System.UserProfile.LockScreenManager.RequestAccessAsync();
isProvider = permission == Windows.Phone.System.UserProfile.LockScreenRequestResult.Granted;
}
if (isProvider)
{
uri = new Uri("ms-appdata:///Local/Background", UriKind.Absolute);
Windows.Phone.System.UserProfile.LockScreen.SetImageUri(uri);
MessageBox.Show("Lock Screen updated!");
}
else
{
MessageBox.Show("Couldn't update the lockscreen picture.");
}
}
catch (Exception ex)
{
MessageBox.Show("An error occured while updating the lockscreen picture: " + ex.Message);
}
}
The message box shows that lock screen is updated even though it is not.
I think the file isn't updated in the isolated storage but cant figure out why ?
Related
I am developing a Xamarin app which retrives info from DB, take/choose photo and upload them to remote server, display this images from the remote server and the user can delete them by tap on and press a button and download the images from the remote server to the local device.
Everything works without problem, but when I download the image and after I go to the gallery for check it, the image does not appear, whereas I can see it and open in the file explorer. When I reboot the phone, the image appear in the gallery.
Below my current button download method:
private void button_download_image_Clicked(object sender, EventArgs e)
{
Uri image_url_format = new Uri(image_url);
WebClient webClient = new WebClient();
try
{
byte[] bytes_image = webClient.DownloadData(image_url_format);
Stream image_stream = new MemoryStream(bytes_image);
string dest_folder = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).ToString();
string file_name = System.IO.Path.GetFileName(image_url_format.LocalPath);
string dest_path = System.IO.Path.Combine(dest_folder, file_name);
using (var fileStream = new FileStream(dest_path, FileMode.Create, FileAccess.Write))
{
image_stream.CopyTo(fileStream);
}
}
catch (Exception ex)
{
DisplayAlert("Error", ex.ToString(), "OK");
}
DisplayAlert("Alert", "Download completed!", "OK");
}
I tried in another device, but I got the same behavior.
Probably there is a sort of thing which does not refresh the gallery.
Any idea how to force the gallery to refresh or something similar?
You need to refresh your gallery after inserting or deleting any pictures in storage.
You can try this.
var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(dest_path)));
Xamarin.Forms.Forms.Context.SendBroadcast(mediaScanIntent);
Add these lines below your code.
Make it like
private void button_download_image_Clicked(object sender, EventArgs e)
{
Uri image_url_format = new Uri(image_url);
WebClient webClient = new WebClient();
try
{
byte[] bytes_image = webClient.DownloadData(image_url_format);
Stream image_stream = new MemoryStream(bytes_image);
string dest_folder = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).ToString();
string file_name = System.IO.Path.GetFileName(image_url_format.LocalPath);
string dest_path = System.IO.Path.Combine(dest_folder, file_name);
using (var fileStream = new FileStream(dest_path, FileMode.Create, FileAccess.Write))
{
image_stream.CopyTo(fileStream);
}
var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(dest_path)));
//for old xamarin forms version
Xamarin.Forms.Forms.Context.SendBroadcast(mediaScanIntent);
//for new xamarin forms version
//Android.App.Application.SendBroadcast(mediaScanIntent);
}
catch (Exception ex)
{
DisplayAlert("Error", ex.ToString(), "OK");
return;
}
DisplayAlert("Alert", "Download completed!", "OK");
}
You need to just refresh the file you have downloaded. It's helpful.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File("file://"+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES));
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}else{
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
}
Make sure required permission given on both platforms.
Use in your class:
bool success = await DependencyService.Get<IPhotoLibrary>().SavePhotoAsync(data, folder, filename);
Common Interface
public interface IPhotoLibrary
{
Task<bool> SavePhotoAsync(byte[] data, string folder, string filename);
}
In Android service
public async Task<bool> SavePhotoAsync(byte[] data, string folder, string filename)
{
try
{
File picturesDirectory = Environment.GetExternalStoragePublicDirectory(Environment.DirectoryPictures);
File folderDirectory = picturesDirectory;
if (!string.IsNullOrEmpty(folder))
{
folderDirectory = new File(picturesDirectory, folder);
folderDirectory.Mkdirs();
}
using (File bitmapFile = new File(folderDirectory, filename))
{
bitmapFile.CreateNewFile();
using (FileOutputStream outputStream = new FileOutputStream(bitmapFile))
{
await outputStream.WriteAsync(data);
}
// Make sure it shows up in the Photos gallery promptly.
MediaScannerConnection.ScanFile(MainActivity.Instance,
new string[] { bitmapFile.Path },
new string[] { "image/png", "image/jpeg" }, null);
}
}
catch (System.Exception ex)
{
return false;
}
return true;
}
In iOS service:
public Task<bool> SavePhotoAsync(byte[] data, string folder, string filename)
{
NSData nsData = NSData.FromArray(data);
UIImage image = new UIImage(nsData);
TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
image.SaveToPhotosAlbum((UIImage img, NSError error) =>
{
taskCompletionSource.SetResult(error == null);
});
return taskCompletionSource.Task;
}
also you can refer this one just to save an image and to reflect it in media, no need to use skiasharp for that. https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/bitmaps/saving
Hope this may resolve your issue.
Refer to Blu's answer,
I changed this Xamarin.Forms.Forms.Context.SendBroadcast(mediaScanIntent); to Android.App.Application.Context.SendBroadcast(mediaScanIntent); and all works.
I try to get screenshot of android device using appium since there is no solution with appium to get video/see app on real time.
I have function of C# to get image (screenshot)
public Image GetImages()
{
Image screen_shot = null;
try
{
if (driverAndroid == null)
{
return screen_shot;
}
var screenshot = ((ITakesScreenshot)driverAndroid).GetScreenshot();
var ms = new MemoryStream(screenshot.AsByteArray);
screen_shot = Image.FromStream(ms);
ms.Dispose();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return screen_shot;
}
and I try to call it using ironpython
class HelloWorldForm(Form):
def __init__(self):
app = test()
Form.__init__(self)
pictureBox = PictureBox()
image = app.GetImages()
pictureBox.SizeMode = PictureBoxSizeMode.StretchImage
pictureBox.Image = image
pictureBox.Dock = DockStyle.Fill
self.Controls.Add(pictureBox)
self.Show()
Application.EnableVisualStyles()
form = HelloWorldForm()
Application.Run(form)
I can get only 1st image for now, I put it in while function but it does not work.
Any solution or modification on the code so that I can get screenshot on real time, like a video.
I want to add a custom tile to the Microsoft Band through Microsoft Band SDK in a UWP app for Windows Phone. Here is my sample code.
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
try
{
// Get the list of Microsoft Bands paired to the phone.
var pairedBands = await BandClientManager.Instance.GetBandsAsync();
if (pairedBands.Length < 1)
{
Debug.WriteLine("This sample app requires a Microsoft Band paired to your device.Also make sure that you have the latest firmware installed on your Band, as provided by the latest Microsoft Health app.");
return;
}
// Connect to Microsoft Band.
using (var bandClient = await BandClientManager.Instance.ConnectAsync(pairedBands[0]))
{
// Create a Tile with a TextButton on it.
var myTileId = new Guid("12408A60-13EB-46C2-9D24-F14BF6A033C6");
var myTile = new BandTile(myTileId)
{
Name = "My Tile",
TileIcon = await LoadIcon("ms-appx:///Assets/SampleTileIconLarge.png"),
SmallIcon = await LoadIcon("ms-appx:///Assets/SampleTileIconSmall.png")
};
// Remove the Tile from the Band, if present. An application won't need to do this everytime it runs.
// But in case you modify this sample code and run it again, let's make sure to start fresh.
await bandClient.TileManager.RemoveTileAsync(myTileId);
// Create the Tile on the Band.
await bandClient.TileManager.AddTileAsync(myTile);
// Subscribe to Tile events.
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
private async Task<BandIcon> LoadIcon(string uri)
{
StorageFile imageFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri(uri));
using (IRandomAccessStream fileStream = await imageFile.OpenAsync(FileAccessMode.Read))
{
WriteableBitmap bitmap = new WriteableBitmap(1, 1);
await bitmap.SetSourceAsync(fileStream);
return bitmap.ToBandIcon();
}
}
If I run this code nothing happend. The app connected to Microsoft Band, but is not able to add a tile. The method AddTileAsync(myTile); Returns false and doesn't add a tile to the Microsoft Band.
If I try this code in a Windows Phone 8.1 app it works, but not in the UWP app.
Any ideas?
Update
Here is the sample app as download. Maybe this can help.
maybe this would help, coming from the documentation of MS Band
using Microsoft.Band.Tiles;
...
try
{
IEnumerable<BandTile> tiles = await bandClient.TileManager.GetTilesAsync();
}
catch (BandException ex)
{
//handle exception
}
//determine if there is space for tile
try
{
int tileCapacity = await bandClient.TileManager.GetRemainingTileCapacityAsync();
}
catch (BandException ex)
{
//handle ex
}
//create tile
WriteAbleBitmap smallIconBit = new WriteAbleBitmap(24, 24);
BandIcon smallIcon = smallIconBit.ToBandIcon();
WriteAbleBitmap largeIconBit = new WriteAbleBitmap(48, 48);//46, 46 for MS band 1
BandIcon largeIcon = largeIconBit.ToBandIcon();
Guid guid = Guid.NewGuid();
BandTile tile = new BandTile(guid)
{
//enable Badging
IsBadgingEnabled = true,
Name = "MYNAME"
SmallIcon = smallIcon;
TileIcon = largeIcon;
};
try
{
if(await bandClient.TileManager.AddTileAsync(tile))
{
///console print something
}
}
catch(BandException ex)
{
//blabla handle
}
I think the issue may be you're setting the writeable bitmap size to (1,1)?
I have this method working:
public static class BandIconUtil
{
public static async Task<BandIcon> FromAssetAsync(string iconFileName, int size = 24)
{
string uri = "ms-appx:///" + iconFileName;
StorageFile imageFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri(uri, UriKind.RelativeOrAbsolute));
using (IRandomAccessStream fileStream = await imageFile.OpenAsync(FileAccessMode.Read))
{
WriteableBitmap bitmap = new WriteableBitmap(size, size);
await bitmap.SetSourceAsync(fileStream);
return bitmap.ToBandIcon();
}
}
}
I am having a strange problem.I am using the Windows API Code Pack for Microsoft .NET Framework for displaying custom thumbnails for my custom file extensions.I have used the Microsoft.WindowsAPICodePack.ShellExtensions namespace methods as mentioned in the documentation and I can successfully show a thumbnail.But i am encountering a strange problem.While the shell thumbnail handler is registered, I cannot delete the file for which the thumbnail is shown.The file gets deleted alright for normal delete but while using Shift+del the file disappears form explorer without errors but will return when i refresh the folder.The file will stay there until I restart explorer.exe process or if I focus the window and wait for 60secs the file disappears on its own.The returned file doesn't allow to get deleted again giving an access denied error message.I tried using LockHunter and it shows that explorer.exe is locking the file.I am confused guys.What am I doing wrong ?. How can I fix this?.
I am using Windows 7 64 bit,visual studio 2010
My code is as follows
namespace CustomThumbnail
{
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("CustomThumbnail.XYZThumbnailer")]
[Guid("439a0bd3-8a44-401d-931c-3021ad8b1ad6")]
[ThumbnailProvider("XYZThumbnailer", ".xyz", ThumbnailAdornment = ThumbnailAdornment.VideoSprockets)]
public class MyThumbnailProvider : ThumbnailProvider, IThumbnailFromStream
{
public Bitmap ConstructBitmap(System.IO.Stream stream, int sideSize)
{
try
{
LogMessageToFile("Hello Stream");
XyzFileDefinition file = new XyzFileDefinition(stream);
using (MemoryStream mstream = new MemoryStream(Convert.FromBase64String(file.EncodedImage)))
{
LogMessageToFile("using Stream");
Bitmap bmp = new Bitmap(mstream);
LogMessageToFile(bmp.ToString());
return bmp;
}
}
catch (Exception ex)
{
LogMessageToFile(ex.ToString());
throw;
}
}
public void LogMessageToFile(string msg)
{
System.IO.StreamWriter sw = System.IO.File.AppendText(#"D:\test\testdoc.txt");
try
{
string logLine = System.String.Format(
"{0:G}: {1}.", System.DateTime.Now, msg);
sw.WriteLine(logLine);
}
finally
{
sw.Close();
}
}
}
}
New Code
public Bitmap ConstructBitmap(Stream stream, int sideSize)
{
try
{
Assembly assembly = Assembly.LoadFile(#"C:\Users\xxxx\Documents\Visual Studio 2010\Projects\MyThumbnailTest\Bin\Data\Data.dll");
Type type = assembly.GetType("Data.ThumbnailData");
MethodInfo foo = type.GetMethod("GetThumbnail");
var c= foo.Invoke(Activator.CreateInstance(type), new object[] { stream });
return (Bitmap)c;
}
catch (Exception ex)
{
LogMessageToFile("error "+ex.Message.ToString());
throw ex;
}
finally
{
stream.Close();
stream.Dispose();
}
}
And my GetThumbnail Method goes like this
public class ThumbnailData
{
public Bitmap GetThumbnail(Stream stream)
{
using (ZipFile zip = ZipFile.Read(stream))
{
ZipEntry image = zip.Entries.Where(p => p.FileName.ToLower().IndexOf(".png") > 0).FirstOrDefault();
if (image != null)
{
using (MemoryStream ms = new MemoryStream())
{
image.Extract(ms);
Bitmap bmp = new Bitmap(ms);
return bmp;
}
}
return new Bitmap(150, 150);
}
}
}
Without seeing the code, this is all I can think of:
Is your custom thumbnail code not closing the Stream for the file after it produces the thumbnail?
As my comment suggested try this:
public Bitmap ConstructBitmap(System.IO.Stream stream, int sideSize)
{
try
{
LogMessageToFile("Hello Stream");
XyzFileDefinition file = new XyzFileDefinition(stream);
using (MemoryStream mstream = new MemoryStream(Convert.FromBase64String(file.EncodedImage)))
{
LogMessageToFile("using Stream");
Bitmap bmp = new Bitmap(mstream);
LogMessageToFile(bmp.ToString());
return bmp;
}
}
catch (Exception ex)
{
LogMessageToFile(ex.ToString());
throw;
}
finally
{
stream.Close();
}
}
I have developed an application the continuous read image stream from a DSLR camera.
while (!liveViewExit)
{
// Create a Memory Stream
stream = new IntPtr();
// Get the bitmap image from the DSLR
bmp = GetEvfImage(stream);
if (bmp != null)
{
// Crop the image.
picImage = (System.Drawing.Image)bmp.Clone(new Rectangle(10, 0, 492, 768), bmp.PixelFormat);
try
{
if (picImage != null)
this.picLiveView.Image = (System.Drawing.Image)picImage.Clone();
}
catch (Exception ex)
{
Utility.HandleError(ex);
}
}
}
After running a while, I have this error for this line of code:
this.picLiveView.Image = (System.Drawing.Image)picImage.Clone();
Object is currently in use elsewhere.( at System.Drawing.Image.get_FrameDimensionsList()
at System.Drawing.ImageAnimator.CanAnimate(Image image)
at System.Drawing.ImageAnimator.ImageInfo..ctor(Image image)
at System.Drawing.ImageAnimator.Animate(Image image, EventHandler onFrameChangedHandler)
at System.Windows.Forms.PictureBox.Animate(Boolean animate)
at System.Windows.Forms.PictureBox.Animate()
at System.Windows.Forms.PictureBox.InstallNewImage(Image value, ImageInstallationType installationType)
at System.Windows.Forms.PictureBox.set_Image(Image value)
I think the picLiveView PictureBox control is not yet ready to accept new image.
Any idea how on detect if PictureBox is still in used.
// Added:
It is a single thread. I think the picturebox is not fast enough to process the picture object in the while loop.
Are multiple threads updating the picLiveView image? If so that would explain this problem. Just use one thread instead, and serialize the update - alternatively you could use a lock to access picLiveView:
private readonly object myLock = new object();
...
if (picImage != null)
{
lock(myLock)
{
this.picLiveView.Image = (System.Drawing.Image)picImage.Clone();
}
}
I know am late...but try this, if someone have same issue..
if (bmp != null)
{
// Crop the image.
picImage = (System.Drawing.Image)bmp.Clone(new Rectangle(10, 0, 492, 768), bmp.PixelFormat);
**Bitmap img = new Bitmap(picImage);
picImage.Dispose();
picImage = null;**
try
{
if (picImage != null)
**this.picLiveView.Image = img;**
}
catch (Exception ex)
{
Utility.HandleError(ex);
}
}