Monotouch - EASession output stream gives null error - printing

Looking for some help over here.
When i run this code (below), it crashes when i process it for the second time.
it crashes with an object reference not set.. on the session.outputstream
var session= new EASession(accessory, "net.gebe");
session.OutputStream.Open();
the second time session.outputstream is null. Even when disposing session.
Richard
public void PrintIt()
{
var _accessoryList = EAAccessoryManager.SharedAccessoryManager.ConnectedAccessories;
accessory = null;
foreach(var obj in _accessoryList)
{
if(obj.ProtocolStrings.Contains("net.gebe"))
{
accessory = obj;
//break;
}
}
if(accessory == null)
{
//tmg.InfoAlert ("No Printer");
return;
}
var session= new EASession(accessory, "net.gebe");
session.OutputStream.Open();
string str2 = "HELLO THERE PRINTER 1 2 3 4 5";
byte[] printdata2;
ASCIIEncoding encoding2 = new ASCIIEncoding();
printdata2 = encoding2.GetBytes(str2);
uint nlen2 = Convert.ToUInt32 (str2.Length+1);
session.OutputStream.Write(printdata2,nlen2 );
session.OutputStream.Close ();
session.Dispose ();
}

I got mine working now. What I did:
Save the session as a variable in the class
Only create the session if session is null
You may not want to call session.OutputStream.Close() after every print. At least it's something to keep in mind while debugging for your situation.
This will allow for multiple print jobs on the same page without blowing up. session.OutputStream was not null in this case.
I also found that the ViewDidLoad/Unload events weren't great for detecting when the device becomes available/unavailable via the EAAccessoryDidConnectNotification and EAAccessory DidDisconnectNotification observers. Instead I used ViewDidAppear/ViewDidDisappear. In those methods, I tear down the session, and when I come back in to print a new job, the session gets created and OutputStream is assigned.
Lastly, I wasn't getting events fired for my device via session.OutputStream.OnEvent. Not sure if it's my device, a MonoTouch bug, or just a generic bug of mine yet.
UPDATE: Check out this nicely wrapped implementation of AccessoryAdapter

You need to list the external accessories you're going to use in your Info.plist.
There is some documentation on this on apple's site:
http://developer.apple.com/library/ios/#featuredarticles/ExternalAccessoryPT/Introduction/Introduction.html#//apple_ref/doc/uid/TP40009502
Here is a screenshot of how to set this value in Info.plist:
http://screencast.com/t/AYmOWjf8wkL
(This is from here: https://bugzilla.xamarin.com/show_bug.cgi?id=1635#c1)

Related

Visual Studio 2015 async variables not showing in debugger

I've got a .NET Core ASP.NET MVC 6 application and what I'm convinced is a bug in Visual Studio. If I place a break point after an await statement, the object does not show up in Locals, and I cannot mouse over to inspect. But if I use the variable, it still works fine, and it's definitely populated.
Something as simple as this:
public async Task<IActionResult> Index()
{
var location = await _listingLocationService.GetLocationByAddress("123 Fake Street");
return Content(location.Latitude.ToString() + " " +location.Longitude.ToString());
}
If I place the break point on the return statement, I cannot inspect location. It doesn't show up anywhere. I can even remove the await & place a .Result at the end, and still nothing shows. But when I continue, the view displays location.latitude, and location.longitude fine. So I know it's being populated.
For the sake of completeness, I'll include the GetLocationByAddress function as well, which does the same thing, if I place a breakpoint anywhere after the awaits, I can't inspect the variables (even the deserialized list!).
public async Task<Geolocation> GetLocationByAddress(string address)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://maps.googleapis.com/maps/api/geocode/json");
var request = new HttpRequestMessage(HttpMethod.Get, "?address=" + WebUtility.UrlEncode(address) + "&key=...");
var response = await client.SendAsync(request);
var contents = await response.Content.ReadAsStringAsync();
var locationResult = JsonConvert.DeserializeObject<GoogleLocationResult>(contents);
if (locationResult.status == "OK")
{
var result = locationResult.results.First().geometry.location;
return new Geolocation
{
Latitude = result.lat,
Longitude = result.lng
};
}
else
{
return null;
}
}
}
Well, after loosing all day with this issue I've finally found the source of the problem and also the solution...
In my case, the problem has started after updating my project to use the .net core 1.1 Preview 1 following the steps shown here: Link to MSFT .NET Blog
The problem was caused by this line of code in the project.json file:
"buildOptions": {
"debugType": "portable", <---- THIS
"preserveCompilationContext": true,
"emitEntryPoint": true
}
after setting "debugType" to "full", awaited variables started to show again while debugging.
Hope it helps to somebody outthere!
It's not a bug. When the debugger hits the return line, it's because the previous line immediately returned a Task object. Your GetLocation method isn't done running yet (which makes sense since it's making an outbound HTTP call that will absolutely take longer than the milliseconds it took to return a Task). When you hit the return line, your debugger has stopped there, but the incomplete task means that location won't be ready. A better place to put a breakpoint is probably in the return line of your GetLocation method.
And by the way, you'll get a null ref error in your action method if the call made to Google Maps fails.

