2011年5月21日土曜日

AndroidStudyMemo (Resource)=DownloadManager

http://developer.android.com/reference/android/app/DownloadManager.html

The download manager is a system service that handles long-running HTTP
downloads. Clients may request that a URI be downloaded to a particular
destination file. The download manager will conduct the download in the
background, taking care of HTTP interactions and retrying downloads after
failures or across connectivity changes and system reboots. Instances of
this class should be obtained through getSystemService(String) by passing
DOWNLOAD_SERVICE. Apps that request downloads through this API should
register a broadcast receiver for ACTION_NOTIFICATION_CLICKED to
appropriately handle when the user clicks on a running download in a
notification or from the downloads UI.

AndroidStudyMemo (Resource)=PackageManager

http://developer.android.com/reference/android/content/pm/PackageManager.html

Class for retrieving various kinds of information related to the application
packages that are currently installed on the device. You can find this class
through getPackageManager().

組み込み業界での Androidの情報を取り扱うグループ

https://groups.google.com/group/android-embedded-japan/about?hl=ja

組み込み業界での Androidの情報を取り扱うグループです。

すべてのユーザーがグループのコンテンツを閲覧できる
メンバーのみがメンバーリストを表示できる
誰でも参加できる
メンバーのみ投稿できる
新規メンバーからのメッセージを管理対象とする

Android Browser File Types

So far there are reports that specific types of files fail to download on
the Android browser. Here is a list of known file types:

Extensions
.zip - fails Note:1: The content being downloaded is not supported by the
phone .xxx - works Note:2: Most .zip files on this site that should be
downloaded via G1 have this extensions with instructions on renaming

Notes
.xxx gets renamed to .asc when downloaded via the browser.
while .zip results in the "content not supported" message, .ZIP (uppercase)
does work (tested on Android 2.1, Moto Defy)

Download Crutch
An application has been added to the market that will allow you to download
any file. I have tested it with a .zip file and it worked great. The app
name is Download Crutch. Find it on the market if you need to download any
non working file extension.

Astro File Manager
In edition to Download Crutch there is another free market app that
addresses this isue. Astro file manager will enable the browser to download
all file types. Astro is one of the highest rated and most popular file
managers in the Android Market. To allow the browser to download all file
types using Astro, download and open Astro File Manager. Then press menu,
select more, then at the bottom of the list select the box marked Enable All
File Types in Browser. In my experience, Astro is a good way to solve this
issue as it is a very good file manager in addition to enhancing the
browsers functionality.

HTTP Headers
If you are writing a web applicatoin that creates downloadable content,
watch your HTTP headers to make your downloads work on all (and especially
older) Android versions as expected:
set the ContentType to application/octet-stream
put the Content-Disposition filename value in double quotes
if your file is a ZIP: write the Content-Disposition filename extension in
UPPERCASE

Android and the HTTP download file headers

I lately had to create a complex download repository for a customer.
Multiple files could be selected and were compressed on the fly into a
single ZIP file before being transfered to the client. After everything
worked fine with IE, FF and Chrome, I checked with Android 2.1 and the
download failed. Here is why, and how to cure it…

I faced a whole bunch of problems like the stock browser not reacting at
all, both browsers reporting that "The content being downloaded is not
supported by the phone", both browsers downloading the file but ignoring my
filename and trying to save the file under the script name that generated
the ZIP. I guess not many users would know how to handle a file that is
downloaded with the name "index.php" or similar. *sigh*

The cause

I finally found that the Android browsers are extremely picky about two of
the usual HTTP download headers. Here are some defunct header lines – just
to show how NOT to do it.

ATTENTION:
If you use any of the lines below your download will probably NOT WORK on
Android.

Content-Type: application/force-download
Content-Disposition: attachment; filename=MyFileName.ZIP
Content-Disposition: attachment; filename="MyFileName.zip"
And the solution

To make it work in Android's stock browser and in Dolphin browser you have
to use:

