Xamarin Media Plugin Crashes when second photo is taken - c#

I am using the Plugin.Media (jamesmontemagno/MediaPlugin) plugin for Xamarin and I am having an issue with accepting a picture. When I take the second picture (the first picture works fine) and I click to accept the image the whole app crashes with no output as to the error. I have tried trapping the error but cannot find where it is occurring. I have as suggested removing the min SDK from Android manifest, but the crash still happens.
I have tried looking through the output in visual studio but it is always different. I am assuming the code works as it takes the image and gives me data back, to be clear, it only happens when trying to accept the second image.
private string GetTimestamp(DateTime value)
{
string timestamp = value.ToString("yyyyMMddHHmmssfff");
string filename = timestamp + ".jpg";
return filename;
}
public Command CaptureImage => new Command(TakePicture);
private async void TakePicture()
{
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
//Some message
return;
}
var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
Directory = "FoodSnap",
Name = GetTimestamp(DateTime.Now) //Gets a unique file name,
PhotoSize = Plugin.Media.Abstractions.PhotoSize.Custom,
CustomPhotoSize = 50
});
if (file == null)
return;
FilePath = file.Path;
}
I am completely stumped as to why this is happening. I am also having trouble refreshing my ViewModel when data changes in the page I am using to take the image. I can't help wondering if this has something to do with it.

I solved the problem by testing each line of code. Once I removed PhotoSize = Plugin.Media.Abstractions.PhotoSize.Custom I could take as many pictures as I need. I did use the Github information for the plugin.
I would be interested to know what I did wrong to cause the error. I would suggest that I have misunderstood the tutorial on Github.

Related

UWP app not launching with one Launcher.LaunchUriAsync override

I have an wpf app that I want to use to open another wpf app.
Call them image viewer (Gallery) and image storage (AppToAppCommunication).
Image storage app shows a list of available images.
Then, on ListBox selection changed I have this code:
private async void lbImages_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var options = new LauncherOptions();
options.ContentType = "image/jpg";
var filePath = Environment.CurrentDirectory + "\\Images\\" +
((ListBoxItem)((ListBox)sender).SelectedItem).Content;
var file = await StorageFile.GetFileFromPathAsync(filePath);
var token = SharedStorageAccessManager.AddFile(file);
ValueSet inputData = new ValueSet();
inputData.Add("Token", token);
Uri uri = new Uri("myprotocol:");
//await Launcher.LaunchUriAsync(uri); // #works
//await Launcher.LaunchUriAsync(uri, options, inputData); // #doesn't
}
Now, when I use the line at #works, it works, with no image shown, as expected.
But, when instead I use line at #desn't, it gives me this error:
Now I tried clicking OK on the popup and running a new VS instance an waiting for it to load, but it never does.
I've tried running both applications from the same solution and I can get to a breakpoint in override void OnActivated in image viewer app (Gallery) when using the #works line in image storage app (AppToAppCommunication), but I can't get to that same breakpoint when using the #doesn't line.
I don't know what the problem is and I am not able to debug it.
How could I go about finding a way to debug this properly?

How do you move documents within the Visual Studio SDK and ensure any source control providers are notified

I am trying to write a VSIX plugin that automates the process of moving files within a visual studio 2017 C++ project. So far I have tried the following, which unfortunately has not worked. The file is moved on disk and the associated VCFile is updated accordingly, however the source control provider (P4V in this particular case) does not check out the file and perform a move automatically as I would expect.
I have also tried using the OnQueryRename and OnAfterRename methods of the IVsTrackPRojectDocuments2 service. The problem with this approach is that both of these methods require an IVsProject . I have been unable to figure out how to resolve a reference to an associated IVsProject from the VCProject reference that I have. Any help from someone who knows this area a little more would be greatly appreciated!
// These variables are resolved outside the scope of this method and passed in
string oldFileLocation;
string newFileLocation;
VCProject containingProject;
IVsTrackProjectDocuments3 documentTrackingService = await asyncServiceProvider.GetServiceAsync(typeof(IVsTrackProjectDocuments3)) as IVsTrackProjectDocuments3;
int methodSucceeded = documentTrackingService.HandsOffFiles((uint)__HANDSOFFMODE.HANDSOFFMODE_DeleteAccess, 2, new string[] { oldFileLocation, newFileLocation });
// If the method did not succeed then we cannot continue
if (methodSucceeded != VSConstants.S_OK)
{
return;
}
// Now move the file on disk and update the relative path of the file
await Task.Run(() => { File.Move(oldFileLocation, newFileLocation); });
// Store the old relative path for rollback
string oldRelativePath = movedFile.RelativePath;
movedFile.RelativePath = GetRelativePath(containingProject.ProjectDirectory, newFileLocation);
methodSucceeded = documentTrackingService.HandsOnFiles(2, new string[] { oldFileLocation, newFileLocation });
// If the method did not succeed then we need to roll back
if (methodSucceeded != VSConstants.S_OK)
{
// Now move the file on disk and update the relative path of the file
await Task.Run(() => { File.Move(newFileLocation, oldFileLocation); });
movedFile.RelativePath = oldRelativePath;
}
Ok so on further investigation I realised that you can simply call 'AddFile' on the VCFile to trigger a move:
await Task.Run(() => { File.Move(oldFileLocation, newFileLocation); });
movedFile.AddFile(newFileLocation);

Tfs Check-in using PendAdd: The array must contain at least one element

So I'm having a problem with automating my code to check-in files to TFS, and it's been driving me up the wall! Here is my code:
string location = AppDomain.CurrentDomain.BaseDirectory;
TfsTeamProjectCollection baseUserTpcConnection = new TfsTeamProjectCollection(uriToTeamProjectCollection);
IIdentityManagementService ims = baseUserTpcConnection.GetService<IIdentityManagementService>();
TeamFoundationIdentity identity = ims.ReadIdentity(IdentitySearchFactor.AccountName, #"PROD1\JR", MembershipQuery.None, ReadIdentityOptions.None);
TfsTeamProjectCollection impersonatedTpcConnection = new TfsTeamProjectCollection(uriToTeamProjectCollection, identity.Descriptor);
VersionControlServer sourceControl = impersonatedTpcConnection.GetService<VersionControlServer>();
Workspace workspace = sourceControl.CreateWorkspace("MyTempWorkspace", sourceControl.AuthorizedUser);
String topDir = null;
try
{
Directory.CreateDirectory(location + "TFS");
String localDir = location + "TFS";
workspace.Map("$/Automation/", localDir);
workspace.Get();
destinationFile = Path.Combine(localDir, Name + ".xml");
string SeconddestinationFile = Path.Combine(localDir, Name + ".ial");
bool check = sourceControl.ServerItemExists(destinationFile, ItemType.Any);
PendingChange[] pendingChanges;
File.Move(sourceFile, destinationFile);
File.Copy(destinationFile, sourceFile, true);
File.Move(SecondsourceFile, SeconddestinationFile);
File.Copy(SeconddestinationFile, SecondsourceFile, true);
if (check == false)
{
workspace.PendAdd(localDir,true);
pendingChanges = workspace.GetPendingChanges();
workspace.CheckIn(pendingChanges, Comments);
}
else
{
workspace.PendEdit(destinationFile);
pendingChanges = workspace.GetPendingChanges();
workspace.CheckIn(pendingChanges, Comments);
}
and the problem is that whenever it's NEW files (PendEdit works correctly when the files already exist in TFS) that my code is attempting to check in, and it runs through this code:
if (check == false)
{
workspace.PendAdd(localDir,true);
pendingChanges = workspace.GetPendingChanges();
workspace.CheckIn(pendingChanges, Comments);
}
The files, instead of being in the included changes in pending changes, are instead in the excluded changes like so:
and when the line that actually does the check-in runs, I'll get a "The array must contain at least one element" error, and the only way to fix it is to manually add those detected changes, and promote them to included changes, and I simply can't for the life of me figure out how to do that programatically though C#. If anyone has any guidance on what direction I should take for this, I would really appreciate it! Thank you!
Edit: I've also discovered another way to solve this by reconciling the folder, which also promotes the detected changes, but again the problem is I can't seem to figure out how to program that to do it automatically.
I know that running the visual studio developer command prompt, redirecting to the folder that this mapping is in, and the running "tf reconcile /promote" is one way, but I can only automate that as far as the /promote part, because that brings up a toolbox that a user would have to input into, which defeats the purpose of the automation. I'm at a loss.
Next Edit in response to TToni:
Next Edit in response to TToni:
I'm not entirely sure if I did this CreateWorkspaceParameters correctly (see picture 1), but this time it gave the same error, but the files were not even in the excluded portions. They just didn't show up anywhere in the pending changes (see picture 2).
Check this blog:
The workspace has a method GetPendingChangesWithCandidates, which actually gets all the “Excluded” changes. Code snippet is as below:
private void PendChangesAndCheckIn(string pathToWorkspace)
{
//Get Version Control Server object
VersionControlServer vs = collection.GetService(typeof
(VersionControlServer)) as VersionControlServer;
Workspace ws = vs.TryGetWorkspace(pathToWorkspace);
//Do Delete and Copy Actions to local path
//Create a item spec from the server Path
PendingChange[] candidateChanges = null;
string serverPath = ws.GetServerItemForLocalItem(pathToWorkspace);
List<ItemSpec> its = new List<ItemSpec>();
its.Add(new ItemSpec(serverPath, RecursionType.Full));
//get all candidate changes and promote them to included changes
ws.GetPendingChangesWithCandidates(its.ToArray(), true,
out candidateChanges);
foreach (var change in candidateChanges)
{
if (change.IsAdd)
{
ws.PendAdd(change.LocalItem);
}
else if (change.IsDelete)
{
ws.PendDelete(change.LocalItem);
}
}
//Check In all pending changes
ws.CheckIn(ws.GetPendingChanges(), "This is a comment");
}

await FileIO.ReadTextAsync giving error (edited: now using IStorageFile.OpenReadAsync)

I have this method in my project. This is what it is supposed to do:
It accepts a string which is the name of a file in a folder, AV, in the Assets folder of my project. It opens this file and performs some operations on it (not all of the required operations are in the code, yet).
public async static Task<Book> ParseFile(string bookN)
{
string bookName = bookN.Replace(" ", "");
StorageFile bookFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/AV/" + bookName + ".txt"));
string content = await FileIO.ReadTextAsync(bookFile);
string chapterStr = "CHAPTER";
int numOfChapters = Utilities.NumOfTimesStringOccurs(content, chapterStr);
Book book = new Book(bookName, numOfChapters);
//book.Chapters = new List<Chapter>(numOfChapters);
return book;
}
The problem is this line:
string content = await FileIO.ReadTextAsync(bookFile);
I know this because I set a breakpoint at the first line of the method. After stepping into the code, that particular line broke and opened the .g.cs file and was highlighting a line that apparently implied the compiler could not trace it. The line had to do with diagnostics.debugger or something like that.
The next step I tried was to put in a try and display the error in a MessageDialog. The error from this was:
Object reference was not found
or something similar.
I am thinking it could be that the line
StorageFile bookFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/AV/" + bookName + ".txt"));
is causing this since it has await so maybe the operation was not complete before the next line could be executed. But I don't expect it to be slow since the files in the folder are just 5 - 6 kB each on average.
I don't know what's wrong as this is my first time of using the Storage namespace classes as I'm new to Windows Store programming.
EDIT
After going through this MSDN Forum, I changed the code to this:
StorageFile bookFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/AV/" + bookName + ".txt"));
Windows.Storage.Streams.IRandomAccessStream ras = await bookFile.OpenReadAsync();
Windows.Storage.Streams.DataReader reader = new Windows.Storage.Streams.DataReader(ras.GetInputStreamAt(0));
int numOfBytes = (int)ras.Size;
Byte[] bytes = new Byte[numOfBytes - 1];
await reader.LoadAsync((uint)numOfBytes);
reader.ReadBytes(bytes);
string content = Convert.ToBase64String(bytes);
This code should have actually worked because when I stepped through it during breakpoint, there was no error. But for some reason I can't fathom, the app doesn't react. When I set a breakpoint and I step into the code, it works (I mean it doesn't break; it does not give me the expected output) but when there is none, it "freezes".
I initially thought it was the size of the file (201 kB) that was taking too long so I changed it to another with a much lesser size (~3 kb) but it was the same. Now I'm thinking it has to do with async and await. I wish there was a way to do this without using them.
EDIT:
I'm not posting this an answer because I realized the it solved the issue but the question did not contain enough info to get an answer.
The solution was that I didn't use await on the method that was calling this method. I would have deleted it but I thought maybe it could be help someone. Thanks to everyone that attempted to solve it.
First You can check the property of your file(Assets/AV/someone.txt).
The Build Action should be Content. But not Embedded Resource or others.
If it still error. Then check if the file is existed.

Simple silverlight open-file-dialog errors

A while back I wrote a silverlight user control which had a csv import/export feature. This has been working fine, until recently I discovered it erroring in one scenario. This may have been due to moving to Silverlight 3.
The Error:
Message: Unhandled Error in Silverlight 2 Application
Code: 4004
Category: ManagedRuntimeError
Message: System.Security.SecurityException: Dialogs must be user-initiated.
at System.Windows.Controls.OpenFileDialog.ShowDialog()
at MyControl.OpenImportFileDialog()
at ...
The Code:
private void BrowseFileButton_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(lblFileName.Text))
{
if (MessageBox.Show("Are you sure you want to change the Import file?", "Import", MessageBoxButton.OKCancel) == MessageBoxResult.Cancel)
{
return;
}
}
EnableDisableImportButtons(false);
var fileName = OpenImportFileDialog();
lblFileName.Text = fileName ?? string.Empty;
EnableDisableImportButtons(true);
}
private string OpenImportFileDialog()
{
var dlg = new OpenFileDialog { Filter = "CSV Files (*.csv)|*.csv" };
if (dlg.ShowDialog() ?? false)
{
using (var reader = dlg.File.OpenText())
{
string fileName;
//process the file here and store fileName in variable
return fileName;
}
}
}
I can open an import file, but if i want to change the import file, and re-open the file dialog, it errors. Does anyone know why this is the case?
Also, I am having trouble debugging because placing a breakpoint on the same line (or prior) to the dlg.ShowDialog() call seems to cause this error to appear as well.
Any help would be appreciated?
You do two actions on one user click.
You show a messagebox which effectively uses your permission to show a dialog on user action.
You then try to show the dialog, since this is a second dialog on user action it's not allowed.
Get rid of the confirmation dialog and you'll be fine.
Remove Break Points before if (dlg.ShowDialog() ?? false) code will run its work for me.

Categories