How to detect when Vaadin FileDownloader succeeds or fails

I have Vaadin 7 code to give the user an option to download a file:
Button btnDownloadResults = new Button("Download Results", FontAwesome.CLOUD_DOWNLOAD);
resource = new StreamResource(new MyStreamResource(), suggestedSaveAsFilename);
new FileDownloader(resource).extend(btnDownloadResults);
I would like to trigger code when the download has succeeded, or even if the download manages to start. Uses for this include closing a window, starting a progress spinner, or incrementing a download count.
Unlike the Vaadin Upload component, the FileDownloader does not have any listeners for finding out when a file download fails, succeeds, or starts.
Here is a simplified version of my StreamResouce subclass:
public class MyStreamResource implements StreamSource {
#Override
public InputStream getStream() {
String filename = /* code to determine the filename */;
try {
final File results = new File(FilenameUtils.normalize(filename));
return new FileInputStream(results);
} catch (FileNotFoundException fnfe) {
String errorMsg = "Cannot download results. Try again later, or contact your sysadmin.";
Utilities.showError(errorMsg);
return null;
} catch (Exception e) {
Utilities.logAndShowException(e);
return null;
}
}
}
Note that the getStream method returns before the user has even been prompted where to save the file (which they can choose to cancel.) So I can't trigger anything from inside that method.
One suggestion I got was to subclass the FileDownloader as follows:
FileDownloader fileDownloader = new FileDownloader(fileInputStream) {
private static final long serialVersionUID = -4584979099145066535L;
#Override
public boolean handleConnectorRequest(VaadinRequest request, VaadinResponse response, String path) throws IOException {
boolean result = super.handleConnectorRequest(request, response, path);
if (result) {
/* YOUR LOGIC GOES HERE */
}
return result;
}
} ;
Again, this fires too soon (and the boolean result is always true, even if my StreamSource returns null.)
Any suggestions?
After more research I believe the answer is that there is no simple way to get this information from the FileDownloader.
The difficulty appears to be a consequence of the way the FileDownloader is designed. From the FileDownloader docs:
"Download should be started directly when the user clicks e.g. a Button without going through a server-side click listener to avoid triggering security warnings in some browsers."
Because there is no round-trip back to the web server, there is no place to respond when the download fails, starts, or succeeds.
Some vague (and possibly bad) ideas for a workaround:
Have JS post some kind of asynchronous notification to the web
server, letting it know what happened. (Using JMS or Ajax?)
If there was some kind active process on the backend involved with transferring the file, it
would know when the transfer happened.
But the short answer seems to be there is no built-in way in Vaadin to do it.

java.lang.IllegalStateException: trying to requery an already closed cursor android.database.sqlite.SQLiteCursor#

