Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Bluetooth Support for iOS, extend support for Android #15

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from

Conversation

Ayiga
Copy link

@Ayiga Ayiga commented Sep 11, 2017

Greetings @gordol

With this update, I've been able to add Bluetooth printing support for iOS. On both platforms, in order for a printer to show up in the lists returned by findBluetoothPrinters and findPrinters, the printer must first be paired. On iOS this spawns a modal window that we don't really have control over, or the ability to interact with. Unfortunately, this means we can't guarantee a meaningful callback for a user cancelling the pairing process. As such, I've added a new method called pairBluetoothPrinters to help facilitate this.

On Android pairBluetoothPrinters just opens the Bluetooth Settings area, on iOS it spawns the aforementioned modal. The callback returns immediately and doesn't reflect any selection, pairing result, or cancellation.

As an aside, I've been thinking about adding a function that can be registered to get informed about Bluetooth Accessory connections. (Perhaps one for disconnections too), but I haven't needed it for now.

I've also taken the opportunity to add failure callbacks for most of the printing methods. I figure this will make it more consistent and easier to chain off of when it comes to failures as well as successes.

I have created an Error system that allows for an Error namespace, code, and message. I haven't really finalized any of these things, and perhaps it's something we can agree on before forcing it.

I have adjusted the Readme accordingly, and cleaned it up a little bit as well. I added a TODO section and put two things in it at the moment. I added the USB into the TODO because I'm not really familiar with it, and I know it's kind of hard-coded for your situation at the moment. However, it should probably be configured to allow for others to be able to use it with other printers as well.

Likely one of the next things I'll be working on is a way to select the device's printing paper type.

Please let me know if you have any questions,

Thanks,

~ Ayiga

Theodore Schnepper added 2 commits September 11, 2017 15:49
add working Bluetooth Support for iOS

adjust the Readme file accordingly.

update the Readme to adhere to some linting guidelines.
@@ -2,35 +2,40 @@

Uses the Brother Print SDK for Android...

More info can be found here, including a list of compatible printers: http://www.brother.com/product/dev/mobile/android/index.htm
More info can be found here, including a list of compatible printers: [http://www.brother.com/product/dev/mobile/android/index.htm](http://www.brother.com/product/dev/mobile/android/index.htm)

Already bundled is the following version: v3.0.4 (5/18/2016) which is in the `src/android/libs` dir. By downloading this you agree to the Brother SDK License terms which are included in the README under the libs dir.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What version is bundled for IOS?

Also, do we know if v3.0.4 is the current bundled version for Android? I'm guessing that's out of date...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did see that the Android SDK was updated not too long ago... but the iOS SDK hasn't been changed since May I think?

The current SDK version for iOS is 3.1.1

The current SDK version for Android is 3.0.7

I have not updated these binaries though. At least, I don't think I did.

@gordol
Copy link
Owner

gordol commented Sep 11, 2017

Thanks, I'll review this soon... I'll try to get to it this week; I need to dust off, and charge my old iPad and update Xcode probably.

I added the USB into the TODO because I'm not really familiar with it, and I know it's kind of hard-coded for your situation at the moment.

The only thing that's hard-coded is the model configuration... We should be able to make that configurable, I think.

@Ayiga
Copy link
Author

Ayiga commented Sep 11, 2017

Please hold off on any potential merge. I have a crash on iOS right now.

@gordol
Copy link
Owner

gordol commented Sep 11, 2017

for sure... no worries. i haven't even tested yet :)

@Ayiga
Copy link
Author

Ayiga commented Sep 12, 2017

Okay I was able to fix the issue and able to print on iOS again... I had a hell of a time chasing this down, all because I changed the name of a variable :\ .

}
});
}

Copy link
Owner

@gordol gordol Sep 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we just use BluetoothManager.getAdapter() to get BluetoothAdapter along with BluetoothDevice. Listen for: ACTION_DISCOVERY_STARTED, ACTION_DISCOVERY_FINISHED, and ACTION_FOUND. Then call BluetoothAdapter.startDiscovery().

Then when you find a brother device via ACTION_FOUND, simply call: BluetoothAdapter.getRemoteDevice() to get a BluetoothDevice. Then on the device returned from getRemoteDevice(), issue a createBond() call: BluetoothDevice.createBond().

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alternatively... this may provide some insight too, though probably overkill for what we need here https://github.com/tanelih/phonegap-bluetooth-plugin this is an android-only plugin for old phonegap, but the android bits should be usable.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can make this better on android with a new ticket though... if you want to stick to IOS here. lemme know...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could probably use BluetoothManager instead of BluetoothAdapter without much issue. It seems like the code would operate roughly the same without it.

As far as the .startDiscovery() call, that would seem to imply you'd like to do the pairing within the plugin itself instead of externally. Is this what you're intending? The only thing that really stopped me from doing that before is that I don't know of any UI we can display to the user that's similar to iOS's. As such, we'd either have to create that UI, or forward the options through the plugin. I didn't like either option really, because the first forces a UI we design on the developer, and the second means that there's different behavior between the plugins.

