Kotlin Fuel download takes long time to connect - kotlin-fuel

Using Fuel 2.0.1 in Android Studio with Kotlin 1.3.31.
My Fuel download request looks as follows
Log.i("tag","connecting")
Fuel.download(uri).fileDestination { response, url ->
File(filesDir,filename)
}.progress { readBytes, totalBytes ->
Log.i("tag","downloading")
}.response { req, res, result ->
Log.i("tag","download complete")
}
There is about 5-7 seconds delay between the connecting and downloading logs.
I tried putting the url into the browser on the same device and it starts downloading instantly.
I also tried other servers but the lag is the same.
What am I doing wrong?

Did you solve this issue? I am experiencing the same and have stopped using Fuel because of this. Instead of using Fuel to download a file I'm doing it this way:
val url = "https://www.abcde.com/fghij/filename.apk"
val filename = "filename.apk"
URL(url + filename).openStream().use { input ->
FileOutputStream(File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), filename)).use { output ->
input.copyTo(output)
}
}

Related

How do i send an intent via react native to Print Connect zebra app

I am currently trying to communicate with a Zebra printer via a react-native application, on mobile I am trying to send my ZPL code (instructions for the printer to print the content i want) from my application to the printer via PrintConnect, Zebra also provides a pdf file guiding people on how to communicate to the app via intents available here however the examples dislpayed on the guide are using a different language.
My question then is how would i go about replicating this (Page 96, Passthrough Intent example) :
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.zebra.printconnect",
"com.zebra.printconnect.print.PassthroughService"));
intent.putExtra("com.zebra.printconnect.PrintService.PASSTHROUGH_DATA", passthroughBytes);
intent.putExtra("com.zebra.printconnect.PrintService.RESULT_RECEIVER", buildIPCSafeReceiver(new
ResultReceiver(null) {
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
if (resultCode == 0) { // Result code 0 indicates success
// Handle successful print
} else {
// Handle unsuccessful print
// Error message (null on successful print)
String errorMessage = resultData.getString("com.zebra.printconnect.PrintService.ERROR_MESSAGE");
}
}
}));
Into something acceptable by the react-native-send-intent package such as this:
SendIntentAndroid.openApp("com.mycorp.myapp", {
"com.mycorp.myapp.reason": "just because",
"com.mycorp.myapp.data": "must be a string",
}).then(wasOpened => {});
Thank you for the time you took to read my question.

Spring Webflux : using flatmap + Mono for downloading google cloud storage Blob or just map?

I want to get a bunch of pictures in a google bucket and convert it to base64 using a webflux project.
public Flux<String> getImages() {
final Storage storage = StorageOptions.newBuilder().setProjectId(PROJECT_ID).build().getService();
Page<Blob> blobs = storage.list(BUCKET_NAME);
long startMillis = System.currentTimeMillis();
return
Flux.fromIterable(blobs.iterateAll())
.parallel()
.runOn(Schedulers.boundedElastic())
.map(blob -> blob.getContent(BlobSourceOption.generationMatch())) //blocking ? http request to google storage (returns byte[])
.map(PhotoUtils::processBytesToBase64) //non blocking
.sequential()
.doOnTerminate(() -> LOGGER.info("ELAPSED {}", System.currentTimeMillis() - startMillis));}
It works. I use Blockhound to check for blocking and nothing is detected. But I read several times that any IO operations (as blob.getContent() is) should be wrapped in a flatmap. So it would be something like :
...
return
Flux.fromIterable(blobs.iterateAll())
.parallel()
.runOn(Schedulers.boundedElastic())
.flatMap(blob -> Mono.just(blob.getContent(BlobSourceOption.generationMatch())))
.map(PhotoUtils::processBytesToBase64)
.sequential()
.doOnTerminate(() -> LOGGER.info("ELAPSED {}", System.currentTimeMillis() - startMillis));}
But I feel it redundant.
Which one is the most correct or am I totally missing the point ?

How to replace blocking code for reading bytes in Kotlin

I have ktor application which expects file from multipart in code like this:
multipart.forEachPart { part ->
when (part) {
is PartData.FileItem -> {
image = part.streamProvider().readAllBytes()
}
else -> // irrelevant
}
}
The Intellij IDEA marks readAllBytes() as inappropriate blocking call since ktor operates on top of coroutines. How to replace this blocking call to the appropriate one?
Given the reputation of Ktor as a non-blocking, suspending IO framework, I was surprised that apparently for FileItem there is nothing else but the blocking InputStream API to retrieve it. Given that, your only option seems to be delegating to the IO dispatcher:
image = withContext(Dispatchers.IO) { part.streamProvider().readBytes() }

