スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

まいぇ~すすめっ!

彼女と別れてもそれも前進!

お互い話し合って別れることにしたのよね
首の調子も良くなってきて、大分痛みがひいてきました。距離は前と同じ800mだったけど、スピード出せるようになってきたしね。

6月のなみはやドームでの大会申し込みも完了したし、俺よ、まいぇーすすめーいっ!
スポンサーサイト

水に揺られて

今日は800mまで距離を伸ばす。ゆらゆら水に揺られて。

6月の水泳大会ですが、名古屋マスターズを迷っているうちに締め切りが来てしまったので、大坂のなみはやに行こうと思ってます。

それまでに泳げるようにしないとなー。

あともうちょっと。

首の痛みはあるけど、泳ごうと思ったら、普通に泳げた感じ。

今日も、600mくらい泳いだべ。

サー、寝よ。

泳げたけど…。

1週間ぶりの水泳。

肩が傷むー。まだ普通に泳げないー。首もあんまり回らない。

600mくらい水に漂ってただけ。

帰ろ。

腫れ時々痛み

リンパ腺の腫れがひかん。いや少しは引いてるのだけれど、ピリピリ痛むしー。

今日は、ブレ50×4とバック50×4と400フリー。

それぞれ、45、42、5:30。体にキレが無いからこんなもん。

かーエロ。

だりぃ。

昨日の反動。ちょーだりぃ。

仕事も早めに切り上げて、軽めに泳ぐ。

上唇のリンパ腺が腫れてます。

今夜は早く寝よう。

あとは大会まで休憩

10時スタートで泳ぐ。

昨日かいた50×2は、36と35でした。微妙…。

しかも、肩と足首の痛みが戻ってきてるような…。
この痛みは完全に仕事のしすぎから来とるな。

なるよーになるさー!

帰ろ。

軽めに調整

1000くらい泳いで、フォームのチェック。

ダッシュは100フリー×1を、80%で泳いで1:10。まあ、こんなもんか?

明日は、50×2をfly-baとbr-frで泳ぐ予定。それぞれ35で泳げればオッケーにしよう。

帰りまっす。

あと一週間

大会まであと一週間です。

今日はダッシュできるか確認のために泳ぎました。
タイムは、1個メは1:16、1フリは1:09。25バタは14秒くらい。

ほか、もろもろ含めて2,000くらいは泳いだかなと。
タイムはギリギリだなぁ。あと、1.5秒くらい上げたいけど難しいわな。
まだ、右くるぶしの後ろが痛むし。

でも、ま、ダッシュできたので良しとしよう。

k・d・ハポンでライブじゃ♪

Android で GoogleDoc にアクセス。おわり

Android で Google Documentに保存すると、ファイルの共有が可能になると思って、調べたり作ったり試行錯誤したりしました。

トークンの再取得や、共有の仕方/考え方、HTTP通信する時のヘッダの設定方法、などなど四苦八苦したことばかり。あと、ウェブで探しまわっても古い情報しか無かったり(でも有益でした!)、APIのバージョンがV3に変わったりしてて、情報が少ない中、なんとか今ウェブにある情報で作り上げることができました。

自分の拙いソースが、自分のような何処かの誰かの役に立てばいいなぁ。

Android で GoogleDoc にアクセス。その4

Google Document で得られるファイル1個に複数設定される、ACL情報を1個づつ管理するためのクラス。

ACL情報は、アクセスコントロールリスト。Google Documentで共有情報を設定するための情報。
1ファイルに対して、この人は読み取りだけ、この人は編集も可能と設定する。「この人」っていうのは、基本的には、G/Mailアドレスをもって設定する。
Google Groupも設定できるらしいけどやってない。次のMandala9のバージョンアップ時に追加する。

読み取り専用なり、編集可能なりで、ファイルを共有設定にすると、共有を設定された人がGoogle Documentにアクセスすると、その人のファイル一覧内に共有ファイルが含まれるようになっている。

当初、どうやって共有されるのかが分からず、またここでもハマった。

public class GoogleDocItemAcl {

// - static --------------------------------------------------------------
public enum AclRoleType {
NONE,
OWNER,
READER,
WRITER,
};

public enum AclScopeType {
NONE,
USER,
DEFAULT,
};

public static final String SCOPE_USER = "user";
public static final String SCOPE_DEFAULT = "default";

public static final String ROLE_NONE = "none";
public static final String ROLE_OWNER = "owner";
public static final String ROLE_READER = "reader";
public static final String ROLE_WRITER = "writer";

// - attribute -----------------------------------------------------------
AclRoleType _RoleType = AclRoleType.NONE; // reader/writer
AclScopeType _ScopeType = AclScopeType.NONE; // default/user
String _ScopeValue = ""; // メールアドレス
String _LinkEdit = "";

ArrayList _WithKeys;

public AclRoleType get_Role() {
return _RoleType;
}

public void set_Role(String _role)
{
if( _role.equals( ROLE_OWNER ) ) {
_RoleType = AclRoleType.OWNER;
}
else if( _role.equals( ROLE_READER ) ) {
_RoleType = AclRoleType.READER;
}
else if( _role.equals( ROLE_WRITER ) ) {
_RoleType = AclRoleType.WRITER;
}
}

public AclScopeType get_ScopeType() {
return _ScopeType;
}

public void set_ScopeType(String _type)
{
if( _type.equals( SCOPE_USER ) ) {
_ScopeType = AclScopeType.USER;
}
else if( _type.equals( SCOPE_DEFAULT ) ) {
_ScopeType = AclScopeType.DEFAULT;
}
}

public String get_MailAddress() { return get_ScopeValue(); }

public String get_ScopeValue() {
return _ScopeValue;
}

public void set_ScopeValue(String _ScopeValue) {
this._ScopeValue = _ScopeValue;
}

public String get_LinkEdit() {
return _LinkEdit;
}

public void set_LinkEdit(String _LinkEdit) {
this._LinkEdit = _LinkEdit;
}

// - public method -------------------------------------------------------

/**
* constractor
*/
GoogleDocItemAcl()
{
_WithKeys = new ArrayList();
}

/**
*
* @param key
* @param role
* @param value
*/
public void add_WithKey(String key, String role)
{
_WithKeys.add( new GAclWithKey(key, role) );
}

/**
* (defaultの?) のロールタイプを返す。
*/
public AclRoleType get_WithKeyRole()
{
AclRoleType type = AclRoleType.NONE;

if( _WithKeys.isEmpty() )
{
// 空っぽの場合は「ウェブで公開」になっている場合のようなので、デフォルトのroleを返す。
type = get_Role();
}
else
{
String role = _WithKeys.get(0).get_Role();

if( role.equals( ROLE_READER ) ) {
type = AclRoleType.READER;
}
else if( role.equals( ROLE_WRITER ) ) {
type = AclRoleType.WRITER;
}
}

return type;
}

/**
* インナー クラス。
* @author tatsu
*/
class GAclWithKey
{
String _Key;
String _Role;

public GAclWithKey( String _k, String _r )
{
_Key = _k;
_Role = _r;
}

// - get/set ---------------------------------------------------------
public String get_Key() {
return _Key;
}

public void set_Key(String _Key) {
this._Key = _Key;
}

public String get_Role() {
return _Role;
}

public void set_Role(String _Role) {
this._Role = _Role;
}


}
}

Android で GoogleDoc にアクセス。その3

GoogleDocAccess クラスが取得したXML情報から、ファイル単位で管理しておきたかったので作ったクラス。

GoogleDocmentにアクセスすると、ファイルの一覧がXMLで取得できますが、それを解析して1アイテムづつで覚えておくためのクラス。

ファイル名や、更新時間、リソースIDなどがある。

