What makes Collect throw "unfortunately stopped" when trying to import a photo via Choose Image?

Hello - newbie alert, please be gentle with me!

I'm trying to understand what causes the "unfortunately has
stopped" error in recent versions of Android (5+?) - and how to stop it
happening with my instance of Collect. My Collect app is slightly
customised, and doesn't use all the latest code, but works nicely on older
Android versions, but it's the nature of the problem that I'm interested
in, not just getting a fix that I don't understand!

So my form has a photo field, which correctly displays the "Take Picture"
and "Choose Image" buttons. Take Picture works fine. Choose Image
displays a bunch of thumbnails corresponding to the latest photos taken
with the Camera app, but when I press on a photo thumbnail to select it,
the app throws the "unfortunately stopped" error. I think that the issue
is with permissions ... do I need to set something in the Manifest file to
enable Collect to access photos from the Camera?

I've run adb logcat and I think this is the relevant bit of the log:

E/AndroidRuntime(17908): FATAL EXCEPTION: main
E/AndroidRuntime(17908): Process: org.odk.collect.android, PID: 17908
E/AndroidRuntime(17908): java.lang.RuntimeException: Failure delivering
result ResultInfo{who=null, request=7, result=-1, data=Intent {
dat=content://com.android.providers.media.documents/document/image:3597
flg=0x1 }} to activity
{org.odk.collect.android/org.odk.collect.android.activities.FormEntryActivity}:
java.lang.NullPointerException: Attempt to invoke virtual method 'char
java.lang.String.toCharArray()' on a null object reference
E/AndroidRuntime(17908): at
android.app.ActivityThread.deliverResults(ActivityThread.java:3574)
E/AndroidRuntime(17908): at
android.app.ActivityThread.handleSendResult(ActivityThread.java:3617)
E/AndroidRuntime(17908): at
android.app.ActivityThread.access$1300(ActivityThread.java:151)
E/AndroidRuntime(17908): at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1352)
E/AndroidRuntime(17908): at
android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime(17908): at android.os.Looper.loop(Looper.java:135)
E/AndroidRuntime(17908): at
android.app.ActivityThread.main(ActivityThread.java:5254)
E/AndroidRuntime(17908): at java.lang.reflect.Method.invoke(Native
Method)
E/AndroidRuntime(17908): at
java.lang.reflect.Method.invoke(Method.java:372)
E/AndroidRuntime(17908): at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)

E/AndroidRuntime(17908): at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
E/AndroidRuntime(17908): Caused by: java.lang.NullPointerException: Attempt
to invoke virtual method 'char java.lang.String.toCharArray()' on a null
object reference
E/AndroidRuntime(17908): at java.io.File.fixSlashes(File.java:185)
E/AndroidRuntime(17908): at java.io.File.(File.java:134)
E/AndroidRuntime(17908): at
org.odk.collect.android.activities.FormEntryActivity.onActivityResult(FormEntryActivity.java:542)

E/AndroidRuntime(17908): at
android.app.Activity.dispatchActivityResult(Activity.java:6192)
E/AndroidRuntime(17908): at
android.app.ActivityThread.deliverResults(ActivityThread.java:3570)
E/AndroidRuntime(17908): ... 10 more
W/ActivityManager( 569): Force finishing activity 1
org.odk.collect.android/.activities.FormEntryActivity

Thanks for any suggestions or enlightenment!

Nik

Hi Nik,

Does your form work with the latest version of Collect? If so, start
comparing the picture taking workflow and manifest files between the
two. The differences there will give you hints into what the problem
might be...

Yaw

··· -- Need ODK consultants? https://nafundi.com provides form design, server setup, in-field training, and software development for ODK.

On Tue, Oct 20, 2015 at 6:15 PM, blitheringeejit holmesnik@googlemail.com wrote:

Hello - newbie alert, please be gentle with me!

I'm trying to understand what causes the "unfortunately has
stopped" error in recent versions of Android (5+?) - and how to stop it
happening with my instance of Collect. My Collect app is slightly
customised, and doesn't use all the latest code, but works nicely on older
Android versions, but it's the nature of the problem that I'm interested in,
not just getting a fix that I don't understand!

