I am implementing a camera function directly in an app, as I do not want to use Intent to open the default camera application. I have followed the code provided here:
The app crashes as soon as the photo gets taken, with the following error message:
Java.Lang.RuntimeException: Fail to connect to camera service
Here is how I set it up. I have ommited the unneccessary code.
namespace camera_test
{
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Android.Support.V7.App.AppCompatActivity, Android.Hardware.Camera.IPictureCallback, Android.Hardware.Camera.IPreviewCallback,
Android.Hardware.Camera.IShutterCallback, ISurfaceHolderCallback
{
static Android.Hardware.Camera camera = null;
Button btnStart;
Button btnEnd;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
SurfaceView surface = (SurfaceView)FindViewById(Resource.Id.surface);
var holder = surface.Holder;
holder.AddCallback(this);
holder.SetType(Android.Views.SurfaceType.PushBuffers);
btnStart = FindViewById<Button>(Resource.Id.buttonStart);
btnEnd = FindViewById<Button>(Resource.Id.buttonEnd);
btnStart.Click += BtnStart_Click;
btnEnd.Click += BtnEnd_Click;
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder(); StrictMode.SetVmPolicy(builder.Build());
}
private void BtnStart_Click(object sender, EventArgs e)
{
camera.StartPreview();
private void BtnEnd_Click(object sender, EventArgs e)
{
Android.Hardware.Camera.Parameters p = camera.GetParameters();
p.PictureFormat = Android.Graphics.ImageFormatType.Jpeg;
camera.SetParameters(p);
camera.TakePicture(this, this, this);
StartActivity(typeof(MainActivity));
}
void Android.Hardware.Camera.IPictureCallback.OnPictureTaken(byte[] data, Android.Hardware.Camera camera)
{
Java.IO.FileOutputStream outStream = null;
Java.IO.File dataDir = Android.OS.Environment.ExternalStorageDirectory;
DateTime DT = DateTime.Now;
String DateTimeStamp = DT.Year.ToString("D4") + "-" + DT.Month.ToString("D2") + "-" + DT.Day.ToString("D2") + "-" + DT.Hour.ToString("D2") + DT.Minute.ToString("D2") + DT.Second.ToString("D2");
String PictureFilename = "Photo-" + DateTimeStamp + ".jpg";
if (data != null)
{
try
{
outStream = new Java.IO.FileOutputStream(dataDir + "/" + PictureFilename);
outStream.Write(data);
outStream.Close();
}
catch (FileNotFoundException e)
{
System.Console.Out.WriteLine(e.Message);
}
catch (IOException ie)
{
System.Console.Out.WriteLine(ie.Message);
}
}
}
void Android.Hardware.Camera.IPreviewCallback.OnPreviewFrame(byte[] b, Android.Hardware.Camera c)
{
}
void Android.Hardware.Camera.IShutterCallback.OnShutter()
{
}
public void SurfaceCreated(ISurfaceHolder holder)
{
try
{
camera = Android.Hardware.Camera.Open();
Android.Hardware.Camera.Parameters p = camera.GetParameters();
p.PictureFormat = Android.Graphics.ImageFormatType.Jpeg;
camera.SetParameters(p);
camera.SetPreviewCallback(this);
camera.Lock();
camera.SetPreviewDisplay(holder);
// camera.StartPreview();
}
catch (IOException e)
{
}
}
public void SurfaceDestroyed(ISurfaceHolder holder)
{
camera.Unlock();
camera.StopPreview();
camera.SetPreviewCallback(null);
camera.Release();
camera = null;
}
public void SurfaceChanged(ISurfaceHolder holder, Android.Graphics.Format f, int i, int j)
{
}
}
}
I am guessing it has something to do with the way in which the camera is opened and closed, but I can't figure out how to solve this problem. Note that the start button correctly starts the camera viewer. It is only when the end button is clicked does the app crash. Any help or suggestions would be appreciated. Also, I know that camera has been depreciated. Thanks.
UPDATE:
The error occurs when:
the device changes orientation
or when I call this line: StartActivity(typeof(MainActivity));.
I.e, the error occurs when the acitvity gets restarted (I think that if the orientation changes then it restarts the activity as well). I have no idea how else to restart my activity because I need to. Interestingly, if I switch to a different activity then switch back to my main activity that has the camera function, the error does not occure. I am very puzzled.
Is there a reason why you use the deprecated camera api?
You should use camera2:
https://developer.android.com/reference/android/hardware/camera2/package-summary
Xamarin also provides a basic example for this:
https://developer.xamarin.com/samples/monodroid/android5.0/Camera2Basic/
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I have C# application for a Food Truck. I have some music playing when customers view the menu. On the menu form I have four tabs. I have the WMPLib code in form load. When the form loads the music begins playing however when I switch to a different tab the music stops. I have debugged but there is nothing there to really see since it runs the lines but just stops when you switch tabs. Any ideas on how to keep the music playing when switching tabs on the main form. I would like it to play continuous not just start again on each tab. Thanks. Here is an image of the form with the tabs.
Here is the form load code:
try
{
WMPLib.WindowsMediaPlayer wplayer = new WMPLib.WindowsMediaPlayer();
wplayer.URL = "runningdownadream.mp3";
wplayer.settings.setMode("loop", true);
wplayer.controls.play();
}
catch (Exception ex)
{
MessageBox.Show("No music. Windows Media Player not installed.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
In order to play an MP3 in the background using WMPLib, try the following:
Create a class (name: HelperMp3.cs)
HelperMp3.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AxWMPLib;
using System.Diagnostics;
namespace WmpLibTest
{
public class HelperMp3 : IDisposable
{
public delegate void EventHandlerMediaError(object sender, object pMediaObject);
public delegate void EventHandlerPlayStateChanged(object sender, int newValue);
//events
public event EventHandlerMediaError Mp3MediaError;
public event EventHandlerPlayStateChanged Mp3PlayStateChanged;
public string MP3Filename { get; set; } //fully-qualified MP3 filename
private WMPLib.WindowsMediaPlayer _wplayer = new WMPLib.WindowsMediaPlayer();
public HelperMp3()
{
//subscribe to events (add event handlers)
_wplayer.PlayStateChange += _wplayer_PlayStateChange;
_wplayer.MediaError += _wplayer_MediaError;
}
private void _wplayer_MediaError(object pMediaObject)
{
System.Diagnostics.Debug.WriteLine("Error (MediaError): " + pMediaObject.ToString());
//if subscribed to event, raise event, otherwise throw exception
if (Mp3MediaError != null)
{
//raise event
Mp3MediaError(this, pMediaObject);
}
else
{
throw new Exception("Error (MediaError): " + pMediaObject.ToString());
}
}
private void _wplayer_PlayStateChange(int NewState)
{
//Undefined = 0,
//Stopped = 1,
//Paused = 2,
//Playing = 3,
//ScanForward = 4,
//ScanReverse = 5,
//Buffering = 6,
//Waiting = 7,
//MediaEnded = 8,
//Transitioning = 9,
//Ready = 10,
//Reconnecting = 11,
//Last = 12
if (Mp3PlayStateChanged != null)
{
//raise event
Mp3PlayStateChanged(this, NewState);
}
System.Diagnostics.Debug.WriteLine("_wplayer_PlayStateChange: " + NewState.ToString());
}
public void Dispose()
{
if (_wplayer != null)
{
_wplayer.controls.stop();
//unsubscribe from events (add event handlers)
_wplayer.PlayStateChange -= _wplayer_PlayStateChange;
_wplayer.MediaError -= _wplayer_MediaError;
//release all resources
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(_wplayer);
_wplayer = null;
}
}
public void Start()
{
if (_wplayer != null)
{
_wplayer.controls.play();
}
}
public void Stop()
{
if (_wplayer != null)
{
_wplayer.controls.stop();
}
}
public void PlayMp3()
{
Debug.WriteLine("MP3Filename: " + MP3Filename);
if (String.IsNullOrEmpty(MP3Filename) || !System.IO.File.Exists(MP3Filename))
{
throw new Exception("MP3Filename not specified.");
}
Debug.WriteLine("Playing mp3...");
//set value
_wplayer.URL = MP3Filename;
_wplayer.settings.setMode("loop", true);
_wplayer.controls.play();
}
}
}
In the form (ex: Form1) code, create an instance of the class above:
private HelperMp3 _helperMp3 = new HelperMp3();
Then create a method that starts the music:
private void StartMusic(string mp3Filename)
{
//set property
helperMp3.MP3Filename = mp3Filename;
Task t1 = Task.Run(_helperMp3.PlayMp3);
}
Subscribe to the Load event for the form (ex: Form1_Load) and add the following code:
private void Form1_Load(object sender, EventArgs e)
{
//ToDo: replace with your MP3 filename
StartMusic(#"C:\Temp\Test.mp3");
}
Subscribe to the FormClosed event for the form (ex: Form1_FormClosed) and add the following code:
Form1_FormClosed
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if (_helperMp3 != null)
{
_helperMp3.Dispose();
_helperMp3 = null;
}
}
Alternatively, one can use BackgroundWorker. If using BackgroundWorker, in HelperMp3.cs change method PlayMp3 to the following:
public void PlayMp3(System.ComponentModel.BackgroundWorker worker, System.ComponentModel.DoWorkEventArgs e)
{
Debug.WriteLine("MP3Filename: " + MP3Filename);
if (String.IsNullOrEmpty(MP3Filename) || !System.IO.File.Exists(MP3Filename))
{
throw new Exception("MP3Filename not specified.");
}
if (worker.CancellationPending || e.Cancel)
{
e.Cancel = true;
}
Debug.WriteLine("Playing mp3...");
//set value
_wplayer.URL = MP3Filename;
_wplayer.settings.setMode("loop", true);
_wplayer.controls.play();
}
Note: If using BackgroundWorker, the BackgroundWorker will complete, but the WMPLib control will still be running.
I have a pretty basic android application. Most of it is still from the template. I use an own class library for a XMPP client. Now what is happening, is that if I declare a global TextView for use in events or different methods(OnCreate, OnResume etc.) my events seem not to get raised.
My library is definetly not the reason since I tested it under different circumstances.
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme.NoActionBar", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
public XMPPClient client;
TextView consoleText;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
FloatingActionButton fab = FindViewById<FloatingActionButton>(Resource.Id.fab);
fab.Click += FabOnClick;
//consoleText = FindViewById<TextView>(Resource.Id.consoleText);
client = new XMPPClient("10.0.2.2", 5222, "chris3", "Define")
{
AuthenticationInfo = true
};
client.OnPublishEvent += Client_OnPublishEvent;
client.OnConnection += Client_OnConnection;
client.OnMessageReceived += Client_OnMessageReceived;
}
private void Client_OnMessageReceived(object sender, MessageEventArgs e)
{
//consoleText.Text += "\nMessage: " + e.text + " from " + e.from;
Log.Debug("mytag", "Message!");
}
private void Client_OnPublishEvent(object sender, SubscriptionEventArgs e)
{
//consoleText.Text += "\nPublication: " + e.title + " with content " + e.content + " at " + e.published;
Log.Debug("mytag", "Publication");
}
private void Client_OnConnection(object sender, ConnectionEventArgs e)
{
//consoleText.Text += "\nConnection status changed: " + e.Status;
Log.Debug("mytag", "ConnectionChange");
}
public override bool OnCreateOptionsMenu(IMenu menu)
{
MenuInflater.Inflate(Resource.Menu.menu_main, menu);
return true;
}
public override bool OnOptionsItemSelected(IMenuItem item)
{
int id = item.ItemId;
if (id == Resource.Id.action_subscribe)
{
client.Subscribe("Node1");
Log.Debug("mytag", "Subscribed");
return true;
}
return base.OnOptionsItemSelected(item);
}
private void FabOnClick(object sender, EventArgs eventArgs)
{
View view = (View) sender;
client.Connect();
}
}
When the TextView consoleText object is there, my OnConnection-event gets fired in the beginning, and when I close the client.
However, if it isn't there, every event works perfectly fine.
For now as I am a beginner with Xamarin I'm really interested on the source of the problem.
You likely need to wrap the text assignments to be processed against the primary dispatcher (UI Thread).
So for example it would look something like this.
private void Client_OnMessageReceived(object sender, MessageEventArgs e)
{
Activity.RunOnUiThread(() => {
consoleText.Text += "\nMessage: " + e.text + " from " + e.from;
});
Log.Debug("mytag", "Message!");
}
Give that a try and let me know if it still errors, don't forget you'll need to wrap all of the consoleText.Text assignments inside of this.
Activity.RunOnUiThread(() => {
});
// You might not need the Activity part, I can't remember exactly which
// one it is for an AppCompatActivity.
RunOnUiThread(() => {
});
I have a Xamarin.Forms application that supports only UWP. I cannot find a way to print a pdf document. Whatever I have seen on the web, for some reason doesn't work for me. E.g. I tried
https://www.syncfusion.com/kb/8767/how-to-print-pdf-documents-in-xamarin-forms-platform
It lets me print, but the preview in the print dialog never shows up, and the progress indicator just keeps rotating forever.
I also tried http://zawayasoft.com/2018/03/13/uwp-print-pdf-files-silently-without-print-dialog/
This gives me errors that I cannot fix.
So I wonder if somebody can suggest something else that would actually work. Maybe something newer than what I have tried (I use VS 2017). Printing without the printing dialog would be preferable.
Thank you in advance.
I used a very dirty hack to do that!
What I had to do was to try to print the image version of the pdf (I did the conversion in backend) and then used the following DependencyInjection:
Inside my Print class in UWP project:
class Print : IPrint
{
void IPrint.Print(byte[] content)
{
Print_UWP printing = new Print_UWP();
printing.PrintUWpAsync(content);
}
}
and the class responsible for printing in uwp:
public class Print_UWP
{
PrintManager printmgr = PrintManager.GetForCurrentView();
PrintDocument PrintDoc = null;
PrintDocument printDoc;
PrintTask Task = null;
Windows.UI.Xaml.Controls.Image ViewToPrint = new Windows.UI.Xaml.Controls.Image();
public Print_UWP()
{
printmgr.PrintTaskRequested += Printmgr_PrintTaskRequested;
}
public async void PrintUWpAsync(byte[] imageData)
{
int i = 0;
while (i < 5)
{
try
{
BitmapImage biSource = new BitmapImage();
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
await stream.WriteAsync(imageData.AsBuffer());
stream.Seek(0);
await biSource.SetSourceAsync(stream);
}
ViewToPrint.Source = biSource;
if (PrintDoc != null)
{
printDoc.GetPreviewPage -= PrintDoc_GetPreviewPage;
printDoc.Paginate -= PrintDoc_Paginate;
printDoc.AddPages -= PrintDoc_AddPages;
}
this.printDoc = new PrintDocument();
try
{
printDoc.GetPreviewPage += PrintDoc_GetPreviewPage;
printDoc.Paginate += PrintDoc_Paginate;
printDoc.AddPages += PrintDoc_AddPages;
bool showprint = await PrintManager.ShowPrintUIAsync();
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
}
// printmgr = null;
// printDoc = null;
// Task = null;
PrintDoc = null;
GC.Collect();
printmgr.PrintTaskRequested -= Printmgr_PrintTaskRequested;
break;
}
catch (Exception e)
{
i++;
}
}
}
private void Printmgr_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)
{
var deff = args.Request.GetDeferral();
Task = args.Request.CreatePrintTask("Invoice", OnPrintTaskSourceRequested);
deff.Complete();
}
async void OnPrintTaskSourceRequested(PrintTaskSourceRequestedArgs args)
{
var def = args.GetDeferral();
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
args.SetSource(printDoc.DocumentSource);
});
def.Complete();
}
private void PrintDoc_AddPages(object sender, AddPagesEventArgs e)
{
printDoc.AddPage(ViewToPrint);
printDoc.AddPagesComplete();
}
private void PrintDoc_Paginate(object sender, PaginateEventArgs e)
{
PrintTaskOptions opt = Task.Options;
printDoc.SetPreviewPageCount(1, PreviewPageCountType.Final);
}
private void PrintDoc_GetPreviewPage(object sender, GetPreviewPageEventArgs e)
{
printDoc.SetPreviewPage(e.PageNumber, ViewToPrint);
}
}
Please note that this is not a perfect solution and sometimes it crashes without actually being able to trace the exception (which is really strange) so I am sure there must be better answers even though it does the job.
In my windows phone application I'm getting the using current location using the following code
private void GetCoordinate()
{
var watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High)
{
MovementThreshold = 2
};
watcher.PositionChanged += this.watcher_PositionChanged;
watcher.StatusChanged += this.watcher_StatusChanged;
watcher.Start();
}
void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
{
switch (e.Status)
{
case GeoPositionStatus.Disabled:
MessageBox.Show("Current position not available!!");
break;
case GeoPositionStatus.NoData:
MessageBox.Show("Current position not available!!");
break;
}
}
private void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
try
{
var pos = e.Position.Location;
StaticData.currentCoordinate = new GeoCoordinate(pos.Latitude, pos.Longitude);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
As shown above I am calling the GetCoordinate method in the page load event of the application page. By using that GPS coordinate values I was enabling or disabling some controls on the page. But here, the issue is page load code executing first and then we are getting the Gps coordinate values..
I need the GPS Coordinate values in pageload. please suggest
You shall start the watcher in the page load, and once the GeoCoordinateWatcher collects the GeoCoordinate value it triggers PositionChanged event where in you shall code for enabling disabling the controls.
So now your code would look like this
private void GetCoordinate()
{
var watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High)
{
MovementThreshold = 2
};
watcher.PositionChanged += this.watcher_PositionChanged;
watcher.StatusChanged += this.watcher_StatusChanged;
watcher.Start();
}
private void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
try
{
var pos = e.Position.Location;
if(position==required one)
{
//enable disable here
}
StaticData.currentCoordinate = new GeoCoordinate(pos.Latitude, pos.Longitude);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
In my web browser app for wp7, i have two xaml pages. One is mainpage.xaml and other is web.xaml.
I have a youtube button in mainpage.xaml, if i click on it, it navigates to youtube.com in web.xaml. But if i press the device back button(to navigate to mainpage) after the youtube is fully navigated, then there is no error. But if i press the back button while the youtube is navigating then it throws an error. Error in recording the history i think(I also have history page to record the history). The error is - "Cannot write to a closed TextWriter". This error will also occur sometime for someother sites too. I have also added the image of that error. Can anyone help me with this? Thanks in advance for your help!
public partial class Web : PhoneApplicationPage
{
List<Uri> HistoryStack;
int HistoryStack_Index;
bool fromHistory;
bool navigationcancelled = false;
public IsolatedStorageFile historyFile = null;
public IsolatedStorageFileStream filestream = null;
public StreamWriter stream = null;
public Web()
{
InitializeComponent();
HistoryStack = new List<Uri>();
historyFile = IsolatedStorageFile.GetUserStoreForApplication();
if (historyFile.FileExists("History.txt"))
{
Error in this line--->filestream = historyFile.OpenFile("History.txt", System.IO.FileMode.Append, FileAccess.Write);--->Error in this line
stream = new StreamWriter(filestream);
}
else
{
filestream = historyFile.OpenFile("History.txt", System.IO.FileMode.Create);
stream = new StreamWriter(filestream);
}
HistoryStack_Index = 0;
fromHistory = false;
browsers[this.currentIndex].Navigated += new EventHandler<System.Windows.Navigation.NavigationEventArgs>(browsers_Navigated);
browsers[this.currentIndex].Navigating += new EventHandler<NavigatingEventArgs>(browsers_Navigating);
}
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
{
stream.Close();
}
}
private void browsers_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
if (!fromHistory)
{
if (HistoryStack_Index < HistoryStack.Count)
{
HistoryStack.RemoveRange(HistoryStack_Index, HistoryStack.Count - HistoryStack_Index);
}
HistoryStack.Add(e.Uri);
//HistoryURL temp = new HistoryURL();
//temp.URL = e.Uri.ToString();
//app.historyList.Add(temp);
Thread.Sleep(100);
Dispatcher.BeginInvoke(() =>
{
string title = (string)browsers[this.currentIndex].InvokeScript("eval", "document.title.toString()");
stream.WriteLine(title + ";" + e.Uri.ToString());---> **Error in this line.**
});
}
HistoryStack_Index += 1;
}
fromHistory = false;
navigationcancelled = false;
}
If I understand this correctly you are having 2 handlers for navigated event (OnNavigatedFrom and browsers_Navigated).
The problem probably is that in OnNavigatedFrom you are calling stream.Close(); so stream.WriteLine will fail the next time it is called since the stream was closed.
Try moving stream.Close(); to the application close event and use stream.Flush() after stream.WriteLine.