Content-Type: application/octet-stream
Content-Disposition: attachment; filename="MyFileName.ZIP"
Please mind the double-quotes around the filename parameter and the
uppercase .ZIP extension of the filename. Both are absolutely necessary for
ZIP files on Android 2.1 to download correctly! From my web research it
looks like it is possible that the uppercase extension is only required for
ZIP files and only for Android versions up to 2.1. I am not sure of that and
did not do any further testing. If you create other downloadable file types
(e.g. PDF), please test yourself and leave a comment below.

Fortunately the above headers work for the major desktop browsers too, so
they are a good general solution.

Let's just hope that future Android versions will be less pesky.

Help to make it better

One important hint about a part of the problem (quoting the filename) came
from this Android bug report:

http://code.google.com/p/android/issues/detail?id=11422

If you have also been struggling with the problems mentioned in this post
and if you found a solution here, I humbly ask that you fuel the above bug
report by clicking the vote star at the bottom of the reporting page (above
the comment field).

AndroidStudyMemo (Resource)=ContentResolver.openInputStream()

public final InputStream openInputStream (Uri uri)

Since: API Level 1

Open a stream on to the content associated with a content URI. If there is no data associated with the URI, FileNotFoundException is thrown.

Accepts the following URI schemes:

See openAssetFileDescriptor(Uri, String) for more information on these schemes.

Parameters
uri The desired URI.
Returns
  • InputStream
Throws
FileNotFoundException if the provided URI could not be opened.

AndroidStudyMemo (Resource)=Intent

 

Class Overview

An intent is an abstract description of an operation to be performed. It can be used with startActivity to launch an Activity, broadcastIntent to send it to any interestedBroadcastReceiver components, and startService(Intent) or bindService(Intent, ServiceConnection, int) to communicate with a background Service.

An Intent provides a facility for performing late runtime binding between the code in different applications. Its most significant use is in the launching of activities, where it can be thought of as the glue between activities. It is basically a passive data structure holding an abstract description of an action to be performed. The primary pieces of information in an intent are:

  • action -- The general action to be performed, such as ACTION_VIEW, ACTION_EDIT, ACTION_MAIN, etc.

  • data -- The data to operate on, such as a person record in the contacts database, expressed as a Uri.

Some examples of action/data pairs are:

  • ACTION_VIEW content://contacts/people/1 -- Display information about the person whose identifier is "1".

  • ACTION_DIAL content://contacts/people/1 -- Display the phone dialer with the person filled in.

  • ACTION_VIEW tel:123 -- Display the phone dialer with the given number filled in. Note how the VIEW action does what what is considered the most reasonable thing for a particular URI.

  • ACTION_DIAL tel:123 -- Display the phone dialer with the given number filled in.

  • ACTION_EDIT content://contacts/people/1 -- Edit information about the person whose identifier is "1".

  • ACTION_VIEW content://contacts/people/ -- Display a list of people, which the user can browse through. This example is a typical top-level entry into the Contacts application, showing you the list of people. Selecting a particular person to view would result in a new intent { ACTION_VIEW content://contacts/N } being used to start an activity to display that person.

In addition to these primary attributes, there are a number of secondary attributes that you can also include with an intent:

  • category -- Gives additional information about the action to execute. For example, CATEGORY_LAUNCHER means it should appear in the Launcher as a top-level application, whileCATEGORY_ALTERNATIVE means it should be included in a list of alternative actions the user can perform on a piece of data.

  • type -- Specifies an explicit type (a MIME type) of the intent data. Normally the type is inferred from the data itself. By setting this attribute, you disable that evaluation and force an explicit type.

  • component -- Specifies an explicit name of a component class to use for the intent. Normally this is determined by looking at the other information in the intent (the action, data/type, and categories) and matching that with a component that can handle it. If this attribute is set then none of the evaluation is performed, and this component is used exactly as is. By specifying this attribute, all of the other Intent attributes become optional.

  • extras -- This is a Bundle of any additional information. This can be used to provide extended information to the component. For example, if we have a action to send an e-mail message, we could also include extra pieces of data here to supply a subject, body, etc.