So my form has a photo field, which correctly displays the "Take Picture"
and "Choose Image" buttons. Take Picture works fine. Choose Image displays
a bunch of thumbnails corresponding to the latest photos taken with the
Camera app, but when I press on a photo thumbnail to select it, the app
throws the "unfortunately stopped" error. I think that the issue is with
permissions ... do I need to set something in the Manifest file to enable
Collect to access photos from the Camera?

I've run adb logcat and I think this is the relevant bit of the log:

E/AndroidRuntime(17908): FATAL EXCEPTION: main
E/AndroidRuntime(17908): Process: org.odk.collect.android, PID: 17908
E/AndroidRuntime(17908): java.lang.RuntimeException: Failure delivering
result ResultInfo{who=null, request=7, result=-1, data=Intent {
dat=content://com.android.providers.media.documents/document/image:3597
flg=0x1 }} to activity
{org.odk.collect.android/org.odk.collect.android.activities.FormEntryActivity}:
java.lang.NullPointerException: Attempt to invoke virtual method 'char
java.lang.String.toCharArray()' on a null object reference
E/AndroidRuntime(17908): at
android.app.ActivityThread.deliverResults(ActivityThread.java:3574)
E/AndroidRuntime(17908): at
android.app.ActivityThread.handleSendResult(ActivityThread.java:3617)
E/AndroidRuntime(17908): at
android.app.ActivityThread.access$1300(ActivityThread.java:151)
E/AndroidRuntime(17908): at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1352)
E/AndroidRuntime(17908): at
android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime(17908): at android.os.Looper.loop(Looper.java:135)
E/AndroidRuntime(17908): at
android.app.ActivityThread.main(ActivityThread.java:5254)
E/AndroidRuntime(17908): at java.lang.reflect.Method.invoke(Native
Method)
E/AndroidRuntime(17908): at
java.lang.reflect.Method.invoke(Method.java:372)
E/AndroidRuntime(17908): at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
E/AndroidRuntime(17908): at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
E/AndroidRuntime(17908): Caused by: java.lang.NullPointerException: Attempt
to invoke virtual method 'char java.lang.String.toCharArray()' on a null
object reference
E/AndroidRuntime(17908): at java.io.File.fixSlashes(File.java:185)
E/AndroidRuntime(17908): at java.io.File.(File.java:134)
E/AndroidRuntime(17908): at
org.odk.collect.android.activities.FormEntryActivity.onActivityResult(FormEntryActivity.java:542)
E/AndroidRuntime(17908): at
android.app.Activity.dispatchActivityResult(Activity.java:6192)
E/AndroidRuntime(17908): at
android.app.ActivityThread.deliverResults(ActivityThread.java:3570)
E/AndroidRuntime(17908): ... 10 more
W/ActivityManager( 569): Force finishing activity 1
org.odk.collect.android/.activities.FormEntryActivity

Thanks for any suggestions or enlightenment!

Nik

--
You received this message because you are subscribed to the Google Groups
"ODK Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to opendatakit-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Yaw -

Thanks for the pointer - I downloaded the current Collect from the Google
Play Store, but as soon as I try to access my forms server to get the form,
Collect immediately crashes - again with the "Unfortunately" error, even
though the context is different.

My forms server doesn't use Aggregate, it's my own implementation running
on my own server, generating custom XForms. I'm confident that the forms
are OK. My old, customised version of Collect isn't in the Play Store,
because I distribute it directly as an APK for a private service. It's
been working happily with older versions of Android for a couple of years,
but I guess there's something in the new security model which is causing
both issues.

When I install my version of Collect from the APK, it correctly asks me to
authorise access to external storage - but I notice that the latest Collect
explicitly requests access to "Photos/Media Files" - which my version
doesn't. Is that request triggered by a particular element in the Manifest?

Thanks
Nik

Exactly how old is your fork off of ODK Collect?

And, for your fork:

  1. What specific Android OS versions do you KNOW do not work.
  2. And what Android OS versions do you KNOW work.

The Media storage API has changed several times recently, which has
required special logic for operation on Android 4.4.2 and newer devices.

Try copying the forms manually to the device and starting ODK Collect and
exercising the forms.

What happens?