public class GoogleDocItem {

// - static members ------------------------------------------------------
private static final String DELETE_APPEND = "?delete=true";

// - attributes ----------------------------------------------------------
private String _ETag;
private Date _Update;
private String _FileName;
private String _Title;
private String _ContentSrc;
private String _ResourceId;

private String _EditUrl = "";
private String _EditMediaUrl = "";
private String _ResumableEditMediaUrl = "";

private String _AuthorName = "";
private String _AuthorMail = "";

// - Acl 情報 -
private Date _UpdateAcl;
private ArrayList _Roles;

// - get/set method ------------------------------------------------------
public String get_ETag() {
return _ETag;
}
public void set_ETag( String _etag ) {
_ETag = _etag;
}

public Date get_Update() {
return _Update;
}
public void set_Update(Date update) {
_Update = update;
}

public String get_FileNameFull() { // 拡張子付き
return _FileName;
}
public String get_FileNameOnly() // 拡張子無し
{
int last_index= _FileName.lastIndexOf('.');
String file_name = _FileName;

if( last_index >= 0 ) {
file_name = _FileName.substring(0, last_index);
}

return file_name;
}
public String get_FileNameExt() // ファイル拡張子
{
int last_index= _FileName.lastIndexOf('.');
String file_ext = "";

if( last_index >= 0 ) {
file_ext = _FileName.substring( last_index+1 );
}

return file_ext;
}

public void set_FileName(String fileName) {
_FileName = fileName;
}

public String get_Title() {
return _Title;
}
public void set_Title(String title) {
_Title = title;
}

public String get_ContentSrc() {
return _ContentSrc;
}
public void set_ContentSrc(String url) {
_ContentSrc = url;
}

public String get_ResourceId() {
return _ResourceId;
}
public void set_ResourceId(String url) {
_ResourceId = url;
}

public String get_EditUrl() {
return _EditUrl;
}
public void set_EditUrl(String _EditUrl) {
if( _EditUrl != null ) this._EditUrl = _EditUrl;
}

public String get_EditMediaUrl() {
return _EditMediaUrl;
}
public void set_EditMediaUrl(String _EditMediaUrl) {
if( _EditMediaUrl != null ) this._EditMediaUrl = _EditMediaUrl;
}

public String get_ResumableEditMediaUrl() {
return _ResumableEditMediaUrl;
}
public void set_ResumableEditMediaUrl(String _EditMediaUrl) {
if( _EditMediaUrl != null ) this._ResumableEditMediaUrl = _EditMediaUrl;
}

public Date get_UpdateAcl() {
return _UpdateAcl;
}
public void set_UpdateAcl(Date _UpdateAcl) {
this._UpdateAcl = _UpdateAcl;
}

public ArrayList get_Roles() {
return this._Roles;
}

public String get_AuthorName() {
return _AuthorName;
}
public void set_AuthorName(String _AuthorName) {
this._AuthorName = _AuthorName;
}
public String get_AuthorMail() {
return _AuthorMail;
}
public void set_AuthorMail(String _AuthorMail) {
this._AuthorMail = _AuthorMail;
}

// - public method -------------------------------------------------------

public GoogleDocItem()
{
_Update = new Date();
_FileName = "";
_ContentSrc = "";
_Title = "";
_Roles = new ArrayList();
}

/**
* ファイル名の拡張子チェック
*/
public boolean isFileExt(
String _ext
)
{
boolean st = false;

if( _FileName != null ) {
st = (get_FileNameExt().equals(_ext) );
}

return st;
}

/**
* 削除用のURLを取得する。
* @param _delete // I: true=Delete / false=Trash
*/
public String get_DeleteUrl(
boolean _delete
)
{
String url = get_EditUrl();

if( _delete ) {
url += DELETE_APPEND;
}

return url;
}

/**
* Acl情報を追加する。
*/
public void clearRoleScope()
{
_Roles.clear();
}

public void addRoleScope(
GoogleDocItemAcl _doc_acl
)
{
_Roles.add( _doc_acl );
}

/**
* Acl情報の default scope の の href を取得する。
*/
public String get_AclLinkEditDefault()
{
String url = "";

for( GoogleDocItemAcl role : _Roles )
{
if( role.get_ScopeType() == AclScopeType.DEFAULT )
{
url = role.get_LinkEdit();
break;
}
}

return url;
}

// - private method ------------------------------------------------------

}

Android で GoogleDoc にアクセス。その2

GoogleDocにアクセスするクラス。Google Docments List API (英語) をなんとか読みこなして作りました。

HTTP通信しているだけなので、そんなに難しいことはない。↑に書いてある通りの作法にのっとって呼び出すだけでした。

ファイルのアップロード/ダウンロード/削除/内容の更新を作った。詳細はソースを参照ください。

