I've blogged about this topic almost more than 3 years ago how I used a couple of drupal modules to send mails with images from my iPhone which automatically got posted to my site. But times change. I now own a Nexus One and one of my goals for 2012 is to write at least one decent mobile application. I experimented with Titanium first, but decided to go native for a couple of reasons, performance and size of app being the main reasons.
While I already have an official go for an application I can develop, I started with a simple use case to learn android application development: uploading images to my personal blog saving a new node. Especially the java part is as good as new to me, so starting simple is always the best advice. After 3 hours of Drupal hacking and a lot more Java reading and debugging, my first application is happily working on my own phone and I have cute Druplicon on my desktop.
The code is freely available (see below) consisting of 2 parts.
The Android part
The application is build at SDK version 10, so it should work on any Android 2.3 or higher. It might possibly work on lower versions as well. After installation of the application and the first run on your telephone, you will need to login. The app authenticates with a Drupal user and only stores the endpoint URL and the session cookie. The session cookie is send when uploading an image so we know exactly who's uploading. Besides selecting from the app, you can also go to your Image gallery, select an image and use the Share menu to drop the image to the application.
The layout of the application as the code is relatively simple, it probably doesn't follow the best practices of Java programming, so be gentle in case you start reviewing, I'm still learning :)
The Drupal part
The Drupal module - D7 only - is simple as well, but was less hard to develop. While I could 've used a combination of services and other modules, I decided to write a simple module with a single menu callback that accepts a request that can either authenticate a user or create a node with title, image and other keys. Once enabled, you need to go to 'admin/config/media/drupapp' and start configure following items:
- The endpoint. Defaults to 'drupapp', but you can change this to your likings.
- The image field name: this will immediately select the content type that will be used to save the node.
- Published status: default status, handy if you want to review after upload.
- Debug option: log the complete $_POST variable through watchdog for testing purposes.
You will need to grant permission on the permissions page as well. Best practice is to create a new role which only has the "upload images via app" permission, and that role does not necessarily need a permission to create nodes.
Combine the 2 technologies and you get Drupoid. What's in name right ? You can browse, fork and/or download the code at http://github.com/swentel/Drupoid. Feel free to modify it to your own needs. The app in its current version will never be made available on the Android market as it's really a personal project. But it might serve as a nice start example for your own adventures in mobile application land.
You can also see some pictures from the screens at http://realize.be/mobile or an installation guide at http://www.slideshare.net/yoroy/drupoid.
Comments
Sweet! Permalink
Submitted by yareckon on January 18, 2012 - 22:52
Thanks for opening the code as you learn it. This is definitely something like what I have been meaning to try as well. If you get stuck, the wordpress app and the gallery2 apps for android are open source, so you can see both sides of the picture there too.
interesting Permalink
Submitted by Mike on January 19, 2012 - 03:28
I've been wanting to explore this possibility as well. With mobile phone camera use rising more and more, things like this will make Drupal all the more useful.
Nice and fun learning project Permalink
Submitted by mongolito404 on January 19, 2012 - 21:13
Nice and fun learning project... I poked at the Java source code, here are some quick notes:
- There is no need to redefine a Base64 utility class, there is one in the Android SDK since Froyo 2.2.x (API Level 8). http://developer.android.com/reference/android/util/Base64.html
- The image upload code compress the selected image in JPG in a byte array. It and then encodes it in base64 in a String. Because of this, the application will hold the whole JPEG in memory twice. This is no very mobile friendly. A better way, but likely harder, would be to use an HTTP API that support data streaming. This way, there would no need to store the uploaded image in memory at any time.
- Uploading a file is a long operation and should be handled asynchronously with something like http://developer.android.com/reference/android/os/AsyncTask.html
Thanks for the hints! Permalink
Submitted by swentel on January 20, 2012 - 08:53
Thanks for the hints!
I've been bitten by not using a background loader yesterday when testing on 3G. It took longer than testing on WIFI so it felt like the app was freezing.
Didn't know there was Base64 support from level 8, good to know. However, as you suggest, using another technique would probably be more memory friendly for the device. Will experiment with this, because I have to re-use this image posting functionality in another app which should theoretically still work for 2.0 (and possibly lower, however, that isn't a hard requirement)
Update 25/01/2012
The app is using a smart scaling algorithm for the preview of the image and a custom httpMultiPart class for uploading. This enables us to send the complete file to the server and doesn't crash the application not anymore. AsyncTasks have been added as well for login and uploading procedures!
This would be awesome for the Permalink
Submitted by Uwe on January 19, 2012 - 22:38
This would be awesome for the iPhone as well
Exception when I try to connect Permalink
Submitted by John Richter on March 25, 2012 - 23:09
Thanks for the tutorial. I seem to get an exception whenever I try to connect through the HttpMultiPart class. I'm working on a project for class that requires me to sync Drupal and an Android app (more info here: http://econexus.co/content/first-draft-growlife-logo ).
Any help would be appreciated! I will post anything I find out as well.
I decided to test out my Permalink
Submitted by John Richter on March 26, 2012 - 02:57
I decided to test out my actual server, and the exception changes to the getInputStream() method.
For some reason, the URL I set up through the drupapp to be my endpoint is not working at all. It worked on my local server (i.e., it returns JSON), but it doesn't work on my actual server.
Any ideas? http://growlife.co/drupapp
Figured it out. It was a Permalink
Submitted by John Richter on March 26, 2012 - 04:25
Figured it out. It was a matter of clean URLs.
very nice Permalink
Submitted by hedac on May 2, 2012 - 03:30
This is very nice... Managed to compile Android app nicely but I still use Drupal 6 and wondering if it is too much different to do a module compatible with Drupal 6.
Porting the module that's Permalink
Submitted by swentel on May 2, 2012 - 11:42
Porting the module that's also on Github to Drupal 6 shouldn't be that hard actually, it should take an hour max.
I don't have experience with Permalink
Submitted by hedac on May 2, 2012 - 17:31
I don't have experience with the differences between 6 and 7 versions.. but I think CCK has changed substantially... One feature I miss is to be able to enter text for the body of the node created. Not only the title. That would be awesome. :) Or maybe just use the title android text for the body and use the automatic nodetitles module to create the title from the body.
I trying to port it to drupal Permalink
Submitted by hedac on May 5, 2012 - 00:11
I trying to port it to drupal 6... I am having trouble with the drupal_session_commit function that doesn't exist in drupal 6. I think That's why I get an error message saying I don't have permission to upload images. I wonder how to write the session in drupal 6... any help? Thanks.
Normally session_write_close( Permalink
Submitted by swentel on May 19, 2012 - 11:17
Normally session_write_close() should work (it's a PHP function). It's used by drupal_goto as well, seeĀ http://api.drupal.org/api/drupal/includes%21common.inc/function/drupal_g...
I managed to port the module Permalink
Submitted by hedac on May 22, 2012 - 08:01
I managed to port the module to Drupal 6. I think I commented out the line.. and sessions are not closed.
One problem I have is that a few days after a post is made.. the session is expired.. but the android app enters directly to the main UI, without logging first and can't post .. solved signing out from the app and re entering.. once session is started again.. it can post without problems.
I Also added option to include body text, not only title. with a minor modification to the android code too. Thanks for this cool app!
Drupal 6 version Permalink
Submitted by andyroid on September 13, 2012 - 15:12
hi hedac
Could you please share your Drupal6 version? I am trying to port it myself but have had problems with the node_bundles section (lines 64 to 73).
will look into it when I have Permalink
Submitted by hedac on September 13, 2012 - 17:17
will look into it when I have time. I think I commented out that entire section.
Tried that.... Permalink
Submitted by Andyroid on September 13, 2012 - 18:40
HI, I tried that, but no such luck.
If I comment that section out - the "drupapp_image_field" is unset and appears to be required.
I am not sure what to set this to, to get it to work in the "build node" sections lines 280-288.
HttpMultipartRequest problem response Permalink
Submitted by Juan on August 28, 2012 - 21:03
Hi, testing the module, I get an empty response
sResponse = HttpMultipartRequest.execute (getBaseContext (), drupappEndpoint, Params, Common.SAVE_COOKIE, "", "");
and response to endpoint http://localhost/drupal/drupapp
is {"result": 0, "message": "Invalid request type."}
I have bad?
thank you very much
Add new comment