Here are some examples of other operations you can specify as intents using these additional parameters:

There are a variety of standard Intent action and category constants defined in the Intent class, but applications can also define their own. These strings use java style scoping, to ensure they are unique -- for example, the standard ACTION_VIEW is called "android.intent.action.VIEW".

Put together, the set of actions, data types, categories, and extra data defines a language for the system allowing for the expression of phrases such as "call john smith's cell". As applications are added to the system, they can extend this language by adding new actions, types, and categories, or they can modify the behavior of existing phrases by supplying their own activities that handle them.

Intent Resolution

There are two primary forms of intents you will use.

  • Explicit Intents have specified a component (via setComponent(ComponentName) or setClass(Context, Class)), which provides the exact class to be run. Often these will not include any other information, simply being a way for an application to launch various internal activities it has as the user interacts with the application.

  • Implicit Intents have not specified a component; instead, they must include enough information for the system to determine which of the available components is best to run for that intent.

When using implicit intents, given such an arbitrary intent we need to know what to do with it. This is handled by the process of Intent resolution, which maps an Intent to an Activity,BroadcastReceiver, or Service (or sometimes two or more activities/receivers) that can handle it.

The intent resolution mechanism basically revolves around matching an Intent against all of the <intent-filter> descriptions in the installed application packages. (Plus, in the case of broadcasts, any BroadcastReceiver objects explicitly registered with registerReceiver(BroadcastReceiver, IntentFilter).) More details on this can be found in the documentation on the IntentFilter class.

There are three pieces of information in the Intent that are used for resolution: the action, type, and category. Using this information, a query is done on the PackageManager for a component that can handle the intent. The appropriate component is determined based on the intent information supplied in the AndroidManifest.xml file as follows:

  • The action, if given, must be listed by the component as one it handles.

  • The type is retrieved from the Intent's data, if not already supplied in the Intent. Like the action, if a type is included in the intent (either explicitly or implicitly in its data), then this must be listed by the component as one it handles.

  • For data that is not a content: URI and where no explicit type is included in the Intent, instead the scheme of the intent data (such as http: or mailto:) is considered. Again like the action, if we are matching a scheme it must be listed by the component as one it can handle.
  • The categories, if supplied, must all be listed by the activity as categories it handles. That is, if you include the categories CATEGORY_LAUNCHER and CATEGORY_ALTERNATIVE, then you will only resolve to components with an intent that lists both of those categories. Activities will very often need to support the CATEGORY_DEFAULT so that they can be found byContext.startActivity().

For example, consider the Note Pad sample application that allows user to browse through a list of notes data and view details about individual items. Text in italics indicate places were you would replace a name with one specific to your own package.

 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      
package="com.android.notepad">
    
<application android:icon="@drawable/app_notes"
            
android:label="@string/app_name">

        
<provider class=".NotePadProvider"
                
android:authorities="com.google.provider.NotePad" />

        
<activity class=".NotesList" android:label="@string/title_notes_list">
            
<intent-filter>
                
<action android:name="android.intent.action.MAIN" />
                
<category android:name="android.intent.category.LAUNCHER" />
            
</intent-filter>
            
<intent-filter>
                
<action android:name="android.intent.action.VIEW" />
                
<action android:name="android.intent.action.EDIT" />
                
<action android:name="android.intent.action.PICK" />
                
<category android:name="android.intent.category.DEFAULT" />
                
<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
            
</intent-filter>
            
<intent-filter>
                
<action android:name="android.intent.action.GET_CONTENT" />
                
<category android:name="android.intent.category.DEFAULT" />
                
<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
            
</intent-filter>
        
</activity>

        
<activity class=".NoteEditor" android:label="@string/title_note">
            
<intent-filter android:label="@string/resolve_edit">
                
<action android:name="android.intent.action.VIEW" />
                