··· ----- w.r.t. the newer ODK Collect.

Your server is likely not entirely OpenRosa compliant -- it either lacks
the OpenRosa version header
https://bitbucket.org/javarosa/javarosa/wiki/OpenRosaRequest or does not
return an OpenRosa xforms structure
https://bitbucket.org/javarosa/javarosa/wiki/FormListAPI. Either of those
could cause the most recent ODK Collect to crash when attempting to
download forms (the development tip (not yet released) now has a code fix
to once again make ODK Collect tolerant of non-compliant servers).

On Tue, Oct 20, 2015 at 8:52 AM, blitheringeejit holmesnik@googlemail.com wrote:

Yaw -

Thanks for the pointer - I downloaded the current Collect from the Google
Play Store, but as soon as I try to access my forms server to get the form,
Collect immediately crashes - again with the "Unfortunately" error, even
though the context is different.

My forms server doesn't use Aggregate, it's my own implementation running
on my own server, generating custom XForms. I'm confident that the forms
are OK. My old, customised version of Collect isn't in the Play Store,
because I distribute it directly as an APK for a private service. It's
been working happily with older versions of Android for a couple of years,
but I guess there's something in the new security model which is causing
both issues.

When I install my version of Collect from the APK, it correctly asks me to
authorise access to external storage - but I notice that the latest Collect
explicitly requests access to "Photos/Media Files" - which my version
doesn't. Is that request triggered by a particular element in the Manifest?

Thanks
Nik

--
You received this message because you are subscribed to the Google Groups
"ODK Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to opendatakit-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
Mitch Sundt
Software Engineer
University of Washington
mitchellsundt@gmail.com

Mitch - thanks for your comments, really helpful.

