Droid version of iOS Tutorial: Using Email Attachments

This is only possible via Corona Enterprise by writing the Java code yourself.

There is no way to do this with the normal Corona SDK (ie: via the Corona Simulator), because we do not provide a means of implementing an “intent filter”, nor accessing the other app’s file via its “content provider” since apps typically do not have direct file access to another app’s files on Android.

Really? That’s disappointing… So the same simple functionality that is available in iOS, such that an article published/promoted on your website showing the flexibility of Corona being able to open files from email attachments using your app, isn’t available for one of the platforms you promote as having cross device support for?

Dam! I’ve struck out here then…

So what other things can’t you do in Android that you can in iOS? Starting to wonder if building in Corona is going to be worth it. G

Just to confirm, so this basic capability in Android isn’t available in Corona SDK? ie adding stuff to the manifest and some simple lines of code that check for how the app is launched to detect the file path? Just like the iOS version of the Corona article does.

This Manifest is used to register (for example) .stl file type with your application:

\<?xml version="1.0" encoding="utf-8"?\> \<manifest xmlns:android="http://schemas.android.com/apk/res/android" &nbsp; &nbsp; package="org.test.core" android:versionCode="1" android:versionName="1.0"\> &nbsp; &nbsp; \<application android:icon="@drawable/icon" android:label="@string/app\_name"\> &nbsp; &nbsp; &nbsp; &nbsp; \<activity android:name=".Testy" android:label="@string/app\_name"\> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \<intent-filter\> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \<action android:name="android.intent.action.MAIN" /\> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \<category android:name="android.intent.category.LAUNCHER" /\> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \</intent-filter\> &nbsp; &nbsp; &nbsp; &nbsp; \</activity\> &nbsp; &nbsp; &nbsp; &nbsp; \<activity android:name="ThorActivity" android:label="@string/app\_name"\> &nbsp; &nbsp; &nbsp; &nbsp; \</activity\> &nbsp; &nbsp; &nbsp; &nbsp; \<activity android:name="LokiActivity" android:label="@string/app\_name"\> &nbsp; &nbsp; &nbsp; &nbsp; \</activity\> &nbsp; &nbsp; &nbsp; &nbsp; \<activity android:name="OdinActivity" android:label="@string/app\_name"\> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \<intent-filter\> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \<action android:name="android.intent.action.VIEW" /\> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \<category android:name="android.intent.category.DEFAULT" /\> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \<category android:name="android.intent.category.BROWSABLE" /\> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \<data android:scheme="http" android:host="\*" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; android:pathPattern=".\*\\.stl" /\> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \<data android:scheme="https" android:host="\*" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; android:pathPattern=".\*\\.stl" /\> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \<data android:scheme="content" android:host="\*" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; android:pathPattern=".\*\\.stl" /\> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \<data android:scheme="file" android:host="\*" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; android:pathPattern=".\*\\.stl" /\> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \</intent-filter\> &nbsp; &nbsp; &nbsp; &nbsp; \</activity\> &nbsp; &nbsp; \</application\> &nbsp; &nbsp; \<uses-permission android:name="android.permission.INTERNET" /\> &nbsp; &nbsp; \<uses-permission android:name="android.permission.BLUETOOTH" /\> &nbsp; &nbsp; \<uses-permission android:name="android.permission.BLUETOOTH\_ADMIN" /\> &nbsp; &nbsp; \<uses-permission android:name="android.permission.READ\_PHONE\_STATE" /\> &nbsp; &nbsp; \<uses-permission android:name="android.permission.ACCESS\_NETWORK\_STATE" /\> &nbsp; &nbsp; \<uses-permission android:name="android.permission.WRITE\_EXTERNAL\_STORAGE" /\> \</manifest\>&nbsp; &nbsp;

We link the .stl file extension to the activity OdinActivity. Inside the OdinActivity, the following line is used to get the file path so it open it:

filePath = getIntent().getData().getEncodedPath();&nbsp;

Then just open it to read from it:

FileOutputStream out = new FileOutputStream(new File(filePath));&nbsp;

To be fair, some things that are simple to do “natively” in iOS are not simple to do “natively” on Android… and vice-versa.  There are always going to be some differences when it comes to cross-platform development.  But what Corona does do well between iOS and Android is provide a nice OpenGL accelerated 2D framework, audio mixing, physics engine, in-app purchase system, async networking, and other services that are common features in most apps.  We don’t support every feature that an OS provides, but if you need that level of functionality, then you’ll need to do the native development yourself.

To be fair … ???

Isn’t it that you’ve included an incredible amount of flexibility in the build.settings file for plist, but bugger all for the same kind of stuff to be included in manifest? There is actually very little code to provide between the two, just plumbing in the right place to allow certain type of XML content in the manifest and associated activity name being registered in code and manifest. 

I’m learning fast, but was hoping a point in the right direction would be offered - if I can’t even register filetypes between both platforms, I will have to abandon Corona and look at something else… heck after a few minutes I can see that Appcelerator Titanium can do this… Mmmmmm can I get a refund on my recently purchased Pro license?

It’s not as trivial as you think.  Other apps typically do *not* give you direct access to their files because they are sandboxed within their own app directory or the file may exist remotely, such as the case with Picasa, Google+, and DropBox files.  In these cases, you have to access the file via an Android ContentProvider object where you may have to “query” for the file like you would with a database or access it via an input stream.

http://developer.android.com/reference/android/content/ContentProvider.html