Unless you're saying you just want to find the first printer you can find and try to bond with it immediately. The only problem with that is when there are multiple printers and you only want to pair with a specific one.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you'd like to do the pairing within the plugin itself

ideally, yes... the plugin should encapsulate all of the steps to provision a printer. that's why it's possible to send USB commands. for example, to set the printer's network settings. i'd like to support the same sort of functionality for bluetooth printing too, if possible.

however, that would mean that it should be done similarly on the IOS side too... and that may be problematic.

i think CoreBluetooth should do what we need, on the IOS side, to get a list of printers and enumerate the services, pair, etc? here's a nice wrapper for it: https://github.com/LGBluetooth/LGBluetooth but i'm not 100% sure if it's possible to pair with "legacy" bluetooth devices programmatically on IOS. are these printers using BLE? if so, wonderful, if not... damnit!

The only thing that really stopped me from doing that before is that I don't know of any UI we can display to the user

well, we don't need a UI, necessarily. this is just a cordova plugin. it's exposing an api to app developers to do with as they please. we can provide an example implementation with a UI for test or example purposes, but that's ultimately a burden that falls on the end user of the plugin, to implement as needed, for their specific purposes.

ideally we just spit back a list of compatible printers, and then the implementor can show that list to a user and let them pick the one they want, or their app code can pick one automatically based on whatever criteria they want. that's outside the scope of this plugin, i think. there should be no UI here, just API.

this sort of workflow is already there for network printing. you ask for a list of printers, then pick one. ideally we can do this on both android and ios for bluetooth printing as well. but, i do understand if it's not possible on IOS. i'm sure there are "ways" such as using private frameworks, and for enterprise usage, that's fine, but you can't use private frameworks if you're pushing to the app store. for my particular use cases, app store compatibility is irrelevant, but i don't know about everyone else.

that being said...

PrivateFrameworks.BluetoothManager has the following methods: scanForConnectableDevices() and connectDevice().

maybe we can add a config.xml flag to include those methods into the ios side of the plugin, optionally, depending whether they want to fully automate, with the caveat that it's only for enterprise or private use, not for deploying to the app store.

thoughts?

@@ -222,7 +222,7 @@ public void handleMessage(Message msg) {
break;
}

final PluginResult wrongOSResult = new PluginResult(PluginResult.Status.ERROR, "Android OS is not supported");
final PluginResult wrongOSResult = pluginErrorResult("wrongOS", 1, "Android OS is not supported");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this mean the android version is not supported? obviously android operating system is supported, haha

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this error is that a specific version of the Android OS is not supported. It's an error that can be returned from the Library itself, so I just made it forward the error in this case.

if (!data || !data.length) {
console.log('No data passed in. Expects a bitmap.')
return
console.log('No data passed in. Expects a bitmap.');
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we kill this console log please :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, no problem.

if (!data || !data.length) {
console.log('No data passed in. Expects print payload string.')
return
console.log('No data passed in. Expects print payload string.');
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one too, bleh

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will kill this too.

@gordol gordol changed the title Add Bluetooth Support for iOS Add Bluetooth Support for iOS, extend support for Android Sep 13, 2017
}

-(void)findPrinters:(CDVInvokedUrlCommand*)command {
// [self.commandDelegate runInBackground:^{
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did this need to run in the background? did you put in foreground for testing? or does it not work in background?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function is a combination of searching for findNetPrinters and findBluetoothPrinters, the findNetPrinters portion cannot run in a background thread, but the findBluetoothPrinters can.

@gordol
Copy link
Owner

gordol commented Sep 13, 2017

good to hear. i have my ipad charged, but i need to get my xcode environment sorted out... my ipad is running ios8.1 though. do you know if this is only compatible with specific IOS versions?

anyway... looks good. i skimmed the IOS bits... need to brush up on my objc a little, but it looks okay from a high level. proper use of background threads and what-not. however, should pairBluetoothPrinters run in the foreground?

@Ayiga
Copy link
Author

Ayiga commented Sep 13, 2017

I was playing with the Background thread stuff yesterday. Honestly, findNetPrinters on iOS doesn't work unless it's on a foreground thread.

pairBluetoothPrinters just spawns a modal, so it's not actually long running.

findBluetoothPrinters just returns the current list of paired printers on both platforms, so that's not long running either. However, it could be made to run on a background thread on iOS without any issue.

The other thing that is able to run in a background thread is printViaSDK on iOS. Running that in a background thread causes no issues. Although the print operation itself is running in an NSOperationQueue that is using the main thread. That could be tested to see if it has to be in the main queue or not. But, as of now I haven't quite tested that portion.

I looked up the supported iOS versions, it seems to be iOS 6 - iOS 10. It'll probably work on iOS 11, barring any large changes.

@gordol
Copy link
Owner

gordol commented Sep 13, 2017

Good to know, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants