I'm able to connect to a webservice and download the data using a variety of devices, such as the BlackBerry 9000 with OS 4.6 or greater.
However, with the 8330 and OS 4.5.0.77 it doesn't work. I have not tried this code on any devices older than the 8330 with 4.5.0.77.
On the 8330 it hangs on the resultObj = op.invoke(inputObject); line in the JSR172 webservice call. This is after making the first webservice call successfully -- it hangs on the second.
There are actually two webservices:
The webservice used for authentication.
The webservice used to download all the information.
Things I've tried thus far:
Wiping the device - did nothing
Connecting the device to Eclipse to see what is going on - didn't find anything useful
Running the code on a 8330 simulator with 4.5 (MDS running)- works flawlessly with no problems
Does anyone know how to fix this issue?
Here is how I build my connection string:
String webserviceURL = developmentUrl;
// if it is simulator then force the network that is available on
// the PC
if (DeviceInfo.isSimulator()) {
webserviceURL += ";deviceside=true";
} else if ((CoverageInfo.getCoverageStatus() & CoverageInfo.COVERAGE_MDS) == CoverageInfo.COVERAGE_MDS) {
// go through MDS
webserviceURL += ";deviceside=false";
}
// else if ((CoverageInfo.getCoverageStatus() &
// CoverageInfo.COVERAGE_CARRIER) == CoverageInfo.COVERAGE_CARRIER)
// {
// webserviceURL += "'deviceside=true";// go direct
// }
// check if the wifi is available and change the url to use the wifi
// signal
if ((RadioInfo.getActiveWAFs() & RadioInfo.WAF_WLAN) != 0)
// check for carrier
{
if (WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED)
// check for wifi
{
// WebService URL when the app is being used in the
// actual device
webserviceURL = webserviceURL + ";interface=wifi";
}
}
// WebService URL when the app is being used in the actual device
_propertyValues = new Object[] { webserviceURL };
I was able to solve this problem by going to ~50k chunks for the data. I'm happy to help anyone who has a similar issue.
Related
I want to be able to remove a connection value from my app's real-time firebase database when they lose connection unexpectedly. This does not seem to be possible from what I have tried already.
I have tried using the "goOffline" function to properly close the sockets because from what I've heard, it doesn't close properly when you turn off your wifi.
func connect() {
let connectionsRef = self.rootRef.child("connections")
AF.request("https://projectname.cloudfunctions.net/Connect").response { response in
if response.data != nil {
if self.visiblename != nil {
connectionsRef.observeSingleEvent(of: .value, with: { snapshot in
for value in JSON(snapshot.value!).arrayValue {
if value["Address"].string! == self.visiblename {
let connectionRef = connectionsRef.child(String(value["Index"].int!))
connectionRef.keepSynced(true)
connectionRef.onDisconnectRemoveValue()
}
}
})
}
}
}
}
self.reachability.whenUnreachable = { _ in
Database.database().goOffline()
}
self.reachability.whenReachable = { _ in
Database.database().goOnline()
}
do {
try self.reachability.startNotifier()
} catch {}
It does automatically remove the value after around 60 seconds but I need my app to be able to handle any internet interruptions and remove the connection value quickly.
Also, if there is no available way to remove the value from the client when the client turns off their wifi. Is there a way to detect the disconnection from the server on the server itself? I have tried comparing date.getTime() to another date.getTime() variable that when you invoke the Connect request it updates the variable. Then the server watches but it didn't seem to work because for some reason it stopped watching the variable as soon as the client disconnected and doesn't have time to realize it. I assume this is because the server is based on cloud functions and has no reason to run when no clients are invoking it.
I have an iOS app that makes some small network requests on app launch (resource updates, etc). If the user turns off cellular access for the app in iOS Settings, they get a prompt from iOS about network usage every time they launch. Is there a way to know programmatically that cellular data for this app has been disabled, so that I can disable the requests at startup?
So I found this on the apple dev forums from an Apple engineer (https://devforums.apple.com/message/1059332#1059332).
Another developer wrote in to DTS and thus I had a chance to
investigate this in depth. Alas, the news is much as I expected:
there is no supported way to detect that your app is in this state.
Nor is there a way to make a "no user interaction" network connection,
that is, request that the connection fail rather than present UI like
this. If these limitations are causing problems for your app, I
encourage you to file a bug describing your specific requirements.
https://developer.apple.com/bug-reporting/
So it looks like it is not possible to detect if cellular data for your app has been turned off.
Edit
I filed a radar for this requesting that it be added. I just got this notification in my radar
We believe this issue has been addressed in the latest iOS 9 beta.
I looked through the API diffs, but so far I can't find the new API.
As of iOS9, the capability to check the setting to enable/disable use of cellular data for your app (Settings/Cellular/AppName) is available using Apple's CTCellularData class. The following code will set cellularDataRestrictedState when it is run initially and then set it and log whenever it changes:
import CoreTelephony
var cellularDataRestrictedState = CTCellularDataRestrictedState.restrictedStateUnknown
let cellState = CTCellularData.init()
cellState.cellularDataRestrictionDidUpdateNotifier = { (dataRestrictedState) in
if cellularDataRestrictedState != .restrictedStateUnknown { // State has changed - log to console
print("cellularDataRestrictedState: " + "\(dataRestrictedState == .restrictedStateUnknown ? "unknown" : dataRestrictedState == .restricted ? "restricted" : "not restricted")")
}
cellularDataRestrictedState = dataRestrictedState
}
Unfortunately (as of iOS11) this seems to check only the state of the app's switch - if your app's switch is set to enabled and the user switches the Cellular Data master switch to disabled, this API will return the app's state as being "not restricted".
Just wanted to add an Objective C version of the above Swift code for future travellers.
- (void)monitorCanUseCellularData {
if (GCIsiOS9) {
CTCellularData *cellularData = [[CTCellularData alloc] init];
NSLog(#"%ld", cellularData.restrictedState);
// 0, kCTCellularDataRestrictedStateUnknown
[cellularData setCellularDataRestrictionDidUpdateNotifier:^(CTCellularDataRestrictedState state) {
NSLog(#"%ld", state);
self.canUseCellularData = cellularData.restrictedState ==2?true:false;
}];
}
}
I have found that the CTCellularData class needs some time to get to the correct value. In my implementation I call the didUpdateNotifier very early after appDidFinishLaunching. By the time my networking call are returning with errors I definitely have a correct value for the restricted state.
class CellularRestriction: NSObject {
private static var cellularData = CTCellularData()
private static var currentState = CTCellularDataRestrictedState.restrictedStateUnknown
static var isRestricted: Bool {
currentState = cellularData.restrictedState
return currentState == .restricted
}
static func prepare() {
if currentState == .restrictedStateUnknown {
cellularData.cellularDataRestrictionDidUpdateNotifier = { state in
currentState = cellularData.restrictedState // This value may be inconsistent, however the next read of isRestricted should be correct.
}
}
}
}
You can detect if cellular data disabled using NWPathMonitor class. (https://developer.apple.com/documentation/network/nwpathmonitor)
let cellMonitor = NWPathMonitor(requiredInterfaceType: .cellular)
cellMonitor.pathUpdateHandler = { path in
self.isCellConnected = path.status == .satisfied
}
Adding to dirkgroten's answer, you can use the Apple Reachability class, found here:
https://developer.apple.com/Library/ios/samplecode/Reachability/Introduction/Intro.html
It uses SCNetworkReachability, and is very straight forward to use, it will detect connectivity via Cell and WiFi as you will need to check both at start up.
There are lots of frameworks out there that will give you the status of your network connectivity, and of course you can roll your own. I've found AFNetworking to be one of the best. It has a singleton class called AFNetworkReachabilityManager that abstracts some of the complexities for you. Specifically you'll want to look at the two boolean properties:
reachableViaWWAN
reachableViaWiFi
There is also a reachability changed status block that you can set:
– setReachabilityStatusChangeBlock:
AFNetworking Github
AFNetworkReachabilityManager
I've looking here on Forums, on the monotouch samples GIT hub, and never found a really functional sample to use CoreBluetooth in order to achieve the following:
1.Check if is there a device that match a criteria(by name or some identifier of the device) paired and connected
2.If paired but not connected, try connect to it
3.If connection fails, then show a list of the bluetooth devices that matches the criterias on topic 1 so the user can select and connect to it
Note: The device I'm trying to connect uses SPP but is Apple MFi certified. It is a credit card reader over bluetooth and some of then even implement ExternalAccessory protocols
The CoreBluetooth samples page is empty http://developer.xamarin.com/samples/ios/CoreBluetooth/
I've trying this pretty simple sample that never get the events called after the scan:
public static class BTHelper
{
private static CBCentralManager manager;
private static CBUUID UUID;
static BTHelper()
{
manager =
manager.DiscoveredPeripheral += OnDiscovery;
manager.ConnectedPeripheral += OnConnected;
manager.DisconnectedPeripheral += OnDisconnected;
UUID = CBUUID.FromString("00001101-0000-1000-8000-00805F9B34FB");
}
public static void CheckBluetooth()
{
manager.ScanForPeripherals(new[] { UUID });
}
static void OnDisconnected(object sender, CBPeripheralErrorEventArgs e)
{
Console.WriteLine("Disconnected - " + e.Peripheral.Name);
}
static void OnConnected(object sender, CBPeripheralEventArgs e)
{
Console.WriteLine("Connected - " + e.Peripheral.Name);
}
static void OnDiscovery(object sender, CBDiscoveredPeripheralEventArgs e)
{
Console.WriteLine("Found - " + e.Peripheral.Name);
}
}
Can anyone help? I've being really tired of googling and looking of many questions on SO with no real answer.
#XamarinTeam, you guys should provide a sample on how to use it... We are lost without reference...
Thank, really appreciate any help...
Gutemberg
It seems like you are looking at wrong documents.Core Bluetooth only allows you to communicate with Bluetooth Low Energy (BLE) devices using the GATT profile. you can not scan SPP device with corebluetooth.
For your MFI device, you need to check External Accessory framework , It allows communication with 'legacy' Bluetooth devices using profiles such as the Serial Port Protocol (SPP).
To answer your question:
: 1.Check if is there a device that match a criteria(by name or some identifier of the device) paired and connected
You can use showBluetoothAccessoryPicker function of EAAccessoryManager to get list of Available devices, read more here
2.If paired but not connected, try connect to it
There is not any documented way to check for this. You can not initiate connect from app without showBluetoothAccessoryPicker . You can monitor for
EAAccessoryDidConnect notification. if this method is not called, and showbluetoothaccessorypicker 's complition get called, your device is not connected.
3.If connection fails, then show a list of the bluetooth devices that matches the criterias on topic 1 so the user can select and connect to it
1)
After completion of showbluetoothaccessorypicker You can check in ConnectedAccessories . If its not avaiable, call showbluetoothaccessorypicker to display list of accessories.
Sample code for using External Accessory framework in your code
EAAccessoryManager manager= EAAccessoryManager.SharedAccessoryManager;
var allaccessorries= manager.ConnectedAccessories;
foreach(var accessory in allaccessorries)
{
yourlable.Text = "find accessory";
Console.WriteLine(accessory.ToString());
Console.WriteLine(accessory.Name);
var protocol = "com.Yourprotocol.name";
if(accessory.ProtocolStrings.Where(s => s == protocol).Any())
{
yourlable.Text = "Accessory found";
//start session
var session = new EASession(accessory, protocol);
var outputStream = session.OutputStream;
outputStream.Delegate = new MyOutputStreamDelegate(yourlable);
outputStream.Schedule(NSRunLoop.Current, "kCFRunLoopDefaultMode");
outputStream.Open();
}
}
and
public class MyOutputStreamDelegate : NSStreamDelegate
{
UILabel label;
bool hasWritten = false;
public MyOutputStreamDelegate(UILabel label)
{
this.label = label;
}
public override void HandleEvent(NSStream theStream, NSStreamEvent streamEvent)
{
//write code to handle stream.
}
}
There is not any perticular demo for using Exeternal Accessory framework,
but You can check this sample code for understanding how it works.:
Whole Project
AccessoryBrowser class
I have an iOS app that makes some small network requests on app launch (resource updates, etc). If the user turns off cellular access for the app in iOS Settings, they get a prompt from iOS about network usage every time they launch. Is there a way to know programmatically that cellular data for this app has been disabled, so that I can disable the requests at startup?
So I found this on the apple dev forums from an Apple engineer (https://devforums.apple.com/message/1059332#1059332).
Another developer wrote in to DTS and thus I had a chance to
investigate this in depth. Alas, the news is much as I expected:
there is no supported way to detect that your app is in this state.
Nor is there a way to make a "no user interaction" network connection,
that is, request that the connection fail rather than present UI like
this. If these limitations are causing problems for your app, I
encourage you to file a bug describing your specific requirements.
https://developer.apple.com/bug-reporting/
So it looks like it is not possible to detect if cellular data for your app has been turned off.
Edit
I filed a radar for this requesting that it be added. I just got this notification in my radar
We believe this issue has been addressed in the latest iOS 9 beta.
I looked through the API diffs, but so far I can't find the new API.
As of iOS9, the capability to check the setting to enable/disable use of cellular data for your app (Settings/Cellular/AppName) is available using Apple's CTCellularData class. The following code will set cellularDataRestrictedState when it is run initially and then set it and log whenever it changes:
import CoreTelephony
var cellularDataRestrictedState = CTCellularDataRestrictedState.restrictedStateUnknown
let cellState = CTCellularData.init()
cellState.cellularDataRestrictionDidUpdateNotifier = { (dataRestrictedState) in
if cellularDataRestrictedState != .restrictedStateUnknown { // State has changed - log to console
print("cellularDataRestrictedState: " + "\(dataRestrictedState == .restrictedStateUnknown ? "unknown" : dataRestrictedState == .restricted ? "restricted" : "not restricted")")
}
cellularDataRestrictedState = dataRestrictedState
}
Unfortunately (as of iOS11) this seems to check only the state of the app's switch - if your app's switch is set to enabled and the user switches the Cellular Data master switch to disabled, this API will return the app's state as being "not restricted".
Just wanted to add an Objective C version of the above Swift code for future travellers.
- (void)monitorCanUseCellularData {
if (GCIsiOS9) {
CTCellularData *cellularData = [[CTCellularData alloc] init];
NSLog(#"%ld", cellularData.restrictedState);
// 0, kCTCellularDataRestrictedStateUnknown
[cellularData setCellularDataRestrictionDidUpdateNotifier:^(CTCellularDataRestrictedState state) {
NSLog(#"%ld", state);
self.canUseCellularData = cellularData.restrictedState ==2?true:false;
}];
}
}
I have found that the CTCellularData class needs some time to get to the correct value. In my implementation I call the didUpdateNotifier very early after appDidFinishLaunching. By the time my networking call are returning with errors I definitely have a correct value for the restricted state.
class CellularRestriction: NSObject {
private static var cellularData = CTCellularData()
private static var currentState = CTCellularDataRestrictedState.restrictedStateUnknown
static var isRestricted: Bool {
currentState = cellularData.restrictedState
return currentState == .restricted
}
static func prepare() {
if currentState == .restrictedStateUnknown {
cellularData.cellularDataRestrictionDidUpdateNotifier = { state in
currentState = cellularData.restrictedState // This value may be inconsistent, however the next read of isRestricted should be correct.
}
}
}
}
You can detect if cellular data disabled using NWPathMonitor class. (https://developer.apple.com/documentation/network/nwpathmonitor)
let cellMonitor = NWPathMonitor(requiredInterfaceType: .cellular)
cellMonitor.pathUpdateHandler = { path in
self.isCellConnected = path.status == .satisfied
}
Adding to dirkgroten's answer, you can use the Apple Reachability class, found here:
https://developer.apple.com/Library/ios/samplecode/Reachability/Introduction/Intro.html
It uses SCNetworkReachability, and is very straight forward to use, it will detect connectivity via Cell and WiFi as you will need to check both at start up.
There are lots of frameworks out there that will give you the status of your network connectivity, and of course you can roll your own. I've found AFNetworking to be one of the best. It has a singleton class called AFNetworkReachabilityManager that abstracts some of the complexities for you. Specifically you'll want to look at the two boolean properties:
reachableViaWWAN
reachableViaWiFi
There is also a reachability changed status block that you can set:
– setReachabilityStatusChangeBlock:
AFNetworking Github
AFNetworkReachabilityManager
I'm trying to print a label with a Star Micronics TSP650II printer in a monotouch app.
The problem is that session.OutputStream.HasSpaceAvailable() always returns false. What am I missing?
the C# code I have goes something like this (cut for simplicity):
var manager = EAAccessoryManager.SharedAccessoryManager;
var starPrinter = manager.ConnectedAccessories.FirstOrDefault (p => p.Name.IndexOf ("Star") >= 0); // this does find the EAAccessory correctly
var session = new EASession (starPrinter, starPrinter.ProtocolStrings [0]); // the second parameter resolves to "jp.star-m.starpro"
session.OutputStream.Schedule (NSRunLoop.Current, "kCFRunLoopDefaultMode");
session.OutputStream.Open ();
byte[] toSend = GetInitData(); // this comes from another project where the same printer with ethernet cable was used in a windows environment and worked, not null for sure
if (session.OutputStream.HasSpaceAvailable()) {
int bytesWritten = session.OutputStream.Write (toSend, (uint)stillToSend.Length);
if (bytesWritten < 0) {
Debug.WriteLine ("ERROR WRITING DATA");
} else {
Debug.WriteLine("Some data written, ignoring the rest, just a test");
}
} else
Debug.WriteLine ("NO SPACE"); // THIS ALWAYS PRINTS, the output stream is never ready to take any output
UPDATE:
I was able to work-around this problem by binding Star Micronics iOS SDK to my project, but that's less than ideal as it adds 700K to the package for something that should work without that binding.
UPDATE 2:
I've been getting requests for the binding code. I still strongly recommend you try to figure out the bluetooth connectivity and not use the binding but for those who are brave enough, here it is.
This is Kale Evans, Software Integration Engineer at Star Micronics.
Although Apple's EADemo doesn't show this, the following piece of code below is important for printing to EAAccessory.(Note, below code is Objective-C example).
if ([[_session outputStream] hasSpaceAvailable] == NO)
{
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}
This gives OS time to process all input sources.
You say this does find the EAAccessory correctly
Could this be the reason the OutputStream returns false if the session is actually null?
Best Regards,
Star Support