<action android:name="android.intent.action.EDIT" />
                
<category android:name="android.intent.category.DEFAULT" />
                
<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
            
</intent-filter>

            
<intent-filter>
                
<action android:name="android.intent.action.INSERT" />
                
<category android:name="android.intent.category.DEFAULT" />
                
<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
            
</intent-filter>

        
</activity>

        
<activity class=".TitleEditor" android:label="@string/title_edit_title"
                
android:theme="@android:style/Theme.Dialog">
            
<intent-filter android:label="@string/resolve_title">
                
<action android:name="com.android.notepad.action.EDIT_TITLE" />
                
<category android:name="android.intent.category.DEFAULT" />
                
<category android:name="android.intent.category.ALTERNATIVE" />
                
<category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
                
<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
            
</intent-filter>
        
</activity>

    
</application>
 
</manifest>

The first activity, com.android.notepad.NotesList, serves as our main entry into the app. It can do three things as described by its three intent templates:

  1.  <intent-filter>
        
    <action android:name="android.intent.action.MAIN" />
        
    <category android:name="android.intent.category.LAUNCHER" />
     
    </intent-filter>

    This provides a top-level entry into the NotePad application: the standard MAIN action is a main entry point (not requiring any other information in the Intent), and the LAUNCHER category says that this entry point should be listed in the application launcher.

  2.  <intent-filter>
        
    <action android:name="android.intent.action.VIEW" />
        
    <action android:name="android.intent.action.EDIT" />
        
    <action android:name="android.intent.action.PICK" />
        
    <category android:name="android.intent.category.DEFAULT" />
        
    <data mimeType:name="vnd.android.cursor.dir/vnd.google.note" />
     
    </intent-filter>

    This declares the things that the activity can do on a directory of notes. The type being supported is given with the <type> tag, where vnd.android.cursor.dir/vnd.google.noteis a URI from which a Cursor of zero or more items (vnd.android.cursor.dir) can be retrieved which holds our note pad data (vnd.google.note). The activity allows the user to view or edit the directory of data (via the VIEW and EDIT actions), or to pick a particular note and return it to the caller (via the PICK action). Note also the DEFAULT category supplied here: this is required for the Context.startActivity method to resolve your activity when its component name is not explicitly specified.

  3.  <intent-filter>
        
    <action android:name="android.intent.action.GET_CONTENT" />
        
    <category android:name="android.intent.category.DEFAULT" />
        
    <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
     
    </intent-filter>

    This filter describes the ability return to the caller a note selected by the user without needing to know where it came from. The data typevnd.android.cursor.item/vnd.google.note is a URI from which a Cursor of exactly one (vnd.android.cursor.item) item can be retrieved which contains our note pad data (vnd.google.note). The GET_CONTENT action is similar to the PICK action, where the activity will return to its caller a piece of data selected by the user. Here, however, the caller specifies the type of data they desire instead of the type of data the user will be picking from.