And typically that URI you receive from intent.getData() is a “key” that you have to pass to that app’s ConentProvider.query() method to get the real location of the file… that even then you may still not have direct file access to.  There’s actually a lot of fallback mechanisms that you have to implement to make this work.  I’m speaking from experience.  We have an API for accessing photos from a photo app on Android and there are *many* different ways the file can be received.  Your FileOutputStream() example above would not work with most photo apps on Android.

Anyways, that’s my 2 cents.

If you feel that Corona won’t work for you project, then I understand.  You have to use what works best for you.  But it’s definitely not as simple as you think.

Although it’s probably “splitting hairs”, I should note that the tutorial you reference was a guest tutorial by a Corona ambassador. It was meant to illustrate a useful (for some) technique on iOS, not serve as an example of what Android can’t do in a similar fashion. The author came up with this method and the example functions by himself and I felt it was useful to share with the developer community.

As Josh says, the nature of cross-platform development is never 100% equal. We put a considerable amount of effort into Android features, but not everything is possible. Sometimes iOS gets the short end of the stick too… for example, we recently added a way to get the physical screen dimensions and DPI of Android devices, which is not exposed on iOS and thus we can’t provide it. So, chalk one up in the Android column. :wink:

Regards,
Brent Sorrentino

Ok, thanks guys. I really appreciate you taking the time to respond and engage.

So to be clear, adding stuff to the manifest in Corona is not something I can do as per my example? 

Josh - I agree catching all the ways other apps provide file is not easy, but the case of just providing a email attachment “open with” which is similar to getting DropBox to “open with”, which is the same as Safari download and “open with” - is that doable with the Corona SDK ? My code above works with all those and is probably 90% of the way you’d get your app to open a file that it knows what to do with… just like the iOS example provided by that ambassador ???

Would love to hear you tell me - Yes, do this, and that… or in the next build next week… etc… 

G

>> but the case of just providing a email attachment “open with” which is similar to getting DropBox to “open with”, which is the same as Safari download and “open with” - is that doable with the Corona SDK ?

This is currently not possible with the Corona SDK.  You can only do this with Corona Enterprise by writing the native code yourself.  Probably not the answer you are looking for.

It’s definitely possible for us to add support for this to Corona, but this feature is rarely requested, making it low priority.  Now, if it was high in our feature request list (see the link below), then we would definitely do something about it.  At the moment, our top priority tasks on Android is AdMob and Ouya support since they have the highest demand.

   http://feedback.coronalabs.com/forums/188732-corona-sdk-feature-requests-feedback/filters/top

A more likely solution that we plan on experimenting with later this year is the ability to make direct calls to Java in Lua.  This would serve as a middle-ground for developers who don’t want to pay for Corona Enterprise because they only want to access a small subset of Android’s Java APIs (which makes sense).  It sounds like you fit into this category.  We just don’t have an ETA for this yet.

Interesting that of the Android requests, the 3rd most requested feature is “Android share image and text intent” of which arguably would be similar and probably require most of the same functionality I’m after… so hopefully you can squeeze this into a future release assuming it isn’t that hard to do (and why would it be?)… fingers crossed.

PS - can you get someone to contact me about Enterprise and perhaps/hopefully the license isn’t too prohibitive for my small use case and size of team (1)… !!

G

The “share image/text intent” actually goes in the opposite direction.  It’s where your app sends a file to another app as described by Google here…

http://developer.android.com/training/sharing/send.html

That’s actually much simpler for us to implement because we have already written our own ContentProvider for sending files to other apps.  This feature is commonly requested because Google Play app reviewers often request this feature of other apps in order to be “featured” on Google Play.  It’s the Android way of sending information out to social apps.  Google seems to prefer this over direct integration of facebook and twitter.  What’s nice about this is that end-users can choose the social service of their choice rather than the app imposing only the social services it integrates with.

I’ll let someone here know that you are interested in Corona Enterprise.

Fair - I guess I was assuming changes need to be made to build.settings to support updating the manifest and also allowing some way to specify app activities etc.

I’m actually just wondering how I can have files that are saved or created elsewhere to be opened and viewed by my customer Corona App… seems I can do this on an iOS device, just won’t be able to do this fully with Android (obviously created data content looks fine, just can’t import or add content from other sources like email attachments or dropbox etc).

You should be able to add content from Dropbox.  Here’s a link to some sample code that should push you in the right direction.

http://developer.coronalabs.com/code/dropbox-rest-sample-code

The sample code only works for text files, however.  If you want to work with images or audio files, you’ll have to add a function to handle the Dropbox /media API:

https://www.dropbox.com/developers/core/api#media

That’s a pretty ugly way to get a file in/out of your app. I’m surprised that working with files isn’t something that on Android, people aren’t requesting. Obviously when building a game, you rarely need to work with files, but anything that processes data visually on the devices (like a statistics app or educational app) might need to import or open files via email (similar to what is being easily done on the iOS devices).

I’ve voted for this which is close and has a few people interested… so c’mon Corona team, get cracking on something better!

http://feedback.coronalabs.com/forums/188732-corona-sdk-feature-requests-feedback/suggestions/3593966-read-and-write-to-the-android-visible-storage

I like the idea of reading and writing to visible storage as well.  But the Dropbox functionality isn’t as terrible as you make it out to be.  The code that I provide simply demonstrates the mechanisms of the REST API.    All apps that access a service like Dropbox (or even Twitter) must have an authorization step.  Once that is done the uploading and downloading can be integrated quite smoothly into the app.   Don’t knock it until you try it!