public class GoogleDocAccess {

// - static members ------------------------------------------------------
public static final String CONTENT_TYPE_XML = "text/xml";
public static final String CONTENT_TYPE_TEXT = "text/plain";
public static final String CONTENT_TYPE_WORD = "application/msword";
public static final String CONTENT_TYPE_APP_ATOM_XML = "application/atom+xml";

private static final String FILE_LIST_URL = "https://docs.google.com/feeds/default/private/full";
private static final String FILE_ENTRY_URL = "https://docs.google.com/feeds/%s/private/full/%s";

private static final String TAG = "GoogleDocsAccess";
private static final String RCM = "resumable-create-media";
private static final String FILE_NO_CONV = "?convert=false";
private static final String FILE_UPLOAD1 =
"\n"+
"\n"+
" %s\n"+
"
\n";

private static final String FILE_ATTR_BATCH_CHAGE =
"" +
"" +
"" +
"" +
"https://docs.google.com/feeds/default/private/full/%s/acl/user:%s" +
"" +
"
";

private static final String FILE_ACL_UPDATE =
" \n"+
" "term='http://schemas.google.com/acl/2007#accessRule'/> \n" +
" \n" +
" \n" +
"
";

// ↓にしたら、「ウェブ上で一般公開」になった。
private static final String FILE_ACL_UPDATE_DEFAULT1 =
" \n"+
" "term='http://schemas.google.com/acl/2007#accessRule'/> \n" +
" \n" +
" \n" +
"
";

// ↓にしたら、「リンクを知っている人全員」になった。
private static final String FILE_ACL_UPDATE_DEFAULT2 =
" \n"+
" "term='http://schemas.google.com/acl/2007#accessRule'/> \n" +
" \n" +
" \n" +
"
\n" +
" \n" +
" \n" +
"
";

// 共有属性バッチ更新用entryタグ
private static final String FILE_ACL_UPDATE_BATCH =
"" +
"%s" +
"" + // ex. insert
"" + // ex. reader
"" + // ex. abc@meil.com
"
";

// - GData XML解析用 --------------------------------------------------------
private static final String TAG_FEED = "feed";
private static final String TAG_ENTRY = "entry";
private static final String TAG_ENTRY_ATT_GD_ETAG_NS= "http://schemas.google.com/g/2005";
private static final String TAG_ENTRY_ATT_GD_ETAG = "etag";
private static final String TAG_LINK = "link";
private static final String TAG_AUTHOR = "author";
private static final String TAG_NAME = "name";
private static final String TAG_EMAIL = "email";
private static final String TAG_LINK_ATT_REL = "rel";
private static final String TAG_LINK_ATT_HREF = "href";
private static final String TAG_LINK_REL_VAL_EDIT = "edit";
private static final String TAG_LINK_REL_VAL_EDIT_MEDIA = "edit-media";
private static final String TAG_LINK_REL_VAL_RESUM_EDIT_MEDIA = "http://schemas.google.com/g/2005#resumable-edit-media";

private static final String TAG_CONTENT = "content";
private static final String TAG_CONTENT_ATT_SRC = "src";
private static final String TAG_GD_RESOURCEID = "resourceId";
private static final String TAG_UPDATED = "updated";
private static final String TAG_FILE_NAME = "filename";
private static final String TAG_TITLE = "title";
private static final String TAG_GACL_ROLE = "role";
private static final String TAG_GACL_SCOPE = "scope";
private static final String TAG_GACL_WITH_KEY = "withKey";
private static final String TAG_GACL_ATT_TYPE = "type";
private static final String TAG_GACL_ATT_VALUE = "value";
private static final String TAG_GACL_ATT_KEY = "key";

// - Upload 用 -------------------------------------------------------------
private static final String NEXT_LOCATION = "Location";
private static final int CHUNK_SIZE = 524288;

// - バッチ更新用 --------------------------------------------------------------
private static final String BATCH_ID_1 = "1";
private static final String BATCH_ID = "%s/user:%s";

private static final String BATCH_INSERT = "insert";
private static final String BATCH_UPDATE = "update";
private static final String BATCH_DELETE = "delete";

private static final String BATCH_READER = "reader";
private static final String BATCH_WRITER = "writer";

// - HTTP Responce -------------------------------------------------------
private static final int HTTP_ST_SUCCESS = 200;
private static final int HTTP_ST_COMPLETE_UPLOAD = 201;
private static final int HTTP_ST_COMPLETE_UPDATE = 201;
private static final int HTTP_ST_RESENT_CONTENT = 308;
private static final int HTTP_ST_BAD_REQUEST = 400;

public enum Method {
GET,
POST,
PUT,
DELETE,
}

// - attributes ----------------------------------------------------------
private String _AuthToken = "";
private ArrayList _GDocItems;
public String _UploadURL = "";
public String _OwnAddress= "";

private AtomParser _GDocParser;

// - get/set -------------------------------------------------------------
public String getAuthToken() { return _AuthToken; }
public int getGDocItemCount() { return _GDocItems.size(); }
public GoogleDocItem getGDocItem(int i) { return _GDocItems.get(i); }

public String get_DocListURL() { return FILE_LIST_URL; }
public String get_DocAclURL( String _res_id ) { return get_DocListURL() + "/" + _res_id + "/acl"; }
public String get_UploadURL() { return _UploadURL; }
public String get_UploadFileMeta(String t) { return String.format(FILE_UPLOAD1,t); }
public void set_UploadURL(String _str) { _UploadURL = _str; }

public String get_OwnAddress() {
return _OwnAddress;
}
public void set_OwnAddress(String _OwnAddress) {
this._OwnAddress = _OwnAddress;
}

/**
* バッチ更新用のURLを取得する。
*/
public String get_AclLinkBatchUpdate( String _res_id ) {
return get_DocAclURL( _res_id ) + "/batch";
}

// - inner class ---------------------------------------------------------

/**
* Google DocへのHTTP問い合わせで使う基本的な HttpRequestInitializer
*/
class GDAHttpRequestInitializer implements HttpRequestInitializer
{
protected GoogleHeaders _Gheaders;

@Override
public void initialize(HttpRequest request)
{
// Google ヘッダを設定する。書き方のルールは下記を参照すること。
// 参考URL : http://javadoc.google-api-java-client.googlecode.com/hg/1.6.0-beta/com/google/api/client/googleapis/GoogleHeaders.html
_Gheaders = new GoogleHeaders();

_Gheaders.setApplicationName("tatsu-Mandala9/3.0");
// headers.setDeveloperId(); <- Youtubeの時だけ指定するみたい?
_Gheaders.setGoogleLogin( _AuthToken );

_Gheaders.gdataVersion = "3.0";

request.setHeaders( _Gheaders );
}
}

/**
* Google DocへのアップロードのPOST初回問い合わせで使う HttpRequestInitializer
*/
class GDAMetaHttpRequestInitializer extends GDAHttpRequestInitializer
{
Long _ContentLeng;
String _ContentType;
String _FileTitle; // 送信するファイル名
Long _DataLeng;

public GDAMetaHttpRequestInitializer(
long _cont_leng,
String _cont_type,
String _file_title,
long _data_leng
)
{
_ContentLeng = _cont_leng; //(long) 359;
_ContentType = _cont_type;
_FileTitle = _file_title;
_DataLeng = _data_leng;
}

@Override
public void initialize(HttpRequest request)
{
super.initialize( request );

// 参考URL : http://stackoverflow.com/questions/6692604/411-length-required-response-from-google-docs-api-using-android-api-10-and-bel

// 今この送るデータ情報
_Gheaders.setContentLength( _ContentLeng.toString() );
_Gheaders.setContentType( CONTENT_TYPE_APP_ATOM_XML );

// ファイル名をセットする。
_Gheaders.setSlugFromFileName( _FileTitle );

// 送信するデータ情報
_Gheaders.put( "X-Upload-Content-Type" , _ContentType );
_Gheaders.put( "X-Upload-Content-Length", _DataLeng.toString() );
}
}

/**
* Google DocへのアップロードのPOST初回問い合わせで使う HttpRequestInitializer
*/
class GDAUpdateHttpRequestInitializer extends GDAHttpRequestInitializer
{
String _ContentType;
Long _DataLeng;

public GDAUpdateHttpRequestInitializer(
String _cont_type,
long _data_leng
)
{
_ContentType = _cont_type;
_DataLeng = _data_leng;
}

@Override
public void initialize(HttpRequest request)
{
super.initialize( request );

// "*" の指定は、ETagを見ることなくアップロード?
_Gheaders.setIfMatch("*");

// 今この送るデータ情報
_Gheaders.setContentLength( _DataLeng.toString() );
_Gheaders.setContentType( _ContentType );

// 送信するデータ情報
_Gheaders.put( "X-Upload-Content-Length", _DataLeng.toString() );
_Gheaders.put( "X-Upload-Content-Type" , _ContentType );
}
}

/**
* Google DocへのアップロードのPUTデータ問い合わせで使う HttpRequestInitializer
*/
class GDAContentHttpRequestInitializer extends GDAHttpRequestInitializer
{
private int _Offset;
private int _Length;
private long _DataLeng;
private String _DataType;

public GDAContentHttpRequestInitializer(
int _offset,
int _length,
long _data_leng,
String _data_type
)
{
_Offset = _offset;
_Length = _length;

_DataLeng = _data_leng;
_DataType = _data_type;

// 送信データサイズがデータ長を超えたら、送信サイズを小さくする。
if( _offset+_length > _data_leng )
{
long reduce = (_offset+_length) - _data_leng;
_Length -= reduce;
}
}

@Override
public void initialize(HttpRequest request)
{
super.initialize( request );

String range = String.format( "bytes %d-%d/%d", _Offset, (_Offset+_Length-1), _DataLeng );
String length= String.format( "%d", _Length );

_Gheaders.setContentLength( length );
_Gheaders.setContentType( _DataType );
_Gheaders.setContentRange( range );
}
}

/**
* Google DocへのアップロードのPOST初回問い合わせで使う HttpRequestInitializer
*/
class GDADeleteHttpRequestInitializer extends GDAHttpRequestInitializer
{
String _ETag; // 送信するファイル名

public GDADeleteHttpRequestInitializer(
String _etag
)
{
// if( _etag.startsWith("\"") && _etag.endsWith( "\"" ) ) {
// _etag = _etag.substring( 1, _etag.length()-1 );
// }

_ETag = _etag;
}

@Override
public void initialize(HttpRequest request)
{
super.initialize( request );

// 削除する if-match 情報
_Gheaders.setIfMatch( _ETag );
}
}

/**
* 送信するコンテンツ
*/
class GDAHttpContent implements HttpContent
{
private final String ENCODING = "identity"; // "gzip";
// private final String CHARCODE = "UTF-8";

private byte[] _ContentData;
private int _Offset;
private int _Length;
private String _Type;

// - get/set ---------------------------------------------------------
public int get_Offset() { return _Offset; }
public void set_Offset(int _off) { this._Offset = _off; }

public int get_Length() { return _Length; }
public void set_Length(int _len) { this._Length = _len; }

// - public method ---------------------------------------------------
public GDAHttpContent(
byte[] _data,
String _type
)
{
_ContentData = _data;
_Offset = 0;
_Length = ( _data.length < CHUNK_SIZE )? _data.length: CHUNK_SIZE;
_Type = _type;
}

public GDAHttpContent(
byte[] _data,
int _off,
int _len,
String _type
)
{
_ContentData = _data;
_Offset = _off;
_Length = _len;
_Type = _type;

if( _off+_len > _data.length )
{
long reduce = (_off+_len) - _data.length;
_Length -= reduce;
}
}

@Override
public long getLength() throws IOException {
return _ContentData.length;
}

@Override
public String getEncoding() {
// 参考URL : http://www.kawa.net/works/perl/contenc/gzip-test.html
return ENCODING;
}

@Override
public String getType() {
return _Type;
}

@Override
public void writeTo(OutputStream out) throws IOException
{
// 参考URL : http://www.cresc.co.jp/tech/java/Servlet_Tutorial/Lesson_35.htm

out.write( _ContentData, _Offset, _Length );
}

@Override
public boolean retrySupported() {
return true;
}
}

/**
* POST送信時のレスポンスを解析するためのclass
*/
class GDAResponseHttpHeaders extends HttpHeaders
{
private int _StatusCode;

GDAResponseHttpHeaders() {
_StatusCode = 0;
}

public int get_StatusCode() { return _StatusCode; }
public void set_StatusCode(int _st) { _StatusCode = _st; }
}

// - public method -------------------------------------------------------

/**
* constractor
*/
public GoogleDocAccess(
String _authToken
)
{
_AuthToken = _authToken;

// ドキュメントアイテムを覚えておくところ。
_GDocItems = new ArrayList();

// ファイル一覧を取得する。
// getGDocItems();

// 1. AtomParser を準備する。
// 参考URL : http://abekatsu.blogspot.com/2011/04/access-token-access-tokensecret-spread.html
// 参考URL : http://code.google.com/intl/ja/apis/documents/docs/3.0/developers_guide_protocol.html#API
// ↑の タグ内の xmlns を参照した。

XmlNamespaceDictionary ns = new XmlNamespaceDictionary();

ns.set( "", Atom.ATOM_NAMESPACE );
ns.set( "openSearch", "http://a9.com/-/spec/opensearch/1.1/" );
ns.set( "docs", "http://schemas.google.com/docs/2007" );
ns.set( "batch", "http://schemas.google.com/gdata/batch" );
// ns.set( "gAcl", "http://schemas.google.com/acl/2007" );
ns.set( "gd", "http://schemas.google.com/g/2005" );
ns.set( "gd:etag", "W/\"CkcMQH0zcSt7ImA9WhdQF0w.\"" );

_GDocParser = new AtomParser( ns );
}

/**
* Google Docment のファイル一覧を取得する。
* @throws HttpResponseException
*/
public void getGDocItems(
String _url
) throws HttpResponseException
{
Log.d("GoogleDocAccess", "getGDocItems");

// 今のアイテムをクリアする。
_GDocItems.clear();

// HTTP通信を実行する。
String xml = "";
GDAHttpRequestInitializer http_init =
new GDAHttpRequestInitializer();

InputStream inp = getGoogleDocInputStream(
_url,
GoogleDocAccess.Method.GET,
http_init,
null,
_GDocParser, null
);

if( inp != null )
{
// レスポンスXMLを取得する。
xml = getStringFromInputStream( inp );

if( xml.length() > 0 )
{
// 取得したXMLを解析する。
AnalyzXml( xml, _GDocItems );
}
}
}

/**
* Google Docment のファイル一覧をアクセスコントロール情報付きで取得する。
* @throws HttpResponseException
*/
public void getGDocItemsAcl() throws HttpResponseException
{
// 1. まずファイル一覧を取得する。
getGDocItems( get_DocListURL() );

// 2. 個別のファイル属性を取得する。
for( GoogleDocItem item : _GDocItems )
{
// HTTP通信を実行する。
String xml = "";
GDAHttpRequestInitializer http_init =
new GDAHttpRequestInitializer();

InputStream inp = getGoogleDocInputStream(
get_DocAclURL( item.get_ResourceId() ),
GoogleDocAccess.Method.GET,
http_init,
null,
_GDocParser, null
);

if( inp != null )
{
// レスポンスXMLを取得する。
xml = getStringFromInputStream( inp );

if( xml.length() > 0 )
{
item.clearRoleScope();

// 取得したXMLを解析する。
AnalyzXmlAcl( xml, item );
}
}
}
}

/**
* Google Docにアクセスして、レスポンスのInputStreamを取得する。
* @param _url
* @return
* @throws HttpResponseException
*/
public InputStream getGoogleDocInputStream(
String _url
) throws HttpResponseException
{
GDAHttpRequestInitializer init = new GDAHttpRequestInitializer();

return getGoogleDocInputStream(
_url, GoogleDocAccess.Method.GET,
init,
null, null, null
);
}

/**
* Google Docにアクセスして、ファイルをアップロードする。
* @param _title // I:ファイルタイトル
* @param _data // I:送信データ
* @param _type // I:Content-Type
* @return
* @throws HttpResponseException
*/
public boolean uploadFile(
String _title, // I:ファイルタイトル
byte[] _data, // I:ファイルデータ
String _cont_type // I:Content-Type
) throws HttpResponseException
{
String meta_data = get_UploadFileMeta( _title );
byte[] byte_meta = meta_data.getBytes();

// 1. 送信メタデータと内容を準備
GDAMetaHttpRequestInitializer meta_head =
new GDAMetaHttpRequestInitializer(
byte_meta.length,
_cont_type,
_title,
_data.length
);

GDAHttpContent http_cont =
new GDAHttpContent( byte_meta, _cont_type );

// 2. ファイルを作成するためのメタデータをPOSTする。
GDAResponseHttpHeaders resp_head = new GDAResponseHttpHeaders();

InputStream inp = getGoogleDocInputStream(
get_UploadFileURL( false ), // Fileのアップロードは必ず conv false を指定するようです.
GoogleDocAccess.Method.POST,
meta_head,
http_cont, _GDocParser, resp_head
);

if( inp == null ) {
return false; // 失敗。
}

if( resp_head.get_StatusCode() != HTTP_ST_SUCCESS ) {
return false; // 失敗。
}

// 3. Locationを取出して送信する。
String upload_url = (String) resp_head.get(NEXT_LOCATION);

// 4. 送信データを用意する。
GDAHttpContent send_cont =
new GDAHttpContent( _data, 0, CHUNK_SIZE, _cont_type );

// 5. 送信する。
boolean st = resumableUpload(
_data, _cont_type, resp_head, upload_url, send_cont
);

return st;
}

/**
*
* @param _data
* @param _cont_type
* @param resp_head
* @param upload_url
* @param send_cont
* @return
* @throws HttpResponseException
*/
private boolean resumableUpload(
byte[] _data,
String _cont_type,
GDAResponseHttpHeaders resp_head,
String upload_url,
GDAHttpContent send_cont
) throws HttpResponseException
{
InputStream inp;
int offset = 0;
long data_leng = _data.length;
boolean st = true;
String xml = "";

while( offset < data_leng )
{
send_cont.set_Offset( offset );

GDAContentHttpRequestInitializer cont_head =
new GDAContentHttpRequestInitializer(
offset, CHUNK_SIZE, data_leng, _cont_type
);

// データを送信する。
inp = getGoogleDocInputStream(
upload_url,
GoogleDocAccess.Method.PUT,
cont_head,
send_cont, null, resp_head
);

// レスポンスにより、次のデータを送っていいか確認する。
int status_code = resp_head.get_StatusCode();

switch( status_code ) {
case HTTP_ST_SUCCESS:
{
// 次のデータを送ってOK
offset += send_cont.get_Length();
upload_url = (String) resp_head.get( NEXT_LOCATION );
break;
}

case HTTP_ST_COMPLETE_UPLOAD: {
// ドキュメントが作成されたのでループを終了する。
xml = getStringFromInputStream( inp );

st = true;
offset += CHUNK_SIZE;
break;
}

case HTTP_ST_BAD_REQUEST: {
// 失敗した
st = false;
break;
}

case HTTP_ST_RESENT_CONTENT:
{
// 指定されたロケーションに再送信を試みる。
upload_url = (String) resp_head.get( NEXT_LOCATION );
}

default : {
// 他の何らかのエラーが発生した。
break;
}
}
}
return st;
}

/**
* Google Docにアクセスして、ファイルを更新する。
* @param _title // I:ファイルタイトル
* @param _data // I:送信データ
* @param _type // I:Content-Type
* @return
* @throws HttpResponseException
*/
public boolean updateFile(
byte[] _data, // I:ファイルデータ
String _update_url, // I:Content-Type
String _cont_type // I:Content-Type
) throws HttpResponseException
{
// 1. 送信メタデータと内容を準備
GDAUpdateHttpRequestInitializer meta_head =
new GDAUpdateHttpRequestInitializer(
_cont_type,
_data.length
);

GDAHttpContent http_cont =
new GDAHttpContent( _data, _cont_type );

// 2. ファイルを更新するための初回データをPUTする。
GDAResponseHttpHeaders resp_head = new GDAResponseHttpHeaders();

InputStream inp = getGoogleDocInputStream(
_update_url,
GoogleDocAccess.Method.PUT,
meta_head,
http_cont, _GDocParser, resp_head
);

if( inp == null ) {
return false; // 失敗。
}

if( resp_head.get_StatusCode() != HTTP_ST_SUCCESS ) {
return false; // 失敗。
}

// 3. Locationを取出して送信する。
String upload_url = (String) resp_head.get(NEXT_LOCATION);

// 4. 送信データを用意する。
GDAHttpContent send_cont =
new GDAHttpContent( _data, 0, CHUNK_SIZE, _cont_type );

// 5. 送信する。
boolean st = resumableUpload(
_data, _cont_type, resp_head, upload_url, send_cont
);

return st;
}

/**
* Google Docにアクセスして、ファイルをアップロードする。
* @param _path // I:contentタグのsrc
* @return
* @throws HttpResponseException
*/
public boolean deleteFile(
String _path
) throws HttpResponseException
{
// DocItemを取得する。
String res_id = getResourceIdFromContentSrc( _path );

GoogleDocItem doc_item = getDocItemFromResourceId( res_id );

// 取得したリソースIDを削除するためのHTTP通信を行う。

// 1. 送信メタデータと内容を準備
GDADeleteHttpRequestInitializer delete_head =
new GDADeleteHttpRequestInitializer(
doc_item.get_ETag()
);

// 2. ファイルを削除するためのHttp通信を実行。
GDAResponseHttpHeaders resp_head = new GDAResponseHttpHeaders();

InputStream inp = getGoogleDocInputStream(
doc_item.get_DeleteUrl( true ),
GoogleDocAccess.Method.DELETE,
delete_head,
null, _GDocParser, resp_head
);

if( inp == null ) {
return false; // 失敗。
}

if( resp_head.get_StatusCode() != HTTP_ST_SUCCESS ) {
return false; // 失敗。
}

return true; // 成功
}

/**
* アップロード先のURLを取得する。
* @param _conv_format
* @return
* @throws HttpResponseException
*/
public String get_UploadFileURL(
boolean _conv_format
) throws HttpResponseException
{
if( _UploadURL.length() <= 0 )
{
// アップロード先のURLを取得する。
getGDocItems( get_DocListURL() );
}

return ( _conv_format )? _UploadURL: _UploadURL + FILE_NO_CONV;
}

/**
* 指定したファイルのAcl default属性を変更する。
* @param _file_path
* @param _role_type
* @param _scope_type
* @param remove_attr
* @return
* @throws HttpResponseException
*/
public boolean changeFileAttrDefault(
String _file_path,
AclRoleType _bfr_role,
AclRoleType _aft_role,
boolean _open_web
) throws HttpResponseException
{
if( _bfr_role == _aft_role ) {
return true;
}

// DocItemを取得する。
String res_id = getResourceIdFromContentSrc( _file_path );

GoogleDocItem doc_item = getDocItemFromResourceId( res_id );

boolean st = false;

if( (_bfr_role == AclRoleType.READER || _bfr_role == AclRoleType.WRITER) &&
(_aft_role == AclRoleType.READER || _aft_role == AclRoleType.WRITER)
)
{
// 取得したリソースIDのファイル属性を変更するためのHTTP通信を行う。
st = delFileAttrDefault( doc_item, _aft_role );

if( st ) {
st = addFileAttrDefault( doc_item, _aft_role, _open_web );
}
}
else if((_bfr_role == AclRoleType.NONE ) &&
(_aft_role == AclRoleType.READER || _aft_role == AclRoleType.WRITER)
)
{
// 取得したリソースIDのファイル属性を追加するためのHTTP通信を行う。
st = addFileAttrDefault( doc_item, _aft_role, _open_web );
}
else if((_bfr_role == AclRoleType.READER || _bfr_role == AclRoleType.WRITER) &&
(_aft_role == AclRoleType.NONE )
)
{
// 取得したリソースIDのファイル属性を削除するためのHTTP通信を行う。
st = delFileAttrDefault( doc_item, _aft_role );
}

return st;
}

/**
* 指定したファイルのAcl メンバー属性を変更する。
* @param _file_path
* @param _reader
* @param _r_to_w
* @param _r_to_n
* @param _writer
* @param _w_to_r
* @param _w_to_n
* @return
* @throws HttpResponseException
*/
public boolean changeFileAttr(
String _file_path,
ArrayList _reader,
ArrayList _r_to_w,
ArrayList _r_to_n,
ArrayList _writer,
ArrayList _w_to_r,
ArrayList _w_to_n
) throws HttpResponseException
{
// DocItemを取得する。
String res_id = getResourceIdFromContentSrc( _file_path );

// GoogleDocItem doc_item = getDocItemFromResourceId( res_id );

// 更新するためのXML文字列を作成する。
String xml = makeXmlForBatchUpdate(
res_id, _OwnAddress,
_reader, _r_to_w, _r_to_n, _writer, _w_to_r, _w_to_n
);
byte[] byte_meta = xml.getBytes();

// 属性の変更をまとめてバッチ実行する。

// 1. 送信メタデータと内容を準備
GDAHttpRequestInitializer update_acl_head =
new GDAHttpRequestInitializer();

GDAHttpContent http_cont =
new GDAHttpContent( byte_meta, CONTENT_TYPE_XML );

// 2. ファイル属性を更新するためのHttp通信を実行。
GDAResponseHttpHeaders resp_head = new GDAResponseHttpHeaders();

String url = get_AclLinkBatchUpdate( res_id );

InputStream inp = getGoogleDocInputStream(
url,
GoogleDocAccess.Method.POST,
update_acl_head,
http_cont, _GDocParser, resp_head
);

if( inp == null ) {
return false; // 失敗。
}

if( resp_head.get_StatusCode() != HTTP_ST_SUCCESS ) {
return false; // 失敗。
}

return true; // 成功
}

/**
* ファイルの共有を通知する。 TODO
* @return
* @throws HttpResponseException
*/
public boolean notifyFileShare(
String res_id
) throws HttpResponseException
{
// 1. 送信メタデータと内容を準備
GDAHttpRequestInitializer update_acl_head =
new GDAHttpRequestInitializer();

// 2. ファイル属性を更新するためのHttp通信を実行。
GDAResponseHttpHeaders resp_head = new GDAResponseHttpHeaders();

String url = get_DocAclURL( res_id );
url += "?send-notification-emails=true";

InputStream inp = getGoogleDocInputStream(
url,
GoogleDocAccess.Method.GET,
update_acl_head,
null, _GDocParser, resp_head
);

if( inp == null ) {
return false; // 失敗。
}

if( resp_head.get_StatusCode() != HTTP_ST_SUCCESS ) {
return false; // 失敗。
}

return true; // 成功
}

/**
* タグを再取得できるURLを作成する。
* @param _res_id
* @return
*/
public String get_EntryGetUrl(
String _res_id
)
{
String author_mail = "";

// リソースIDからアイテムの著者を取得する。
for( GoogleDocItem item : _GDocItems )
{
if( item.get_ResourceId().equals( _res_id ) )
{
author_mail = item.get_AuthorMail();
break;
}
}

// URLを作成する。
String url = String.format( FILE_ENTRY_URL, author_mail, _res_id );

return url;
}

// - private method ------------------------------------------------------

/**
* 指定したファイルのAcl default属性を追加する。
* @param _doc_item
* @param _role_type
* @return
* @throws HttpResponseException
*/
private boolean addFileAttrDefault(
GoogleDocItem _doc_item,
AclRoleType _role_type,
boolean _open_web
) throws HttpResponseException
{
if( _role_type == AclRoleType.OWNER ) {
return false; // OWNER の default属性は変更不可
}

// 1. 送信メタデータと内容を準備
GDAHttpRequestInitializer update_acl_head =
new GDAHttpRequestInitializer();

String role = "";
String scope = GoogleDocItemAcl.SCOPE_DEFAULT;
String value = "";

// role
if( _role_type == AclRoleType.NONE ) {
role = GoogleDocItemAcl.ROLE_NONE;
}
else if( _role_type == AclRoleType.READER ) {
role = GoogleDocItemAcl.ROLE_READER;
}
else if( _role_type == AclRoleType.WRITER ) {
role = GoogleDocItemAcl.ROLE_WRITER;
}

String meta = "";
// String meta = String.format( FILE_ACL_UPDATE, role );
if( _open_web ) {
meta = String.format( FILE_ACL_UPDATE_DEFAULT1, role );
}
else {
meta = String.format( FILE_ACL_UPDATE_DEFAULT2, role );
}

GDAHttpContent http_cont =
new GDAHttpContent( meta.getBytes(), GoogleDocAccess.CONTENT_TYPE_APP_ATOM_XML ); // CONTENT_TYPE_TEXT );//CONTENT_TYPE_XML );

// 2. ファイル属性を更新するためのHttp通信を実行。
GDAResponseHttpHeaders resp_head = new GDAResponseHttpHeaders();

String url = get_DocAclURL( _doc_item.get_ResourceId() );

InputStream inp = getGoogleDocInputStream(
url,
GoogleDocAccess.Method.POST,
update_acl_head,
http_cont, _GDocParser, resp_head
);

if( inp == null ) {
return false; // 失敗。
}

if( resp_head.get_StatusCode() != HTTP_ST_COMPLETE_UPDATE ) {
return false; // 失敗。
}

return true; // 成功
}

/**
* 指定したファイルのAcl default属性を削除する。
* @param _doc_item
* @param _role_type
* @return
* @throws HttpResponseException
*/
private boolean delFileAttrDefault(
GoogleDocItem _doc_item,
AclRoleType _role_type
) throws HttpResponseException
{
if( _role_type == AclRoleType.OWNER ) {
return false; // OWNER の default属性は変更不可
}

// 1. 送信メタデータと内容を準備
GDAHttpRequestInitializer update_acl_head =
new GDAHttpRequestInitializer();

// 2. ファイル属性を更新するためのHttp通信を実行。
GDAResponseHttpHeaders resp_head = new GDAResponseHttpHeaders();

String url = _doc_item.get_AclLinkEditDefault();

InputStream inp = getGoogleDocInputStream(
url,
GoogleDocAccess.Method.DELETE,
update_acl_head,
null, _GDocParser, resp_head
);

if( inp == null ) {
return false; // 失敗。
}

if( resp_head.get_StatusCode() != HTTP_ST_SUCCESS ) {
return false; // 失敗。
}

return true; // 成功
}

/**
* Google Docにアクセスして、レスポンスのInputStreamを取得する。
* @param _url
* @param _method
* @param _http_init
* @param _post_content
* @param parser
* @return
* @throws HttpResponseException
*/
private InputStream getGoogleDocInputStream(
String _url,
GoogleDocAccess.Method _method,
GDAHttpRequestInitializer _http_init,
HttpContent _http_content, // POST/PUT送信コンテンツ
AtomParser parser,
GDAResponseHttpHeaders _resp_head
) throws HttpResponseException
{
Log.d("GoogleDocAccess", "getGoogleDocInputStream:" + _AuthToken );

// 参考URL : http://code.google.com/p/google-api-java-client/wiki/SampleProgram のYouTube

// 1. set up the HTTP request factory
HttpTransport transport = new NetHttpTransport();

HttpRequestFactory factory = transport.createRequestFactory( _http_init );

// 2. URLにアクセスして、InputStreamを取得する。
InputStream ret = null;

try {
GoogleUrl g_url = new GoogleUrl( _url );
HttpRequest request = null;

switch( _method )
{
case GET: {
request = factory.buildGetRequest( g_url );
break;
}

case POST: {
request = factory.buildPostRequest( g_url, _http_content );
break;
}

case PUT: {
request = factory.buildPutRequest( g_url, _http_content );
break ;
}

case DELETE: {
request = factory.buildDeleteRequest( g_url );
break ;
}
}

if( parser != null )
{
// Parserをセットして、リクエストを送信する。
request.addParser( parser );
}

Log.d("GoogleDocAccess", "getGoogleDocInputStream:request.execute()");

HttpResponse resp = request.execute();

// ステータスコードとヘッダを取得する。
if( _resp_head != null )
{
Log.d("GoogleDocAccess", "getGoogleDocInputStream:request.execute()");

_resp_head.set_StatusCode( resp.getStatusCode() );
_resp_head.putAll( resp.getHeaders() );
}

// 出力を取得するストリームを取得する。
ret = resp.getContent();
}
catch (HttpResponseException e) {
Log.d("GoogleDocAccess", "getGoogleDocInputStream:HttpResponseException");
e.printStackTrace();
throw e;
}
catch (IOException e) {
Log.d("GoogleDocAccess", "getGoogleDocInputStream:IOException");
e.printStackTrace();
}
catch (Exception e) {
Log.d("GoogleDocAccess", "getGoogleDocInputStream:Exception");
e.printStackTrace();
}

// x. InputStreamを返す。
return ret;
}

/**
* 取得したXML文字列を解析する。
* 参考URL : http://code.google.com/intl/ja/apis/documents/docs/3.0/developers_guide_protocol.html
*/
private void AnalyzXml(
String _xml,
ArrayList _gDocItems
)
{
XmlPullParser xmlPullParser = Xml.newPullParser();

try {
xmlPullParser.setInput( new StringReader ( _xml ) );
} catch (XmlPullParserException e) {
Log.d("XmlPullParserSample", "Error");
}

try {
int eventType;
eventType = xmlPullParser.getEventType();

while (eventType != XmlPullParser.END_DOCUMENT)
{
if(eventType == XmlPullParser.START_DOCUMENT) {
Log.d("XmlPullParserSample", "Start document");
}
else if(eventType == XmlPullParser.END_DOCUMENT) {
Log.d("XmlPullParserSample", "End document");
}
else if(eventType == XmlPullParser.START_TAG) {
Log.d("XmlPullParserSample", "Start tag "+xmlPullParser.getName());

String tag_name = xmlPullParser.getName();

if( tag_name.equals( TAG_FEED ) )
{
;
}
else if( tag_name.equals( TAG_EMAIL ) )
{
// emailタグを見つけた。
_OwnAddress = xmlPullParser.nextText();
}
else if( tag_name.equals( TAG_ENTRY ) )
{
// entry タグを見つけた。
GoogleDocItem doc_item = new GoogleDocItem();

// のetag属性を取得する。
String etag = xmlPullParser.getAttributeValue(
TAG_ENTRY_ATT_GD_ETAG_NS,
TAG_ENTRY_ATT_GD_ETAG
);

doc_item.set_ETag( etag );

// タグの内側を解析する。
boolean st = AnalyzTagEntry( xmlPullParser, doc_item );

// 成功したらアイテムを追加する。
if( st ) {
_gDocItems.add( doc_item );
}
}
else if( tag_name.equals( TAG_LINK ) )
{
// link タグを見つけた。

// rel/href 属性を取得する。
String rel = xmlPullParser.getAttributeValue( null, TAG_LINK_ATT_REL );
String href= xmlPullParser.getAttributeValue( null, TAG_LINK_ATT_HREF );

// rel属性に、resumable があったらアップロード先を覚える。
if( rel.contains(RCM) ) {
set_UploadURL( href );
}
}
}
else if(eventType == XmlPullParser.END_TAG) {
Log.d("XmlPullParserSample", "End tag "+xmlPullParser.getName());
}
else if(eventType == XmlPullParser.TEXT) {
Log.d("XmlPullParserSample", "Text "+xmlPullParser.getText());
}

// 次の解析に進む
eventType = xmlPullParser.next();
}
}
catch (Exception e) {
Log.d("XmlPullParserSample", "Error");
}
}

/**
* ドキュメントアイテム情報を取得する。
* @param xmlPullParser // I:
* @param _doc_item // O:
*/
private boolean AnalyzTagEntry(
XmlPullParser xmlPullParser,
GoogleDocItem _doc_item
)
{
boolean st = true;

try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

// は解析済みなので1つすすめる。
xmlPullParser.next();

int eventType = xmlPullParser.getEventType();
String tag_text;
String tag_name;
boolean author = false;

while (eventType != XmlPullParser.END_DOCUMENT)
{
tag_name = xmlPullParser.getName();

if(eventType == XmlPullParser.START_TAG)
{
if( tag_name.equals( TAG_UPDATED ) )
{
// 次のテキストを読み取り、ファイル更新日付を解析する。
tag_text = xmlPullParser.nextText();

Date date = sdf.parse( tag_text );
_doc_item.set_Update( date );
}
else if( tag_name.equals( TAG_FILE_NAME ) )
{
// 次のテキストを読み取り、ファイル名をセットする。
// (タグはとなっているが、文字列は"filename"で取り出されてた。)
tag_text = xmlPullParser.nextText();

_doc_item.set_FileName( tag_text );
}
else if( tag_name.equals( TAG_TITLE ) )
{
// 次のテキストを読み取り、タイトルをセットする。
tag_text = xmlPullParser.nextText();

_doc_item.set_Title( tag_text );
}
else if( tag_name.equals( TAG_CONTENT ) )
{
// src 属性を取得する。
String url = xmlPullParser.getAttributeValue( null, TAG_CONTENT_ATT_SRC );

_doc_item.set_ContentSrc( url );
}
else if( tag_name.equals( TAG_GD_RESOURCEID ) )
{
// 次のテキストを読み取り、リソースIDをセットする。
tag_text = xmlPullParser.nextText();

_doc_item.set_ResourceId( tag_text );
}
else if( tag_name.equals( TAG_LINK ) )
{
// rel/href 属性を取得する。
String rel = xmlPullParser.getAttributeValue( null, TAG_LINK_ATT_REL );
String href= xmlPullParser.getAttributeValue( null, TAG_LINK_ATT_HREF );

if( rel.equals( TAG_LINK_REL_VAL_EDIT ) )
{
_doc_item.set_EditUrl( href );
}
else if( rel.equals( TAG_LINK_REL_VAL_EDIT_MEDIA ) )
{
_doc_item.set_EditMediaUrl( href );
}
else if( rel.equals( TAG_LINK_REL_VAL_RESUM_EDIT_MEDIA ) )
{
_doc_item.set_ResumableEditMediaUrl( href );
}
}
else if( tag_name.equals( TAG_AUTHOR ) )
{
author = true; // 著者読み込み中
}
else if( author && tag_name.equals( TAG_NAME ) )
{
// 著者名
tag_text = xmlPullParser.nextText();

_doc_item.set_AuthorName( tag_text );
}
else if( author && tag_name.equals( TAG_EMAIL ) )
{
// 著者メールアドレス
tag_text = xmlPullParser.nextText();

_doc_item.set_AuthorMail( tag_text );
}
}
else if(eventType == XmlPullParser.END_TAG)
{
if( tag_name.equals( TAG_ENTRY ) ) {
// entry タグが終了したら終了。
break;
}
else if( tag_name.equals( TAG_AUTHOR ) ) {
// author タグが終了した。
author = false;
}
}

// 次の解析に進む
eventType = xmlPullParser.next();
}
}
catch (Exception e)
{
// 何らかのエラーが発生した。
st = false;
}

return st;
}

/**
* 取得したXML文字列を解析する。
* @param _xml
* @param _doc_item
*/
private void AnalyzXmlAcl(
String _xml,
GoogleDocItem _doc_item
)
{
XmlPullParser xmlPullParser = Xml.newPullParser();

try {
xmlPullParser.setInput( new StringReader ( _xml ) );
} catch (XmlPullParserException e) {
Log.d("XmlPullParserSample", "Error");
}

try {
int eventType;
eventType = xmlPullParser.getEventType();

while (eventType != XmlPullParser.END_DOCUMENT)
{
if(eventType == XmlPullParser.START_DOCUMENT) {
;
}
else if(eventType == XmlPullParser.END_DOCUMENT) {
;
}
else if(eventType == XmlPullParser.START_TAG) {
;

String tag_name = xmlPullParser.getName();

if( tag_name.equals( TAG_FEED ) )
{
;
}
else if( tag_name.equals( TAG_ENTRY ) )
{
// entry タグを見つけた。

// のetag属性を取得する。
String etag = xmlPullParser.getAttributeValue(
TAG_ENTRY_ATT_GD_ETAG_NS,
TAG_ENTRY_ATT_GD_ETAG
);

// _doc_item.set_ETagAcl( etag );

// タグの内側を解析する。
AnalyzTagEntryAcl( xmlPullParser, _doc_item );
}
else if( tag_name.equals( TAG_LINK ) )
{
// link タグを見つけた。
;
}
}
else if(eventType == XmlPullParser.END_TAG) {
;
}
else if(eventType == XmlPullParser.TEXT) {
;
}

// 次の解析に進む
eventType = xmlPullParser.next();
}
}
catch (Exception e) {
;
}
}

