NativeScript / nativescript-background-http

Background Upload plugin for the NativeScript framework
Apache License 2.0
102 stars 50 forks source link

App crashes while uploading image - android.app.RemoveServiceException: can't deliver broadcast #89

Closed NickIliev closed 6 years ago

NickIliev commented 6 years ago

From @neddinn on November 28, 2017 7:32

Tell us about the problem

The app crashes when trying to upload an image. Error:

System.err: java.lang.RuntimeException: Error receiving broadcast Intent { act=net.gotev.uploadservice.broadcast.status flg=0x10 (has extras) } in com.tns.gen.net.gotev.uploadservice.UploadServiceBroadcastReceiver_ftns_modules_nativescript-background-http_background-http_l9_c79__@4255a258
System.err:     at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:782)
System.err:     at android.os.Handler.handleCallback(Handler.java:733)
System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)
System.err:     at android.os.Looper.loop(Looper.java:146)
System.err:     at android.app.ActivityThread.main(ActivityThread.java:5602)
System.err:     at java.lang.reflect.Method.invokeNative(Native Method)
System.err:     at java.lang.reflect.Method.invoke(Method.java:515)
System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
System.err:     at dalvik.system.NativeStart.main(Native Method)
System.err: Caused by: com.tns.NativeScriptException: Cannot find object id for instance=com.tns.gen.net.gotev.uploadservice.UploadServiceBroadcastReceiver_ftns_modules_nativescript-background-http_background-http_l9_c79__@4255a258
System.err:     at com.tns.Runtime.callJSMethodImpl(Runtime.java:959)
System.err:     at com.tns.Runtime.callJSMethod(Runtime.java:953)
System.err:     at com.tns.Runtime.callJSMethod(Runtime.java:937)
System.err:     at com.tns.Runtime.callJSMethod(Runtime.java:929)
System.err:     at com.tns.gen.net.gotev.uploadservice.UploadServiceBroadcastReceiver_ftns_modules_nativescript-background-http_background-http_l9_c79__.onProgress(net.gotev.uploadservice.UploadServiceBroadcastReceiver.java)
System.err:     at net.gotev.uploadservice.UploadServiceBroadcastReceiver.onReceive(UploadServiceBroadcastReceiver.java:40)
System.err:     at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:772)
System.err:     ... 9 more
ActivityManager: Process org.nativescript.fo3mobilenativescript (pid 27172) (adj 0) has died.

Which platform(s) does your issue occur on?

Android

Please provide the following version numbers that your issue occurs with:

I'm using nativescript-background-http v3.0.0 & tns-core-modules v3.3.0

Please tell us how to recreate the issue in as much detail as possible.

This error is quite erratic but it mostly doesn't work, after taking a photo using camera plugin and saving or even selecting an image from the gallery, when I try to upload, it crashes the application and throws the aforementioned error.

Is there code involved? If so, please share the minimal amount of code needed to recreate the problem.

    var camera = require('nativescript-camera');
    var fs = require('file-system');
    var imageSource = require('image-source');
    var bghttp = require('nativescript-background-http');
    var session = bghttp.session('image-upload');

    camera.takePicture()
      .then(function (imageAsset) {
        var hash = (new Date()).getTime() + Math.floor(Math.random() * 20);
        let folder = fs.knownFolders.documents();
        let path = fs.path.join(folder.path, `Test-${hash}.png`);
        return imageSource.fromAsset(imageAsset)
          .then(function (res) {
            res.saveToFile(path, 'png');            
            var request = {
              url: "http://httpbin.org/post",
              method: "POST",
              headers: {
                "Content-Type": "application/octet-stream",
                "File-Name": 'randomName'
              },
              description: "{ 'uploading': " + 'randomName' + " }"
            };
            var task = session.uploadFile(path, request);

            task.on("progress", logEvent);
            task.on("error", logEvent);
            task.on("complete", logEvent);

            function logEvent(e) {
              console.log("currentBytes: " + e.currentBytes);
              console.log("totalBytes: " + e.totalBytes);
              console.log("eventName: " + e.eventName);
            }

            return {};
          });
      }).catch(function (err) {
        console.log(`Error -> ${err.message}`);
      });

Copied from original issue: NativeScript/NativeScript#5098

NickIliev commented 6 years ago

@neddinn I was able to fully reproduce the issue and it seems related to nativescript-background-http and the way it broadcasts large data - it also appears only on devices running Android 7.1+.

Moving this issue to nativescript-background-http repository.

Steps to reproduce: - use this sample application on a device with Android 7.1 or greater (reproducible on Nexus 5x a.k.a. bullhead)

Error received:

System err: android.app.RemvoeServiceException: can't deliver broadcast
lini commented 6 years ago

Issue traced back to the android-upload-service library used in the plugin. It happens because the test service https://httpbin.com/post responds with the contents of the uploaded file. If the contents are big enough, the native library will produce an exception.

To avoid this, please use another testing service that does not return the uploaded file in the response.

An issue has been logged in the native library repo - https://github.com/gotev/android-upload-service/issues/342

neddinn commented 6 years ago

@lini Not so sure this is the issue. I am trying to upload files to Amazon S3 (which doesnt return the contents of the uploaded file), and I still encounter this error.

geoffbullen commented 6 years ago

I get this too and I am not using httpbin. The service I upload to, just returns a lil bit of JSON...

lini commented 6 years ago

Hi, Can you share some more details so we can try to reproduce the error - what plugin and android versions are you using? Can you provide us with sample code/test service URL so we can make some requests? Do you get the same exception as in the original issue description and if not, can you share the log output?

geoffbullen commented 6 years ago

@lini I ended up getting past this issue by setting the large heap flag in the android manifest.

android:largeHeap="true"

tbozhikov commented 6 years ago

Thanks for the provided solution. I am closing this issue, feel free to reopen if the problem persists.

ppyoosuf commented 4 years ago

Getting this issue even set the android:largeHeap="true"

juanbonoso commented 4 years ago

I am having the same problem. Not Sure why sometimes is happening, and why sometimes it works as expected. Screenshot_1584465867

I just realize that the problems comes when converting to JSON :

function respondedHandler(e) { console.log('respondedHandler received ' + e.responseCode + ' code. Server sent: ' + e.data); set_mark_time(JSON.parse(e.data)); }

sirajahmad1 commented 3 years ago

Any update on this I'm having the same issue Screenshot_1607358695

overbost commented 3 years ago

I solved this issue by move some logic outside the onComplete() function. Seem you must create single instruction to lighten the calculations. For example you must save in let or const your JSON.parse(), because as argument the single calculation is too heavy.

My working code:

        this.$photoService.pickPhoto({ width:800, height: 800, lockSquare: false }, (file_path)=>{
        this.waiter.start()
        this.$store.commit('set_waiter', {prop: "progress", value: this.t("LOADING.PROGRESS_UPLOAD_IMAGE")})

        let query = new Object({ company: this.$store.state.company_selected._key});
        if(this.is_draft) query["draft"] = this.feed._key
        else query["post"] = this.feed._key

        let url = Array.from(this.$rawApi.POST_POST_PHOTO);
        url[1] = this.$rawApi.getURL(url[1], query)

        this.$rawApi.uploadImage(url, file_path,
          // onProgress
          (e)=>{
            let perc:number = ~~(parseFloat(e.currentBytes) * 100 / parseFloat(e.totalBytes))
            this.$store.commit('set_waiter', {prop: "progress", value: perc.toString() + " %"})
            //self.progress ="progress.."
          },
          //onError
          (e)=>{
          },
          //onComplete
          (e)=>{
              const json = JSON.parse(e.response.getBodyAsString());
              let post = new Post(json.post);
              this.feed = post;
              this.$store.dispatch("updatePost", {post:post, is_draft:this.is_draft});
              this.edit_mode = false;
          }
        )
      })
    },