I've read several related posts and even posted and answer here but it seems like I was not able to solve the problem.
I have 3 Activities:
Act1 (main)
Act2
Act3
When going back and forth Act1->Act2 and Act2->Act1 I get no issues
When going Act2->Act3 I get no issues
When going Act3->Act2 I get occasional crashes with the following error: java.lang.IllegalStateException: trying to requery an already closed cursor android.database.sqlite.SQLiteCursor#.... This is a ListView cursor.
What I tried:
1. Adding stopManagingCursor(currentCursor);to the onPause() of Act2 so I stop managing the cursor when leaving Act2 to Act3
protected void onPause()
{
Log.i(getClass().getName() + ".onPause", "Hi!");
super.onPause();
saveState();
//Make sure you get rid of the cursor when leaving to another Activity
//Prevents: ...Unable to resume activity... trying to requery an already closed cursor
Cursor currentCursor = ((SimpleCursorAdapter)getListAdapter()).getCursor();
stopManagingCursor(currentCursor);
}
When returning back from Act3 to Act2 I do the following:
private void populateCompetitorsListView()
{
ListAdapter currentListAdapter = getListAdapter();
Cursor currentCursor = null;
Cursor tournamentStocksCursor = null;
if(currentListAdapter != null)
{
currentCursor = ((SimpleCursorAdapter)currentListAdapter).getCursor();
if(currentCursor != null)
{
//might be redundant, not sure
stopManagingCursor(currentCursor);
// Get all of the stocks from the database and create the item list
tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId);
((SimpleCursorAdapter)currentListAdapter).changeCursor(tournamentStocksCursor);
}
else
{
tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId);
}
}
else
{
tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId);
}
startManagingCursor(tournamentStocksCursor);
//Create an array to specify the fields we want to display in the list (only name)
String[] from = new String[] {StournamentConstants.TblStocks.COLUMN_NAME, StournamentConstants.TblTournamentsStocks.COLUMN_SCORE};
// and an array of the fields we want to bind those fields to (in this case just name)
int[] to = new int[]{R.id.competitor_name, R.id.competitor_score};
// Now create an array adapter and set it to display using our row
SimpleCursorAdapter tournamentStocks = new SimpleCursorAdapter(this, R.layout.competitor_row, tournamentStocksCursor, from, to);
//tournamentStocks.convertToString(tournamentStocksCursor);
setListAdapter(tournamentStocks);
}
So I make sure I invalidate the cursor and use a different one. I found out that when I go Act3->Act2 the system will sometimes use the same cursor for the List View and sometimes it will have a different one.
This is hard to debug and I was never able to catch a crashing system while debugging. I suspect this has to do with the time it takes to debug (long) and the time it takes to run the app (much shorter, no pause due to breakpoints).
In Act2 I use the following Intent and expect no result:
protected void onListItemClick(ListView l, View v, int position, long id)
{
super.onListItemClick(l, v, position, id);
Intent intent = new Intent(this, ActivityCompetitorDetails.class);
intent.putExtra(StournamentConstants.App.competitorId, id);
intent.putExtra(StournamentConstants.App.tournamentId, mTournamentRowId);
startActivity(intent);
}
Moving Act1->Act2 Act2->Act1 never gives me trouble. There I use startActivityForResult(intent, ACTIVITY_EDIT); and I am not sure - could this be the source of my trouble?
I would be grateful if anyone could shed some light on this subject. I am interested in learning some more about this subject.
Thanks,D.
I call this a 2 dimensional problem: two things were responsible for this crash:
1. I used startManagingCursor(mItemCursor); where I shouldn't have.
2. I forgot to initCursorAdapter() (for autocomplete) on onResume()
//#SuppressWarnings("deprecation")
private void initCursorAdapter()
{
mItemCursor = mDbHelper.getCompetitorsCursor("");
startManagingCursor(mItemCursor); //<= this is bad!
mCursorAdapter = new CompetitorAdapter(getApplicationContext(), mItemCursor);
initItemFilter();
}
Now it seems to work fine. I hope so...
Put this it may work for you:
#Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
orderCursor.requery();
}
This also works
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
startManagingCursor(Cursor);
}

Visual Studio 2010 add in - events not triggered

I have written an add in that takes the active document as a parameter. So each time that the active document has changed, I need to know. To do so, I wanted to use "Events.DocumentEvents.DocumentOpened" event of the DTE2 object. But the problem is that event is never get fired even though I change the active document.
The code snippet is as follows
public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
_applicationObject = (DTE2)application;
_applicationObject.Events.DocumentEvents.DocumentOpened += new _dispDocumentEvents_DocumentOpenedEventHandler(DocumentEvents_DocumentOpened);
...
}
void DocumentEvents_DocumentOpened(Document Document)
{
MessageBox.Show("Not called");
}
I have tried with DocumentEvents as well but no success. Any ideas?
I had just realized that I focused on the wrong event and thats why it was not fired. With the code below I got what I intended to. So instead of DocumentEvents, I had to use WindowEvents.
....
_applicationObject.Events.WindowEvents.WindowActivated += new _dispWindowEvents_WindowActivatedEventHandler(WindowEvents_WindowActivated);
}
void WindowEvents_WindowActivated(Window GotFocus, Window LostFocus)
{
if (ucCAST != null && GotFocus.Document != null)
((CAST)ucCAST).refreshCode(GotFocus.Document.Name);
}

J2ME/Java: Referencing StringBuffer through Threads