/**
* ドキュメントアイテムAcl情報を取得する。
* @param xmlPullParser // I:
* @param _doc_item // O:
*/
private boolean AnalyzTagEntryAcl(
XmlPullParser xmlPullParser,
GoogleDocItem _doc_item
)
{
boolean st = true;

String role = "";
String scope_type = "";
String scope_value = "";

GoogleDocItemAcl doc_acl = new GoogleDocItemAcl();

try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

// は解析済みなので1つすすめる。
xmlPullParser.next();

int eventType = xmlPullParser.getEventType();
String tag_text;
String tag_name;

while (eventType != XmlPullParser.END_DOCUMENT)
{
if(eventType == XmlPullParser.START_TAG)
{
tag_name = xmlPullParser.getName();

if( tag_name.equals( TAG_UPDATED ) )
{
// 次のテキストを読み取り、ファイル更新日付を解析する。
tag_text = xmlPullParser.nextText();

Date date = sdf.parse( tag_text );
_doc_item.set_UpdateAcl( date );
}
else if( tag_name.equals( TAG_FILE_NAME ) )
{
;
}
else if( tag_name.equals( TAG_TITLE ) )
{
;
}
else if( tag_name.equals( TAG_CONTENT ) )
{
;
}
else if( tag_name.equals( TAG_LINK ) )
{
// rel属性を取得する。
String rel = xmlPullParser.getAttributeValue( null, TAG_LINK_ATT_REL );
String href= xmlPullParser.getAttributeValue( null, TAG_LINK_ATT_HREF );

if( rel.equals( TAG_LINK_REL_VAL_EDIT ) )
{
doc_acl.set_LinkEdit( href );
}
}
else if( tag_name.equals( TAG_GACL_ROLE ) )
{
role = xmlPullParser.getAttributeValue( null, TAG_GACL_ATT_VALUE );
}
else if( tag_name.equals( TAG_GACL_SCOPE ) )
{
scope_type = xmlPullParser.getAttributeValue( null, TAG_GACL_ATT_TYPE );
scope_value = xmlPullParser.getAttributeValue( null, TAG_GACL_ATT_VALUE );
}
else if( tag_name.equals( TAG_GACL_WITH_KEY ) )
{
// タグを解析する。
AnalyzTagGAclWithKeyAcl( xmlPullParser, doc_acl );
}
}
else if(eventType == XmlPullParser.END_TAG)
{
// entry タグが終了したら終了。
if( xmlPullParser.getName().equals( TAG_ENTRY ) ) {
break;
}
}

// 次の解析に進む
eventType = xmlPullParser.next();
}
}
catch (Exception e)
{
// 何らかのエラーが発生した。
st = false;
}