Given these capabilities, the following intents will resolve to the NotesList activity:

  • { action=android.app.action.MAIN } matches all of the activities that can be used as top-level entry points into an application.

  • { action=android.app.action.MAIN, category=android.app.category.LAUNCHER } is the actual intent used by the Launcher to populate its top-level list.

  • { action=android.intent.action.VIEW data=content://com.google.provider.NotePad/notes } displays a list of all the notes under "content://com.google.provider.NotePad/notes", which the user can browse through and see the details on.

  • { action=android.app.action.PICK data=content://com.google.provider.NotePad/notes } provides a list of the notes under "content://com.google.provider.NotePad/notes", from which the user can pick a note whose data URL is returned back to the caller.

  • { action=android.app.action.GET_CONTENT type=vnd.android.cursor.item/vnd.google.note } is similar to the pick action, but allows the caller to specify the kind of data they want back so that the system can find the appropriate activity to pick something of that data type.

The second activity, com.android.notepad.NoteEditor, shows the user a single note entry and allows them to edit it. It can do two things as described by its two intent templates:

  1.  <intent-filter android:label="@string/resolve_edit">
        
    <action android:name="android.intent.action.VIEW" />
        
    <action android:name="android.intent.action.EDIT" />
        
    <category android:name="android.intent.category.DEFAULT" />
        
    <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
     
    </intent-filter>

    The first, primary, purpose of this activity is to let the user interact with a single note, as decribed by the MIME type vnd.android.cursor.item/vnd.google.note. The activity can either VIEW a note or allow the user to EDIT it. Again we support the DEFAULT category to allow the activity to be launched without explicitly specifying its component.

  2.  <intent-filter>
        
    <action android:name="android.intent.action.INSERT" />
        
    <category android:name="android.intent.category.DEFAULT" />
        
    <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
     
    </intent-filter>

    The secondary use of this activity is to insert a new note entry into an existing directory of notes. This is used when the user creates a new note: the INSERT action is executed on the directory of notes, causing this activity to run and have the user create the new note data which it then adds to the content provider.

Given these capabilities, the following intents will resolve to the NoteEditor activity:

  • { action=android.intent.action.VIEW data=content://com.google.provider.NotePad/notes/{ID} } shows the user the content of note {ID}.

  • { action=android.app.action.EDIT data=content://com.google.provider.NotePad/notes/{ID} } allows the user to edit the content of note {ID}.

  • { action=android.app.action.INSERT data=content://com.google.provider.NotePad/notes } creates a new, empty note in the notes list at "content://com.google.provider.NotePad/notes" and allows the user to edit it. If they keep their changes, the URI of the newly created note is returned to the caller.

The last activity, com.android.notepad.TitleEditor, allows the user to edit the title of a note. This could be implemented as a class that the application directly invokes (by explicitly setting its component in the Intent), but here we show a way you can publish alternative operations on existing data:

 <intent-filter android:label="@string/resolve_title">
    
<action android:name="com.android.notepad.action.EDIT_TITLE" />
    
<category android:name="android.intent.category.DEFAULT" />
    
<category android:name="android.intent.category.ALTERNATIVE" />
    
<category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
    
<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
 
</intent-filter>

In the single intent template here, we have created our own private action called com.android.notepad.action.EDIT_TITLE which means to edit the title of a note. It must be invoked on a specific note (data type vnd.android.cursor.item/vnd.google.note) like the previous view and edit actions, but here displays and edits the title contained in the note data.

In addition to supporting the default category as usual, our title editor also supports two other standard categories: ALTERNATIVE and SELECTED_ALTERNATIVE. Implementing these categories allows others to find the special action it provides without directly knowing about it, through the queryIntentActivityOptions(ComponentName, Intent[], Intent, int)method, or more often to build dynamic menu items with addIntentOptions(int, int, int, ComponentName, Intent[], Intent, int, MenuItem[]). Note that in the intent template here was also supply an explicit name for the template (via android:label="@string/resolve_title") to better control what the user sees when presented with this activity as an alternative action to the data they are viewing.

Given these capabilities, the following intent will resolve to the TitleEditor activity:

  • { action=com.android.notepad.action.EDIT_TITLE data=content://com.google.provider.NotePad/notes/{ID} } displays and allows the user to edit the title associated with note {ID}.

Standard Activity Actions

These are the current standard actions that Intent defines for launching activities (usually through startActivity(Intent). The most important, and by far most frequently used, areACTION_MAIN and ACTION_EDIT.

Standard Broadcast Actions

These are the current standard actions that Intent defines for receiving broadcasts (usually through registerReceiver(BroadcastReceiver, IntentFilter) or a <receiver> tag in a manifest).

Standard Categories

These are the current standard categories that can be used to further clarify an Intent via addCategory(String).

Standard Extra Data

These are the current standard fields that can be used as extra data via putExtra(String, Bundle).

Flags

These are the possible flags that can be used in the Intent via setFlags(int) and addFlags(int). See setFlags(int) for a list of all possible flags.