This question might be long, but I want to provide much information.
Overview: I'm creating a Stock Quotes Ticker app for Blackberry. But I'm having problems with my StringBuffer that contains an individual Stock information.
Process: My app connects to our server via SocketConnection. The server sends out a formatted set of strings that contains the latest Stock trade. So whenever a new trade happens, the server will send out an individual Stock Quote of that trade. Through an InputStream I am able to read that information and place each character in a StringBuffer that is referenced by Threads. By parsing based on char3 I am able to determine a set of stock quote/information.
char1 - to separate data
char3 - means end of a stock quote/information
sample stock quote format sent out by our server:
stock_quote_name(char 1)some_data(char1)some_data(char1)(char3)
My app then parses that stock quote to compare certain data and formats it how it will look like when displayed in the screen. When trades happen gradually(slow) the app works perfectly. However..
Problem: When trades happen too quickly and almost at the same time, My app is not able to handle the information sent efficiently. The StringBuffer has its contents combined with the next trade. Meaning Two stock information in one StringBuffer.
field should be: Stock_quote_name some_data some_data
sample of what's happening: Stock_quote_name some_data some_dataStock_quote_name some_data some_data
here's my code for this part:
while (-1 != (data = is.read()))
{
sb.append((char)data);
while(3 != (data = is.read()))
{
sb.append((char)data);
}
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
try
{
synchronized(UiApplication.getEventLock())
{
SetStringBuffer(sb);
DisplayStringBuffer();
RefreshStringBuffer();
}
} catch (Exception e)
{
System.out.println("Error in setting stringbuffer: " + e.toString());
}
}
});
}
public synchronized void DisplayStringBuffer()
{
try
{
//parse sb - string buffer
......
}
catch(Exception ex)
{
System.out.println("error in DisplayStringBuffer(): " + ex.toString());
}
}
public synchronized void SetStringBuffer(StringBuffer dataBuffer)
{
this.sb =dataBuffer;
System.out.println(sb);
}
public synchronized void RefreshStringBuffer()
{
this.sb.delete(0, this.sb.length());
}
From what I can see, when trades happen very fast, The StringBuffer is not refreshed immediately and still has the contents of the previous trade, when i try to put new data.
My Question is:
Do you guys have any suggestion on how i can put data into the StringBuffer, without the next information being appended to the first content
The part where you read data is synchronized, but the part where you append data to the buffer is not. If you are reusing the same StringBuffer each time, you will have a race condition.
Well, since you are using invokeLater to set / display / clear your StringBuffer, you're right, there's nothing blocking you from going back up to the next read() call and modifying that StringBuffer before you're able to dispaly it.
Obviously you're not reading from the input stream from your event thread, so in order to update the UI you need to either use invokeLater OR synchronize on the event lock, but you're doing both.
If you want to use invokeLater, then you'll need to make sure you don't append to your StringBuffer with your input stream reader thread while your event thread is attempting to display the data in the UI. Thus, you'll probably look into creating a new StringBuffer for each Runnable.
If you want to synchronize on the event lock, something like this could work (which might work better as it avoids unnecessary garbage creation with creating new Runnables / StringBuffers).
while (-1 != (data = is.read()))
{
sb.append((char)data);
while(3 != (data = is.read()))
{
sb.append((char)data);
}
synchronized(UiApplication.getEventLock())
{
SetStringBuffer(sb);
DisplayStringBuffer();
RefreshStringBuffer();
}
}
You can't reuse the same StringBuffer for each stock quote because you are reading the next stock quote before the UI thread has finished displaying the last one. Remember, you are writing to the StringBuffer on one thread, and reading the StringBuffer on another. There is no guarantee that the UI thread (reading thread) has called RefreshStringBuffer() before the loop iterates and starts appending the next stock quote to the StringBuffer.
Use a collection of Strings instead.
java.util.queue<String> q = new java.util.concurrent.ConcurrentLinkedQueue<String>();
then do q.add(sb.toString()); when your done putting the quote into sb.
to display the quotes
public void DisplayStockQuote() {
while(!q.isEmpty()) {
String s = q.poll();
// display s
try
{
//parse s - string containing stock quote
......
}
catch(Exception ex)
{
System.out.println("error in DisplayStringBuffer(): " + ex.toString());
}
}
}
Call that method from your UI thread instead of
SetStringBuffer(sb);
DisplayStringBuffer();
RefreshStringBuffer();
I suggest you try avoiding the extra thread and go with Bradley's solution. But if you really want to have two threads, something like this will work.

Resources