// 成功していたら、Role/Scopeを追加する。
if( st )
{
doc_acl.set_Role( role );
doc_acl.set_ScopeType( scope_type );
doc_acl.set_ScopeValue( scope_value );

_doc_item.addRoleScope( doc_acl );
}

return st;
}

/**
* ドキュメントアイテムAcl情報を取得する。
* @param xmlPullParser // I:
* @param _doc_item // O:
*/
private boolean AnalyzTagGAclWithKeyAcl(
XmlPullParser xmlPullParser,
GoogleDocItemAcl _doc_acl
)
{
boolean st = true;

String key = "";
String role = "";
// String value = "";

try {
// のキーを取得する。
key = xmlPullParser.getAttributeValue( null, TAG_GACL_ATT_KEY );

// は解析済みなので1つすすめる。
xmlPullParser.next();

int eventType = xmlPullParser.getEventType();
String tag_name;

while (eventType != XmlPullParser.END_DOCUMENT)
{
if(eventType == XmlPullParser.START_TAG)
{
tag_name = xmlPullParser.getName();

if( tag_name.equals( TAG_GACL_ROLE ) )
{
role = xmlPullParser.getAttributeValue( null, TAG_GACL_ATT_VALUE );
}
}
else if(eventType == XmlPullParser.END_TAG)
{
// タグが終了したら終了。
if( xmlPullParser.getName().equals( TAG_GACL_WITH_KEY ) ) {
break;
}
}

// 次の解析に進む
eventType = xmlPullParser.next();
}
}
catch (Exception e)
{
// 何らかのエラーが発生した。
st = false;
}

// 成功していたら、Role/Scopeを追加する。
if( st ) {
_doc_acl.add_WithKey( key, role );
}

return st;
}

