i have created xamarin form app for signpad which capture sign and saving png file to device storage but file is not writing on storage
here is my code to convert image to bytes[]
var image = await signature.GetImageStreamAsync(SignaturePad.Forms.SignatureImageFormat.Png);//getting png file from here
var signatureMemoryStream = image as MemoryStream;
byte[] data = signatureMemoryStream.ToArray();// convert png to bytes[]
string fileName = "img.png";
DependencyService.Get<IFileReadWrite>().WriteData(fileName, data);
I have created DependencyService (Interface) for saving file
public interface IFileReadWrite
{
void WriteData(string fileName, byte[] data);
}
This is my code to save file using native(app.android) api
public class FileHelper : IFileReadWrite
{
public void WriteData(string filename, byte[] data)
{
var documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var filePath = Path.Combine(documentsPath, filename);
File.WriteAllBytes(filePath, data); // this execute without error but file is not saving on path
}
}
i already have given permission WRITE_EXTERNAL_STORAGE in mainfest
Replace this in your code and try:
var documentsPath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads);
Hope this may solve your issue.
Related
im developing a Xamarin Forms App where the User can take Videos and save them to the public external storage. Im currently saving the filename of the created video.
My way of saving the video:
private readonly string DirectoryName = "KiloFürKilo";
public async Task<string> CaptureVideoAsync()
{
var photo = await MediaPicker.CaptureVideoAsync();
await using var stream = await photo.OpenReadAsync();
await using var memoryStream = new MemoryStream();
await stream.CopyToAsync(memoryStream);
var filename = "KforK" + DateTime.Now + ".mp4";
SaveVideoFromByte(memoryStream.ToArray(), filename);
return filename;
}
private async void SaveVideoFromByte(byte[] imageByte, string filename)
{
var context = CrossCurrentActivity.Current.AppContext;
var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
//Android 10+
if (Android.OS.Build.VERSION.SdkInt > Android.OS.BuildVersionCodes.P)
{
using var resolver = context.ContentResolver;
var contentValues = new ContentValues();
contentValues.Put(MediaStore.IMediaColumns.DisplayName, filename);
contentValues.Put(MediaStore.IMediaColumns.MimeType, "video/mp4");
contentValues.Put(MediaStore.IMediaColumns.RelativePath, "DCIM/" + DirectoryName);
var uri = resolver.Insert(MediaStore.Video.Media.ExternalContentUri, contentValues);
using var stream = resolver.OpenOutputStream(uri);
await stream.WriteAsync(imageByte);
stream.Close();
mediaScanIntent.SetData(uri);
}
else
{
var rootPath =
Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryMovies);
var storagePath = Path.Combine(rootPath.ToString(), DirectoryName);
if (!File.Exists(storagePath))
{
Directory.CreateDirectory(storagePath);
}
string path = Path.Combine(storagePath.ToString(), filename);
File.WriteAllBytes(path, imageByte);
mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(path)));
}
context.SendBroadcast(mediaScanIntent);
}
I now want to be able to open and play the video, without the user need to pick it from the gallery.
How can i find a video in the external public storage by a filename and retrieve the path to it?
I think i have to use the MediaStore but could not figure out how.
Thanks to anyone who can help me with this problem:)
MediaStore insert() gave you an uri where you wrote the file.
To read/play the file you can use the same uri.
Further your relative path was "DCIM/"+DirectoryName;
And if you need a path then complete path is
"/storage/emulated/0/DCIM/"+DirectoryName+"/"+filename.
So, In my app I need to get a file from the user's drive and upload it to mine.
I've searched and it seems like the only way to do this is by downloading the file from the user's drive and then uploading it to mine.
I already have all the OAuth2 settled and I'm able to create, get and list files.
But my problem is that according to google's documentation, I'm suposed to download the file to a ByteArrayOutputStream declared as an OutputStream, but when I upload the file, I'm supposed to upload a java.io file
Does anyone knows how I can get the outputstream from the download method and turn it into a file in order to send to the upload method?
This is my code so far:
The code to download the file (I got it from google)
public Task<java.io.File> downloadFile(PostFileHolder postFileHolder) {
return Tasks.call(mExecutor, () -> {
// Retrieve the metadata as a File object.
Log.i("download file", "chegou");
OutputStream outputStream = new ByteArrayOutputStream();
mDriveService.files().export(postFileHolder.getGoogleId(), "application/pdf")
.executeMediaAndDownloadTo(outputStream);
// I need to use the export method because I will have some docs and slides files
return null;
});
}
And this is the code to upload files:
public Task<File> uploadFileWithMetadata(java.io.File javaFile, String mimeType, boolean isSlide, #Nullable final String folderId) {
return Tasks.call(mExecutor, () -> {
Log.i("upload file", "chegou" );
String convertTo;
if(isSlide){
convertTo = TYPE_GOOGLE_SLIDES;
}
else{
convertTo = TYPE_GOOGLE_DOCS;
}
List<String> folder;
if (folderId == null) {
folder = Collections.singletonList("root");
} else {
folder = Collections.singletonList(folderId);
}
File metadata = new File()
.setParents(folder)
.setName(javaFile.getName())
.setMimeType(convertTo);
FileContent mediaContent = new FileContent(convertTo, javaFile);
File uploadedFile = mDriveService.files().create(metadata, mediaContent)
.setFields("id,name,size,createdTime,modifiedTime,starred,thumbnailLink,mimeType")
.execute();
Log.i("File ID: " , uploadedFile.getId());
return uploadedFile;
});
}
Thanks!
You can simply use following minimal code to create a file. And use this file later on to upload.
val outputStream = ByteArrayOutputStream() // Your
val byteData = bos.toByteArray()
val mainFile = File("Path with filename")
//write the bytes in file
val fos = FileOutputStream(mainFile)
fos.write(bitmapdata)
fos.flush()
fos.close()
Since ur outputStream was initialized as ByteArrayOutputStream so you can simply use cast method e.g ((ByteArrayOutputStream) outputStream).toByteArray()
Regarding path, You can save file anywhere in your internal file directory or external storage as temporary file. I would recommend you to go through Data and File Storage Overview and this tutorial for more information.
How can be compress the image taken in Xamarin.Android using CameraSourcePreview, the byte in the method OnPictureTaken is too big.
Here's one way to do it by converting the Bitmap to a compressed JPG file. Also in this example is how to save the compressed JPG file to the picture gallery and make it immediately available through USB/Windows via an Android Media Scan. Hope this helps!
public void OnPictureTaken(byte[] data, Camera camera) {
var bmp = BitmapFactory.DecodeByteArray(data, 0, data.Length);
SaveBitmapAsJPEG(bmp, 75);
}
public void SaveBitmapAsJPEG(Bitmap pBitmap, int pnQuality = 85) {
Java.IO.File jFolder = GetCreatePhotoAlbumStorageDir("MyPhotoAlbum");
Java.IO.File jFile = new Java.IO.File(jFolder, $"Photo_{DateTime.Now.ToString("yyyyMMddHHmmss")}.jpg");
// "/storage/emulated/0/Pictures/MyPhotoAlbum/Photo_20190526112410.jpg", which is the following via Windows/USB...
// "Internal shared storage\Pictures\MyPhotoAlbum\Photo_20190526112410.jpg"
using (var fs = new FileStream(jFile.AbsolutePath, FileMode.CreateNew)) {
pBitmap.Compress(Bitmap.CompressFormat.Jpeg, pnQuality, fs);
}
SavePictureToGallery(jFile);
Android.Util.Log.Info("MyApp", $"Picture saved using SaveBitmapAsJPEG() at {jFile.AbsolutePath}");
// Request the media scanner to scan a file and add it to the media database (Make file visible/available through USB connection in Windows Explorer)
var f = new Java.IO.File(jFile.AbsolutePath);
var intent = new Intent(Intent.ActionMediaScannerScanFile);
intent.SetData(Android.Net.Uri.FromFile(f));
Application.Context.SendBroadcast(intent);
}
public Java.IO.File GetCreatePhotoAlbumStorageDir(string psAlbumName) {
// Get the directory for the user's public pictures directory. Will create if it doesn't exist.
var dir = new Java.IO.File(Environment.GetExternalStoragePublicDirectory(Environment.DirectoryPictures), psAlbumName);
if (!dir.Exists())
dir.Mkdirs();
return dir;
}
private void SavePictureToGallery(Java.IO.File pFile) {
var intent = new Intent(MediaStore.ActionImageCapture);
intent.PutExtra(MediaStore.ExtraOutput, Android.Net.Uri.FromFile(pFile));
StartActivityForResult(intent, 0);
}
Note that you could change the format to PNG if desired by changing the "CompressFormat" to .Png, and naming the file accordingly.
I successfully store image to Internal storage but In Android i can not Display Image from Internal storage,
My Code For storage in Xamarin.Android:
public void SavePictureToDisk"ProfilePicture", byte[] imageData)
{
var pictures = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
string filePath = System.IO.Path.Combine(pictures, "ProfilePicture"+".png");
try
{
System.IO.File.WriteAllBytes(filePath, imageData);
File fl = new File(filePath);
}
catch (System.Exception e)
{
System.Console.WriteLine(e.ToString());
}
}
I successfully store image to internal storage in Android.
My Code to access file stored in Xamarin.Forms
public async void ImageDisplay()
{
IFolder rootFolder = FileSystem.Current.LocalStorage;
IFile imgfile1 = await rootFolder.GetFileAsync("ProfilePicture.png");
ImgUser.Source = ImageSource.FromFile(imgfile1.Path);
}
But image Display blank.please help me.i have tried lot of but i don't get anything.
Thanx in advance.
I would like convert Byte array to PDF file and stored it to Internal Storage. I am using below mentioned code, it is saying PDF is of invalid format.
private void ConvertToFile(string fileName , string filePath,Byte[] Bytes){
if (!File.Exists (filePath)) {
File.WriteAllBytes(filePath, Bytes);
}
}
First you get bytedata from your webservice in your application. then give the respective Absolute path (I have set internal storage path in download folder in my code below). After that WriteAllBytes is the inbuilt function that convert your bytes to pdf here :
WebService ws= new Android.WebService();
byte[] getbytedata= ws.YourMethodName();
string directory = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads);
string file = Path.Combine(directory, "temp.pdf");
System.IO.File.WriteAllBytes(file, getbytedata);
Hope this will work.