My working Collect fork is from 1.2.1, contemporary with Android 4.0,
approximately, and the build target is Google APIs 2.3.3. So it's very old

  • but the app needs to work on 2.3.3 (if that's possible), as we still have
    old devices in the field. Maybe I'm being over-optimistic hoping to get
    the same app working on 2.3.3 and 5.1.1...?

The only test devices I have beyond 4.1 are 5.0 and 5.1.1 - these
definitely have this problem. It definitely works OK on 2.3.3. and I have
devices in the field running 4.0 and 4.1 with no reports of problems. So
your comment about 4.4.2+ sounds spot on.

if I load my form manually into the latest Playstore version of Collect,
the Choose Image button works OK.

FYI my fork of the old Collect app and server work fine in all respects
(download/upload forms, GPS grab, signature grab, take photo etc) - apart
from the "Choose Image" button. That's the only problem, which is why I
thought I might resolve it with a single Manifest permission.

Please could you point me to the "special logic" you refer to for the media
storage API? Does this require changes to the app source, or can it be
done with Manifest permissions?

Re OpenRosa compliance - you may be right, but I can fix that serverside
using your links - thankyou. The bigger problem with getting everything up
to date will be me starting a new fork from the latest Collect and making
an Eclipse project out of it - I don't normally work in Java, and it's been
so long since I did the original one that I can't remember how to - doh!

Thanks
Nik

Exactly how old is your fork off of ODK Collect?

And, for your fork:

  1. What specific Android OS versions do you KNOW do not work.

5.1

··· On Tuesday, October 20, 2015 at 5:29:50 PM UTC+1, Mitch wrote:
  1. And what Android OS versions do you KNOW work.

The Media storage API has changed several times recently, which has
required special logic for operation on Android 4.4.2 and newer devices.

Try copying the forms manually to the device and starting ODK Collect and
exercising the forms.

What happens?


w.r.t. the newer ODK Collect.

Your server is likely not entirely OpenRosa compliant -- it either lacks
the OpenRosa version header
https://bitbucket.org/javarosa/javarosa/wiki/OpenRosaRequest
https://www.google.com/url?q=https%3A%2F%2Fbitbucket.org%2Fjavarosa%2Fjavarosa%2Fwiki%2FOpenRosaRequest&sa=D&sntz=1&usg=AFQjCNFq1YVE68039qn2DxWxrATdqQ0lFA
or does not return an OpenRosa xforms structure
https://bitbucket.org/javarosa/javarosa/wiki/FormListAPI. Either of those
could cause the most recent ODK Collect to crash when attempting to
download forms (the development tip (not yet released) now has a code fix
to once again make ODK Collect tolerant of non-compliant servers).

Hi Nik,

If you are using both a custom Collect and a custom server, you are
sort of on your own as far as the support on this mailing list. Your
best approach is to take the individual pieces (e.g. your mobile app
with Aggregate, then Collect with your server) and try to find where
the differences are. And don't just look at how they behave. Look at
the source.

Good luck,

Yaw

··· -- Need ODK consultants? https://nafundi.com provides form design, server setup, in-field training, and software development for ODK.

On Tue, Oct 20, 2015 at 10:52 PM, blitheringeejit holmesnik@googlemail.com wrote:

Yaw -

Thanks for the pointer - I downloaded the current Collect from the Google
Play Store, but as soon as I try to access my forms server to get the form,
Collect immediately crashes - again with the "Unfortunately" error, even
though the context is different.

My forms server doesn't use Aggregate, it's my own implementation running on
my own server, generating custom XForms. I'm confident that the forms are
OK. My old, customised version of Collect isn't in the Play Store, because
I distribute it directly as an APK for a private service. It's been
working happily with older versions of Android for a couple of years, but I
guess there's something in the new security model which is causing both
issues.

When I install my version of Collect from the APK, it correctly asks me to
authorise access to external storage - but I notice that the latest Collect
explicitly requests access to "Photos/Media Files" - which my version
doesn't. Is that request triggered by a particular element in the Manifest?

Thanks
Nik

--
You received this message because you are subscribed to the Google Groups
"ODK Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to opendatakit-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Yaw -

If you are using both a custom Collect and a custom server, you are
sort of on your own as far as the support on this mailing list.

Of course - I was just looking for wisdom on the specific issue of the
Photos/Media/Files permission, and how to request that via the Manifest
file. But it sounds like this simple question has a much more complicated
answer than I was hoping!

Thanks
NIk

The changes were substantial enough that we added a class to hide the
details:

https://github.com/opendatakit/collect/blob/master/collect_app/src/main/java/org/odk/collect/android/utilities/MediaUtils.java

But there are also a lot of other changes to the code to fix the slightly
different timings and behaviors with the newer Android OSes. Somewhere in
the 3.x / 4.x transition, there were changes to how the views and
activities worked, which caused forced-stops. Your old code likely will
have that problem too.

And then there is the migration to Android Studio.

··· On Tue, Oct 20, 2015 at 10:14 AM, blitheringeejit wrote:

Yaw -

If you are using both a custom Collect and a custom server, you are
sort of on your own as far as the support on this mailing list.

Of course - I was just looking for wisdom on the specific issue of the
Photos/Media/Files permission, and how to request that via the Manifest
file. But it sounds like this simple question has a much more complicated
answer than I was hoping!

Thanks
NIk

--
You received this message because you are subscribed to the Google Groups
"ODK Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to opendatakit-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
Mitch Sundt
Software Engineer
University of Washington
mitchellsundt@gmail.com

Mitch - appreciate your comments, thanks.

Given the changes you mention, does the current Collect APK work on all
Android versions from 2.3.3 to 5.1.1 and beyond, in theory?

Kind regards
Nik

··· On Tuesday, October 20, 2015 at 6:28:25 PM UTC+1, Mitch wrote: > > The changes were substantial enough that we added a class to hide the > details: > > > https://github.com/opendatakit/collect/blob/master/collect_app/src/main/java/org/odk/collect/android/utilities/MediaUtils.java > > But there are also a lot of other changes to the code to fix the slightly > different timings and behaviors with the newer Android OSes. Somewhere in > the 3.x / 4.x transition, there were changes to how the views and > activities worked, which caused forced-stops. Your old code likely will > have that problem too. >

And then there is the migration to Android Studio.

ODK Collect 1.4.6 and onward support Android 2.2 and later
ODK Collect 1.4.5 supports Android 2.1
ODK Collect 1.1.7 supports Android 1.8 - 2.0.1

Our intention is to maintain the tip so that it works with all non-obsolete
Android OS levels (as indicated by the Android SDK's SDK Manager UI at the
time the ODK Collect APK is built).

Since the vast majority of large deployments do not install their software
via Google Play, we rely heavily on users reporting problems on opendatakit@
to notify us of broken functionality with the newer Android OS releases.

We simply cannot test all devices and all OS releases.

-----interesting factoids....

When users install ODK Collect via Google Play, and it crashes, they can
choose to send us a crash report. You might think that those crash reports
would be useful, given that ODK Collect is nearing the 100,000 active
installs mark (again, just via Google Play -- there are many more installs
out there). Unfortunately, it isn't.

For the 1.4.7 release (released Sept 2 on Google Play), over the last 30
days, we have a grand total of only 70 crash reports -- 21 crash reports on
9 different errors relating to out-of-memory issues (i.e. forms to big;
exceeding the SD card storage), and 49 crash reports on 19 errors relating
to connectivity or other application issues (and 4 of those errors (18
crash reports) are directly related to the force-close that you saw when
attempting to download from your server).

··· On Tue, Oct 20, 2015 at 3:07 PM, blitheringeejit wrote:

Mitch - appreciate your comments, thanks.

Given the changes you mention, does the current Collect APK work on all
Android versions from 2.3.3 to 5.1.1 and beyond, in theory?

Kind regards
Nik

On Tuesday, October 20, 2015 at 6:28:25 PM UTC+1, Mitch wrote:

The changes were substantial enough that we added a class to hide the
details:

https://github.com/opendatakit/collect/blob/master/collect_app/src/main/java/org/odk/collect/android/utilities/MediaUtils.java

But there are also a lot of other changes to the code to fix the slightly
different timings and behaviors with the newer Android OSes. Somewhere in
the 3.x / 4.x transition, there were changes to how the views and
activities worked, which caused forced-stops. Your old code likely will
have that problem too.

And then there is the migration to Android Studio.

--
You received this message because you are subscribed to the Google Groups
"ODK Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to opendatakit-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
Mitch Sundt
Software Engineer
University of Washington
mitchellsundt@gmail.com

Mitch - interesting info, your Collect crash stats and back-compatibility
are impressive!

On a more boring note - as you pointed out, the migration to Android Studio
is far from trivial, and I realise that it's quite recent - do you know of
any newbie walkthroughs for getting Collect built using it? I note your
addition of a Readme, which says that the project "depends upon the
gradle-config and google-play-services projects" - but you don't describe
how to build a dev environment which includes these dependencies. It's
especially inscrutable for those like me who are not already familiar with
git, gradle etc.

Has anyone else written a basic end-to-end howto for this?

And if not, would the group trade me some step-by-step guidance on the
promise that I'll write it up as a complete walkthrough and post it back
here? :slight_smile:

Thanks
Nik

We just have the README.

Create an 'odk' directory then check out the 3 projects into
sub-directories under that, each with the name of the corresponding git
repo, as laid out in the graphic in the README.

The critical thing is to git checkout the appropriate tag version of
gradle-config. As we change our build and archive environment, we make
revisions to a common set of build scripts (gradle-config project). Each
APK is built against a specific tag version of those scripts. We are
updating these build scripts a lot as we become more familiar with gradle,
AndroidStudio and artifactory and their arious limitations.

··· On Wed, Oct 21, 2015 at 3:34 AM, blitheringeejit wrote:

Mitch - interesting info, your Collect crash stats and back-compatibility
are impressive!

On a more boring note - as you pointed out, the migration to Android
Studio is far from trivial, and I realise that it's quite recent - do you
know of any newbie walkthroughs for getting Collect built using it? I note
your addition of a Readme, which says that the project "depends upon the
gradle-config and google-play-services projects" - but you don't describe
how to build a dev environment which includes these dependencies. It's
especially inscrutable for those like me who are not already familiar with
git, gradle etc.

Has anyone else written a basic end-to-end howto for this?

And if not, would the group trade me some step-by-step guidance on the
promise that I'll write it up as a complete walkthrough and post it back
here? :slight_smile:

Thanks
Nik

--
You received this message because you are subscribed to the Google Groups
"ODK Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to opendatakit-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
Mitch Sundt
Software Engineer
University of Washington
mitchellsundt@gmail.com