Uploaded image for project: 'Apache Cordova'
  1. Apache Cordova
  2. CB-10496

Contacts plugin on Android can't handle photos provided as base64

    Details

      Description

      Missing documentation on how to set a new contact photo when creating an contact via plugin.

      I am trying to create a contact (works fine) but have no idea how to provide a new picture (uploaded) to it.

      Tried to set "photos[0].value" to an base64 encoded picture .. but it is not displayed in contact.

        Issue Links

          Activity

          Hide
          ArneCoder Arne added a comment -

          Found an "bug" in Cordova Contacts Plugin:

          platforms/android/src/org/apache/cordova/contacts/ContactAccessorSdk5.java
          private InputStream getPathFromUri(String path) throws IOException

          Missing function to handle the base64 stuff! If i add:

          if (path.startsWith("data:")) {
          String dataInfos = path.substring(0, path.indexOf(','));
          dataInfos = dataInfos.substring(dataInfos.indexOf(':') + 1);
          String baseEncoding = dataInfos.substring(dataInfos.indexOf(';') + 1);
          if("base64".equalsIgnoreCase(baseEncoding))

          { String img = path.substring(path.indexOf(',') + 1); byte[] encodedData = img.getBytes(); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(encodedData, 0, encodedData.length); Base64InputStream base64InputStream = new Base64InputStream(byteArrayInputStream, Base64.DEFAULT); return base64InputStream; }

          else

          { Log.w(LOG_TAG, "Could not decode image. Encoding is " + baseEncoding); }

          }

          it works fine

          Show
          ArneCoder Arne added a comment - Found an "bug" in Cordova Contacts Plugin: platforms/android/src/org/apache/cordova/contacts/ContactAccessorSdk5.java private InputStream getPathFromUri(String path) throws IOException Missing function to handle the base64 stuff! If i add: if (path.startsWith("data:")) { String dataInfos = path.substring(0, path.indexOf(',')); dataInfos = dataInfos.substring(dataInfos.indexOf(':') + 1); String baseEncoding = dataInfos.substring(dataInfos.indexOf(';') + 1); if("base64".equalsIgnoreCase(baseEncoding)) { String img = path.substring(path.indexOf(',') + 1); byte[] encodedData = img.getBytes(); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(encodedData, 0, encodedData.length); Base64InputStream base64InputStream = new Base64InputStream(byteArrayInputStream, Base64.DEFAULT); return base64InputStream; } else { Log.w(LOG_TAG, "Could not decode image. Encoding is " + baseEncoding); } } it works fine
          Hide
          githubbot ASF GitHub Bot added a comment -

          Github user filmaj commented on the issue:

          https://github.com/apache/cordova-plugin-contacts/pull/142

          It looks like a JIRA issue is filed for this already: https://issues.apache.org/jira/browse/CB-10496

          Show
          githubbot ASF GitHub Bot added a comment - Github user filmaj commented on the issue: https://github.com/apache/cordova-plugin-contacts/pull/142 It looks like a JIRA issue is filed for this already: https://issues.apache.org/jira/browse/CB-10496
          Hide
          filmaj Filip Maj added a comment -

          There was some other discussion on the phonegap group related to this: https://groups.google.com/forum/#!msg/phonegap/jTMu9Azjaa8/ywQMMEcoS1YJ

          Show
          filmaj Filip Maj added a comment - There was some other discussion on the phonegap group related to this: https://groups.google.com/forum/#!msg/phonegap/jTMu9Azjaa8/ywQMMEcoS1YJ
          Hide
          filmaj Filip Maj added a comment -

          I can confirm that on iOS 10.2 on an iPhone 5S, the following code correctly shows the contact image in the native contacts viewer when a contact is created using the Contacts API:

          var contact = navigator.contacts.create({"displayName": "Test User"});
          var name = new ContactName();
          name.givenName = "Jane";
          name.familyName = "Doe";
          contact.name = name;
          var photos = [];
          photos[0] = new ContactField('base64', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==', false);
          contact.photos = photos;
          contact.save(function() {
              alert('we saved the freaking contact');
          }, function(err) {
              alert('there was an error saving contact!');
              alert(err);
          });
          

          On Android, this same code does not add a photo and can confirm this stack trace from logcat:

          E/ContactsAccessor( 2821): java.io.FileNotFoundException: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4/8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==: open failed: ENOENT (No such file or directory)
          E/ContactsAccessor( 2821): 	at libcore.io.IoBridge.open(IoBridge.java:456)
          E/ContactsAccessor( 2821): 	at java.io.FileInputStream.<init>(FileInputStream.java:76)
          E/ContactsAccessor( 2821): 	at java.io.FileInputStream.<init>(FileInputStream.java:103)
          E/ContactsAccessor( 2821): 	at org.apache.cordova.contacts.ContactAccessorSdk5.getPathFromUri(ContactAccessorSdk5.java:1705)
          E/ContactsAccessor( 2821): 	at org.apache.cordova.contacts.ContactAccessorSdk5.getPhotoBytes(ContactAccessorSdk5.java:1665)
          E/ContactsAccessor( 2821): 	at org.apache.cordova.contacts.ContactAccessorSdk5.insertPhoto(ContactAccessorSdk5.java:1643)
          E/ContactsAccessor( 2821): 	at org.apache.cordova.contacts.ContactAccessorSdk5.createNewContact(ContactAccessorSdk5.java:1866)
          E/ContactsAccessor( 2821): 	at org.apache.cordova.contacts.ContactAccessorSdk5.save(ContactAccessorSdk5.java:1044)
          E/ContactsAccessor( 2821): 	at org.apache.cordova.contacts.ContactManager$2.run(ContactManager.java:186)
          E/ContactsAccessor( 2821): 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
          E/ContactsAccessor( 2821): 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
          E/ContactsAccessor( 2821): 	at java.lang.Thread.run(Thread.java:818)
          
          Show
          filmaj Filip Maj added a comment - I can confirm that on iOS 10.2 on an iPhone 5S, the following code correctly shows the contact image in the native contacts viewer when a contact is created using the Contacts API: var contact = navigator.contacts.create({"displayName": "Test User"}); var name = new ContactName(); name.givenName = "Jane"; name.familyName = "Doe"; contact.name = name; var photos = []; photos[0] = new ContactField('base64', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==', false); contact.photos = photos; contact.save(function() { alert('we saved the freaking contact'); }, function(err) { alert('there was an error saving contact!'); alert(err); }); On Android, this same code does not add a photo and can confirm this stack trace from logcat: E/ContactsAccessor( 2821): java.io.FileNotFoundException: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4/8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==: open failed: ENOENT (No such file or directory) E/ContactsAccessor( 2821): at libcore.io.IoBridge.open(IoBridge.java:456) E/ContactsAccessor( 2821): at java.io.FileInputStream.<init>(FileInputStream.java:76) E/ContactsAccessor( 2821): at java.io.FileInputStream.<init>(FileInputStream.java:103) E/ContactsAccessor( 2821): at org.apache.cordova.contacts.ContactAccessorSdk5.getPathFromUri(ContactAccessorSdk5.java:1705) E/ContactsAccessor( 2821): at org.apache.cordova.contacts.ContactAccessorSdk5.getPhotoBytes(ContactAccessorSdk5.java:1665) E/ContactsAccessor( 2821): at org.apache.cordova.contacts.ContactAccessorSdk5.insertPhoto(ContactAccessorSdk5.java:1643) E/ContactsAccessor( 2821): at org.apache.cordova.contacts.ContactAccessorSdk5.createNewContact(ContactAccessorSdk5.java:1866) E/ContactsAccessor( 2821): at org.apache.cordova.contacts.ContactAccessorSdk5.save(ContactAccessorSdk5.java:1044) E/ContactsAccessor( 2821): at org.apache.cordova.contacts.ContactManager$2.run(ContactManager.java:186) E/ContactsAccessor( 2821): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) E/ContactsAccessor( 2821): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) E/ContactsAccessor( 2821): at java.lang.Thread.run(Thread.java:818)
          Hide
          filmaj Filip Maj added a comment -

          Confirmed that the code in the linked-to pull request indeed fixes the issue.

          Show
          filmaj Filip Maj added a comment - Confirmed that the code in the linked-to pull request indeed fixes the issue.
          Hide
          filmaj Filip Maj added a comment -

          Ping Joe Bowser. I think we should merge this in. I recall testing the PR on Android 5.1 and it fixed the issue. We should test on Android 6/7 but I think it's a worthwhile patch.

          Show
          filmaj Filip Maj added a comment - Ping Joe Bowser . I think we should merge this in. I recall testing the PR on Android 5.1 and it fixed the issue. We should test on Android 6/7 but I think it's a worthwhile patch.
          Hide
          filmaj Filip Maj added a comment -

          Got Joe approval. Moving ahead with this one.

          Show
          filmaj Filip Maj added a comment - Got Joe approval. Moving ahead with this one.
          Show
          filmaj Filip Maj added a comment - Fixed in https://github.com/apache/cordova-plugin-contacts/commit/9d71756e2c6ee243d54eb2c5724c0b0c51dce369

            People

            • Assignee:
              filmaj Filip Maj
              Reporter:
              ArneCoder Arne
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development