Spring WebFlux Webclient receiving an application/octet-stream file as a Mono

I'm prototyping a small Spring WebFlux application in Kotlin. This application needs to GET a tar archive from a remote REST endpoint and store it locally on disk. Sounds simple.
I first created an integration test that starts the spring server and one other WebFlux server with a mock REST endpoint that serves the tar archive.
The test should go like:
1) app: GET mock-server/archive
2) mock-server: response with status 200 and tar archive in body as type attachment
3) app: block until all bytes received, then untar and use files
The problem I'm having is that when I try and collect the bytes into a ByteArray on the app, it blocks forever.
My mock-server/archive routes to the following function:
fun serveArchive(request: ServerRequest): Mono<ServerResponse> {
val tarFile = FileSystemResource(ARCHIVE_PATH)
assert(tarFile.exists() && tarFile.isFile && tarFile.contentLength() != 0L)
return ServerResponse
.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.contentLength(tarFile.contentLength())
.header("Content-Disposition", "attachment; filename=\"$ARCHIVE_FNAME\"")
.body(fromResource(tarFile))
}
Then my app calls that with the following:
private fun retrieveArchive {
client.get().uri(ARCHIVE_URL).accept(MediaType.APPLICATION_OCTET_STREAM)
.exchange()
.flatMap { response ->
storeArchive(response.bodyToMono())
}.subscribe()
}
private fun storeArchive(archive: Mono<ByteArrayResource>): Mono<Void> {
val archiveContentBytes = archive.block() // <- this blocks forever
val archiveContents = TarArchiveInputStream(archiveContentBytes.inputStream)
// read archive
}
I've see How to best get a byte array from a ClientResponse from Spring WebClient? and that's why I'm trying to use the ByteArrayResource.
When I step through everything, I see that serveArchive seems to be working (the assert statement says the file I'm passing exists and there are some bytes in it). In retrieveArchive I get a 200 and can see all the appropriate information in the .headers (content-type, content-length all look good). When I get down to storeArchive and try to retrieve the bytes from the Mono using block, it simply blocks forever.
I'm at a complete loss of how to debug something like this.
You just have to return the converted body from the flatMap so it transforms from Mono<T> to T:
client.get().uri(ARCHIVE_URL).accept(MediaType.APPLICATION_OCTET_STREAM)
.exchange()
.flatMap { response ->
response.bodyToMono(ByteArrayResource::class.java)
}
.map { archiveContentBytes ->
archiveContentBytes.inputStream
}
.doOnSuccess { inputStream ->
//here is you code to do anything with the inputStream
val archiveContents = TarArchiveInputStream(inputStream)
}
.subscribe()

Having Trouble Getting the UIDocumentBrowserController to open docs in a Document based app

I've been working on a new Document-based app, and was super glad about the new UIDocumentBrowserController...trying to roll my own solution for the document browser UI was tricky!
I'm having some trouble getting the browser to open documents after they've been created.
What happens now is that when I choose to create a new document in the document browser, the document is created and opened as expected, although an error message is logged. However, after the doc is closed, I cannot reopen the file, either immediately or upon subsequent launches, even though the document is displayed. However, a weird clue here is that if I stop running the app after creating the document, but without adding new information to it (triggering the save cycle), and run the project again, I can open the file correctly. Whuch makes me think that there's something in the way the files are being saved that is the issue.
(Note: At this phase, I'm working on getting the local, non/icloud implentation working, before I move on to the icloud implementation.)
Here is the error message at any point in the code whenthe document is saved to disk (or at least most of the time!):
2017-06-20 13:21:58.254938-0500 Sermon Design 2 iOS[22454:5000138] [default] [ERROR] Could not get attribute values for item file:///Users/stevenhovater/Library/Developer/CoreSimulator/Devices/9A4364F2-B3A1-4AD9-B680-FB4BC876C707/data/Containers/Data/Application/DD534ED8-C4A3-40FE-9777-AED961976878/Documents/Untitled-9.sermon. Error: Error Domain=NSFileProviderInternalErrorDomain Code=1 "The reader is not permitted to access the URL." UserInfo={NSLocalizedDescription=The reader is not permitted to access the URL.}
I suspect that the issue lies somewher in my document types plists, which I've tried to set up by imitating the setup in the video for wwdc 2017 session 229.
My docs are encapuslated by an NSData object, using what I take to be a pretty standard subclass implentation of UIDocument. (I'm omitting the code to generate the thumbnails)
override func contents(forType typeName: String) throws -> Any {
print("Saving Document Changes")
if sermon != nil {
let newData = NSKeyedArchiver.archivedData(withRootObject: sermon!)
return newData
} else {
let newData = NSKeyedArchiver.archivedData(withRootObject: Sermon())
return newData
}
}
override func fileAttributesToWrite(to url: URL, for saveOperation: UIDocumentSaveOperation) throws -> [AnyHashable : Any] {
let thumbnail:UIImage = self.createThumbnail()
let thumbnaildict = [URLThumbnailDictionaryItem.NSThumbnail1024x1024SizeKey : thumbnail]
let dict = [URLResourceKey.thumbnailDictionaryKey:thumbnaildict]
return dict
}
override func load(fromContents contents: Any, ofType typeName: String?) throws {
guard let newSermon:Sermon = NSKeyedUnarchiver.unarchiveObject(with: contents as! Data) as? Sermon else{
throw documentErrors.invalidFile
}
self.sermon = newSermon
}
In my subclass of UIDocumentBrowserViewController, Here is my code for getting a local filename and for creating the new document.
func documentBrowser(_ controller: UIDocumentBrowserViewController, didRequestDocumentCreationWithHandler importHandler: #escaping (URL?, UIDocumentBrowserViewController.ImportMode) -> Void) {
var newDocumentURL: URL? = nil
print("creating new local document")
guard let target = self.newLocalFilename() else {
return
}
let targetSuffix = target.lastPathComponent
let tempURL = URL(fileURLWithPath: NSTemporaryDirectory() + targetSuffix)
let newDocument:SDDocument = SDDocument(fileURL: tempURL)
newDocument.sermon = Sermon()
/
newDocument.save(to: tempURL, for: .forCreating) { (saveSuccess) in
/
guard saveSuccess else {
/
importHandler(nil, .none)
return
}
/
newDocument.close(completionHandler: { (closeSuccess) in
/
guard closeSuccess else {
/
importHandler(nil, .none)
return
}
/
importHandler(tempURL, .move)
})
}
}
func newLocalFilename() -> URL? {
let fileManager = FileManager()
guard let baseURL = self.localDocumentsDirectoryURL.appendingPathComponent("Untitled")
else {return nil}
var target = baseURL.appendingPathExtension(DocumentBrowserViewController.documentExtension)
var nameSuffix = 2
while fileManager.fileExists(atPath: target.path) {
target = URL(fileURLWithPath: baseURL.path + "-\(nameSuffix).\(DocumentBrowserViewController.documentExtension)")
nameSuffix += 1
}
let targetSuffix = target.lastPathComponent
print("Target name: \(targetSuffix)")
print("new url: \(target)")
return target
}
After four or five hours of work banging my head against this problem, I discovered a simple solution: don't test in the Simulator. I switched to testing on my device and instantly everything started working as advertised.
[I can't speak from experience here, but it may be that the "doesn't work in the Simulator" problem is confined to Sierra, but that the Simulator does work in High Sierra. This would explain why some users see this issue and others don't, and especially why Apple seems blissfully unaware of it in the WWDC video.]
I had exactly the same issue when I was trying to save to NSTemporaryDirectory().
If you instead save to the documents directory ([[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject]), it appears to work fine!
Update: it looks like this issue is fixed in iOS 11 beta 3, and you can now save newly created documents to NSTemporaryDirectory() correctly.
Here is my current theory.
This error
Error Domain=NSFileProviderInternalErrorDomain Code=1 "The reader is not permitted to access the URL."
shows up when first creating a UIDocument at a new URL using -initWithFileURL. It's basically saying "this URL doesn't exist yet," but in a way that makes it sound more like a permissions issue.
As far as I can tell, it doesn't prevent you from saving, opening, editing, or closing the file. So I think it's just a superfluous error that Apple should have taken out.
I found that the error happens on simulator when LSSupportsOpeningDocumentsInPlace property is set to YES in the info.plist.
Turn this property to NO, then it starts working, in my case.
On the real device, it works anyway without having error.
Had similar problem, and tried the method for providing a default Core Location in the Schemes settings and it works now. The method was mentioned in this answer: IOS 9 Error Domain=kCLErrorDomain Code=0 "(null)"