/**
* InputStreamを文字列に変換する。
* @throws IOException
*/
public String getStringFromInputStream( InputStream inp )
{
String res = "";
String str = "";
try {
Log.d("GoogleDocAccess", "getStringFromInputStream");

// null check していないので注意
InputStreamReader inr = new InputStreamReader( inp );
BufferedReader reader = new BufferedReader(inr, 1024);

while ((str = reader.readLine()) != null) {
res += str;
}

reader.close();
inr.close();
}
catch (IOException e)
{
e.printStackTrace();
}

return res;
}

/**
* Google Docにアクセスして、タグのアイテムを再取得する。
* @param _url
* @return
* @throws HttpResponseException
*/
public GoogleDocItem getGoogleDocItemFromEntryUrl(
String _url
) throws HttpResponseException
{
// タグを再取得する。
InputStream inp = getGoogleDocInputStream( _url );

if( inp == null ) {
return null;
}

String xml = getStringFromInputStream( inp );

// タグを解析する。
ArrayList gDocItems;

gDocItems = new ArrayList();

if( xml.length() > 0 ) {
AnalyzXml( xml, gDocItems );
}

// GoogleDocItemを取得する。
GoogleDocItem item = null;

if( gDocItems.size() == 1 ) {
item = gDocItems.get(0);
}

return item;
}

// - private method ------------------------------------------------------

/**
* content の src のURLからリソースIDを取得する。
*/
private String getResourceIdFromContentSrc(
String _src
)
{
for( GoogleDocItem item : _GDocItems )
{
if( item.get_ContentSrc().equals( _src ) ) {
return item.get_ResourceId();
}
}

return "";
}

/**
* リソースIDから、DocItemを取得する。
*/
private GoogleDocItem getDocItemFromResourceId(
String _res
)
{
for( GoogleDocItem item : _GDocItems )
{
if( item.get_ResourceId().equals( _res ) ) {
return item;
}
}

return null;
}

/**
*
*/
// 更新するためのXML文字列を作成する。
private String
makeXmlForBatchUpdate(
String _res_id,
String _own_addr,
ArrayList _reader,
ArrayList _r_to_w,
ArrayList _r_to_n,
ArrayList _writer,
ArrayList _w_to_r,
ArrayList _w_to_n
)
{
// 先頭のXMLを作成する。
String xml = String.format( FILE_ATTR_BATCH_CHAGE, _res_id, _own_addr );
String tmp;

// 各タグをつなげていく。
for( String addr : _reader )
{
tmp = getBatchEntry( _res_id, BATCH_INSERT, BATCH_READER, addr );
xml += tmp;
}

for( String addr : _r_to_w )
{
tmp = getBatchEntry( _res_id, BATCH_UPDATE, BATCH_WRITER, addr );
xml += tmp;
}

for( String addr : _r_to_n )
{
tmp = getBatchEntry( _res_id, BATCH_DELETE, BATCH_READER, addr );
xml += tmp;
}

for( String addr : _writer )
{
tmp = getBatchEntry( _res_id, BATCH_INSERT, BATCH_WRITER, addr );
xml += tmp;
}

for( String addr : _w_to_r )
{
tmp = getBatchEntry( _res_id, BATCH_UPDATE, BATCH_READER, addr );
xml += tmp;
}

for( String addr : _w_to_n )
{
tmp = getBatchEntry( _res_id, BATCH_DELETE, BATCH_WRITER, addr );
xml += tmp;
}

return xml;
}

/**
* バッチ更新用のタグを作成する。
*/
String getBatchEntry(
String _res_id,
String _ins_upd_del,
String _read_write,
String _addr
)
{
String tag;

if( _ins_upd_del.equals( BATCH_INSERT ) )
{
tag = String.format(
FILE_ACL_UPDATE_BATCH,
BATCH_ID_1, _ins_upd_del, _read_write, _addr
);
}
else
{
String tmp = String.format(
BATCH_ID, get_DocAclURL( _res_id ), _addr
);

tag = String.format(
FILE_ACL_UPDATE_BATCH,
tmp, _ins_upd_del, _read_write, _addr
);
}

return tag;
}
}

Android で GoogleDoc にアクセス。

ウェブで結構探しても、なかなかこれってのに出会わなかったので、ブログに書いて残しておきます。Mandala9 で GoogleDoc にアクセするクラスを4つばかり書いたので。

まず Account 情報から、GoogleDoc にアクセスするためのトークンを取得するクラス。M9GoogleDoc クラスの内主要なメンバのみにして公開します。

トークンには有効期限があるので、しばらくしたら(2週間くらい?)更新しなおすする処理(invalidateAuthToken の呼び出しか、AVDの作り直し)が必要。

当初、AVDが定期的にG/Docにアクセスできなくなる原因が分からず、開発環境の不具合とか思ってたけど単なる自分の作りこみが甘かっただけでした。



selectAccount()
端末内のアカウントが複数あれば選択ダイアログを表示して選択する。選択の必要性がなければ、[0]を使う。

getInputStream()~readMandalaListFromGDoc()
別途掲載する、GoogleDocAccessクラスを使って、G/Docを操作する。

ResetAuthToken()
トークンの再発行をするメンバ。再発行の必要性を知らなくてハマった。



public class M9GoogleDoc {

// - static --------------------------------------------------------------
private static final String ACCOUNT_TYPE = "com.google";
private static final String TAG = "GoogleDocsTest";

// - attributes ----------------------------------------------------------
private Activity _Context = null;
private GoogleDocAccess _GDA = null;

// - get/set -------------------------------------------------------------
private GoogleDocAccess getGDoc()
{
if( _GDA == null )
{
// GoogleDocへアクセスしてファイル一覧を、GDocアイテムとして取得する。
setGDA();
}

return _GDA;
}

// - public method -------------------------------------------------------

/**
* constracter
* コンストラクト後に、必ずselectAccount()を呼ぶこと。複数アカウントを一意に決める必要がある。
*/
public M9GoogleDoc( Activity _c )
{
_Context = _c;
}

public M9GoogleDoc( Activity _c, String _auth )
{
_Context = _c;
_GDA = new GoogleDocAccess( _auth );
}

/**
* アカウントを選択する。
*/
String _AccountName;

public int selectAccount()
{
// AccountManager を通じてGoogleアカウントを取得
AccountManager manager = AccountManager.get(_Context);
_Accounts = manager.getAccountsByType( ACCOUNT_TYPE );

int accounts = _Accounts.length;

// 端末にGoogleアカウントが登録されていないと 数が0になるのでチェックする。
if( _Accounts.length <= 0 )
{
Toast.makeText(
_Context, R.string.IO_WARN_NeedGoogleAccount, Toast.LENGTH_SHORT
).show();

_AccountName = null;
}
else if( _Accounts.length == 1 )
{
_AccountName =_Accounts[0].name;
}
else if( _Accounts.length >= 2 )
{
// 入力ダイアログを作る。
M9Dialog dlg = new M9Dialog( _Context );

AccountsList ok = new AccountsList( dlg, M9Dialog.State.OK );
CharSequence[] items = new CharSequence[ _Accounts.length ];

for( int i = 0; i < _Accounts.length; ++i ) {
items[i] = _Accounts[i].name;
}

dlg.selectSortType(
R.string.IO_Mess_SelectAccount,
items,
ok
);
}

return accounts;
}

/**
* GDAオブジェクトを設定する。
* @return
*/
Account[] _Accounts;

public GoogleDocAccess setGDA()
{
genGDA( _AccountName );

return getGDoc();
}

/**
* アカウントから、GoogleDocAccess オブジェクトを作成する。
*/
private AccountManager _Manager;
private Account _Account = null;

public GoogleDocAccess genGDA(
String _acc_name
)
{
// AccountManager を通じてGoogleアカウントを取得
_Manager = AccountManager.get(_Context);

Account[] accounts = _Manager.getAccountsByType( ACCOUNT_TYPE );

// 選択したアカウント名と同じアカウントを取得する。
for( int i = 0; i < accounts.length; ++i ) {
if( accounts[i].name.equals( _acc_name ) ) {
_Account = accounts[i];
break;
}
}

if( _Account == null ) {
return null;
}

// 認証用トークン取得
ResetAuthToken( _Account );

return getGDoc();
}

/**
* 認証文字列を返す。
*/
public String getAuthToken()
{
if( _GDA != null ) {
return _GDA.getAuthToken();
}

return "";
}

/**
* URLからの入力ストリームを取得する。
*/
public InputStream getInputStream(
String _file_path
)
{
InputStream inp = null;

try {
inp = _GDA.getGoogleDocInputStream( _file_path );
}
catch (HttpResponseException e)
{
// トークンの有効期間が切れたかもしれんので、再設定して再実行。
ResetAuthToken( _Account );

try {
inp = _GDA.getGoogleDocInputStream( _file_path );
} catch (HttpResponseException e1) {
e1.printStackTrace();
}

e.printStackTrace();
}

return inp;
}

// - private -------------------------------------------------------------

/**
* GoogleDocにファイルをアップロードする。
*/
public boolean uploadFile(
String _title,
byte[] _data
)
{
String title_ext = _title;

title_ext += ".";
title_ext += M9Const.MANDALA_XML_EXT;

boolean st = false;
try {
st = getGDoc().uploadFile(
title_ext, _data, GoogleDocAccess.CONTENT_TYPE_XML
);
}
catch (HttpResponseException e)
{
// トークンの有効切れかもしれんので、トークンを取得し直す。
ResetAuthToken( _Account );

try {
st = getGDoc().uploadFile(
title_ext, _data, GoogleDocAccess.CONTENT_TYPE_XML
);
} catch (HttpResponseException e1) {
e1.printStackTrace();
}

e.printStackTrace();
}

return st;
}

/**
* GoogleDocにあるファイルをアップデートする。
*/
public boolean updateFile(
byte[] _data,
String _update_url
)
{
boolean st = false;

try {
st = getGDoc().updateFile(
_data, _update_url, GoogleDocAccess.CONTENT_TYPE_XML
);
}
catch (HttpResponseException e)
{
// トークンの有効切れかもしれんので、トークンを取得し直す。
ResetAuthToken( _Account );

try {
st = getGDoc().updateFile(
_data, _update_url, GoogleDocAccess.CONTENT_TYPE_XML
);
} catch (HttpResponseException e1) {
e1.printStackTrace();
}

e.printStackTrace();
}

return st;
}

/**
* 共有を通知する。
* @param _res
*/
public void notifyFileShare(
String _res
)
{
GoogleDocAccess gda = this.getGDoc();
String res = _res;

try {
gda.notifyFileShare( res );
}
catch (HttpResponseException e)
{
// 有効期限切れかもしれんので取得し直す。
ResetAuthToken( _Account );

try {
gda.notifyFileShare( res );
} catch (HttpResponseException e1) {
e1.printStackTrace();
}

e.printStackTrace();
}
}

/**
* ファイル一覧を取得する。
* @param _NewMandItem
*/
public void getFileList(
ArrayList _NewMandItem
)
{
GoogleDocAccess gdoc = this.getGDoc();

// ファイル一覧を取得する。
try {
gdoc.getGDocItems( gdoc.get_DocListURL() );
}
catch (HttpResponseException e)
{
// 有効期限切れかもしれんので取得し直す。
ResetAuthToken( _Account );

try {
gdoc.getGDocItems( gdoc.get_DocListURL() );
} catch (HttpResponseException e1) {
e1.printStackTrace();
}

e.printStackTrace();
}

// G/Docアイテムを表示アイテムに代入する。
readMandalaListFromGDoc( gdoc, _NewMandItem );
}

/**
* ファイル一覧(ACL情報付き)を取得する。
* @param _NewMandItem
*/
public void getFileListAcl(
ArrayList _NewMandItem
)
{
GoogleDocAccess gdoc = this.getGDoc();

// ファイル一覧を取得する。
try {
gdoc.getGDocItemsAcl();
}
catch (HttpResponseException e)
{
// トークンが有効期限切れかもしれんので取得し直す。
ResetAuthToken( _Account );

try {
gdoc.getGDocItemsAcl();
} catch (HttpResponseException e1) {
e1.printStackTrace();
}

e.printStackTrace();
}

// G/Docアイテムを表示アイテムに代入する。
readMandalaListFromGDoc( gdoc, _NewMandItem );
}

/**
* ファイルを削除する。
* @param _file_path
* @return
*/
public boolean deleteFile(
String _file_path
)
{
GoogleDocAccess gda = this.getGDoc();

boolean st = false;
try {
st = gda.deleteFile( _file_path );
}
catch (HttpResponseException e)
{
// トークンが有効期限切れかもしれんので取得し直す。
ResetAuthToken( _Account );

try {
st = gda.deleteFile( _file_path );
} catch (HttpResponseException e1) {
e1.printStackTrace();
}

e.printStackTrace();
}

return st;
}

/**
* ファイルの共有設定を修正する。
* @param _file_path
* @param reader
* @param r_to_w
* @param r_to_n
* @param writer
* @param w_to_r
* @param w_to_n
* @return
*/
public boolean changeAttr(
String _file_path,
ArrayList reader,
ArrayList r_to_w,
ArrayList r_to_n,
ArrayList writer,
ArrayList w_to_r,
ArrayList w_to_n
)
{
GoogleDocAccess gda = this.getGDoc();

boolean st = false;
try {
st = gda.changeFileAttr(
_file_path, reader, r_to_w, r_to_n, writer, w_to_r, w_to_n
);
}
catch (HttpResponseException e)
{
// トークンが有効期限切れかもしれんので取得し直す。
ResetAuthToken( _Account );

try {
st = gda.changeFileAttr(
_file_path, reader, r_to_w, r_to_n, writer, w_to_r, w_to_n
);
} catch (HttpResponseException e1) {
e1.printStackTrace();
}

e.printStackTrace();
}

return st;
}

/**
* 指定したファイルパスのInputStreamを取得する。
*/
public InputStream getGDocInputStream(
String _file_path
)
{
InputStream is = null;

try {
is = getGDoc().getGoogleDocInputStream( _file_path );
}
catch (HttpResponseException e)
{
// トークンが有効期限切れかもしれんので取得し直す。
ResetAuthToken( _Account );

try {
is = getGDoc().getGoogleDocInputStream( _file_path );
} catch (HttpResponseException e1) {
e1.printStackTrace();
}

e.printStackTrace();
}

return is;
}

// - private -------------------------------------------------------------

private void readMandalaListFromGDoc(
GoogleDocAccess gdoc,
ArrayList _mandala_item
)
{
// 取り出したGDocアイテムを
int count = gdoc.getGDocItemCount();
String own_addr = gdoc.get_OwnAddress();

for( int i = 0; i < count; ++i )
{
M9MandalaItem m9_item = new M9MandalaItem();
GoogleDocItem gd_item = gdoc.getGDocItem(i);

// 拡張子が正しいか?
if( gd_item.isFileExt( M9Const.MANDALA_XML_EXT ) )
{
// 編集時間をセット
m9_item.setSaveSec( gd_item.get_Update().getTime() );

// タイトルをセットする
String file_name = gd_item.get_FileNameOnly();

m9_item.setTitle( file_name );

// ファイルパスをセット
m9_item.set_Path( gd_item.get_ContentSrc() );
m9_item.set_Edit( gd_item.get_EditUrl() );
m9_item.set_EditMedia( gd_item.get_EditMediaUrl() );
m9_item.set_ResumableEditMedia(
gd_item.get_ResumableEditMediaUrl()
);

// リソースIDをセット
m9_item.set_ResId( gd_item.get_ResourceId() );

// Acl情報を追加する。
m9_item.set_Roles( gd_item.get_Roles() );

// m9アイテムを追加する。
_mandala_item.add( m9_item );

// オーナーかどうかをセットする。
m9_item.set_Own(
own_addr.equals( gd_item.get_AuthorMail() )
);
}
}

return;
}

/**
* トークンを取得しなおす。
* 参考URL: http://d.hatena.ne.jp/adsaria/20101012/1286886888
* 参考URL: http://stackoverflow.com/questions/7204658/how-can-i-list-google-documents-android
*/
private String _AuthToken = "";
private Bundle _Bundle = null;

private boolean
ResetAuthToken(
Account _account
)
{
Log.d( "M9GoogleDoc", "ResetAuthToken:" + _AuthToken );

// 古いトークンを無効化する。
if( _AuthToken.length() > 0 ) {
_Manager.invalidateAuthToken( ACCOUNT_TYPE, _AuthToken );
}

try {
_Bundle = _Manager.getAuthToken(
_account, // 選択したアカウントでトークンを取得する。
"writely", // ※1
null,
_Context,
null,
null).getResult();
}
catch (OperationCanceledException e) {
Log.e(TAG, "", e);
return false;
}
catch (AuthenticatorException e) {
Log.e(TAG, "", e);
return false;
}
catch (IOException e) {
Log.e(TAG, "", e);
return false;
}

// 認証用トークン取得
_AuthToken = _Bundle.getString( AccountManager.KEY_AUTHTOKEN );

// GoogleDocへアクセスしてファイル一覧を、GDocアイテムとして取得する。
_GDA = new GoogleDocAccess( _AuthToken );

return true;
}
}
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。