Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

FlashAir x Androidアプリ開発ワークショップ コーディングパート

33.511 visualizaciones

Publicado el

FlashAir x Androidアプリ開発ワークショップは、FlashAirと連携したAndroidアプリを作ることを目的に、FlashAirにAndroidデバイスから通信するための基本から、開発に役立つ機能や設定をご説明し、実際のコーディングを行うワークショップです。
この資料はコーディングパートで使用したスライドです。

【開催日】2013年9月18日
【講師】あんざいゆき
【主催】株式会社フィックスターズ

FlashAirで使用可能なAPIの一覧や開発チュートリアル、Q&AフォーラムはFlashAirデベロッパーズにて公開しています。> https://flashair-developers.com

Publicado en: Tecnología, Educación
  • DOWNLOAD FULL BOOKS INTO AVAILABLE FORMAT ......................................................................................................................... ......................................................................................................................... 1.DOWNLOAD FULL PDF EBOOK here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL EPUB Ebook here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL doc Ebook here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL PDF EBOOK here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL EPUB Ebook here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL doc Ebook here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Responder 
    ¿Estás seguro?    No
    Tu mensaje aparecerá aquí

FlashAir x Androidアプリ開発ワークショップ コーディングパート

  1. 1. FlashAir対応 Androidアプリ開発 2013年9月18日 あんざいゆき (株式会社ウフィカ)
  2. 2. Steps • FlashAirにアクセスする • FlashAirに保存されているファイルの一覧を表 示する • FlashAirに保存されている画像ファイルのサム ネイルを表示する • FlashAirに保存されている画像ファイルをダウ ンロードする
  3. 3. プロジェクトの用意
  4. 4. • [File] - [New] - [Android Application Project] • Application Name: FlashAirSample • Project Name: FlashAirSample • Package Name: com.example.flashairsample • Mininum Required SDK:API 9 • 以降はすべてデフォルト設定
  5. 5. FlashAirにアクセスする
  6. 6. FlashAirにアクセスする(1) • FlashAirにアクセスするには、Androidデバイス がFlashAirのアクセスポイントに接続している必 要があります • 設定アプリのWiFi接続画面を開くメニューを用意 しましょう
  7. 7. res/menu/main.xml <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/action_wifi_settings" android:showAsAction="never" android:title="@string/action_wifi_settings"/> </menu> res/values/strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> ... <string name="action_wifi_settings">WiFi Settings</string> </resources>
  8. 8. MainActivity.java public class MainActivity extends Activity { ... @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int itemId = item.getItemId(); switch (itemId) { case R.id.action_wifi_settings: Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS); startActivity(intent); return true; } return super.onOptionsItemSelected(item); } }
  9. 9. FlashAirにアクセスする(2) • FlashAirにはHTTPでアクセスするため、アプリ にはInternetパーミッションが必要です • デフォルト SSID: flashair_xxxxx • デフォルト Pass: 12345678
  10. 10. AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.flashairsample" android:versionCode="1" android:versionName="1.0" > <uses-permission android:name="android.permission.INTERNET"/> ... </manifest>
  11. 11. FlashAirにアクセスする(3) • ライブラリプロジェクトを利用する • FlashAirDev • https://github.com/yanzm/FlashAirDev • git clone https://github.com/yanzm/FlashAirDev.git • [File] - [Import] - [Android] - [Existing Android Code Into Workspace] • Select root directory: • FlashAirDevフォルダを指定
  12. 12. FlashAirにアクセスする(4) • FlashAirSampleのプロパティを開く • [Android] - [Library] - [Add] • FlashAirDev を選択
  13. 13. FlashAirにアクセスする(5) • フォルダ内のファイル数を取得する • http://flashair/command.cgi?op=101&DIR=[path] • https://www.flashair-developers.com/ja/ documents/api/commandcgi/#101 • レスポンスはファイル数(数字)
  14. 14. res/layout/activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" ... tools:context=".MainActivity" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> </RelativeLayout>
  15. 15. res/menu/main.xml <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/action_reload" android:showAsAction="ifRoom" android:title="@string/action_reload"/> ... </menu> res/values/strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> ... <string name="action_reload">Reload</string> <string name="image_count_format">%1$d images</string> </resources>
  16. 16. MainActivity.java public class MainActivity extends Activity { ... @Override public boolean onOptionsItemSelected(MenuItem item) { int itemId = item.getItemId(); switch (itemId) { ... case R.id.action_reload: String dir = "/DCIM"; getFileCount(dir); return true; } return super.onOptionsItemSelected(item); } ... }
  17. 17. MainActivity.java public class MainActivity extends Activity { ... private void getFileCount(final String dir) { new AsyncTask<Void, Void, Integer>() { @Override protected Integer doInBackground(Void... params) { return FlashAirUtils.getFileCount(dir); } @Override protected void onPostExecute(Integer result) { TextView tv = (TextView) findViewById(R.id.textView1); tv.setText(getString(R.string.image_count_format, result)); } }.execute(); } }
  18. 18. FlashAirUtils.java public class FlashAirUtils { public static final String BASE = "http://flashair/"; public static final String COMMAND = BASE + "command.cgi?"; public static final String FILE_COUNT = COMMAND + "op=101&DIR="; public static int getFileCount(String dir) { try { String result = Utils.accessToFlashAir(FILE_COUNT + dir); return Integer.parseInt(result); } catch (NumberFormatException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return -1; } ... } ファイル数取得
  19. 19. Utils.java public class Utils { public static String accessToFlashAir(String uri) throws IOException { URL url = new URL(uri); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); String result = null; try { InputStream in = new BufferedInputStream(urlConnection.getInputStream()); result = inputStreamToString(in); in.close(); } finally { urlConnection.disconnect(); } return result; } ... } HTTPアクセス用
  20. 20. Utils.java public class Utils { ... private static String inputStreamToString(InputStream stream) throws IOException { Reader reader = new InputStreamReader(stream, "UTF-8"); StringBuilder sb = new StringBuilder(); char[] buffer = new char[1024]; int num; while (0 < (num = reader.read(buffer))) { sb.append(buffer, 0, num); } return sb.toString(); } ... } HTTPアクセス用
  21. 21. FlashAirに保存されている ファイルの一覧を表示する
  22. 22. ファイルの一覧を表示する(1) • DCIMフォルダ内のファイル一覧を取得する • http://flashair/command.cgi?op=100&DIR=[path] • https://www.flashair-developers.com/ja/ documents/api/commandcgi/#100 • レスポンスは<ディレクトリ>,<ファイル名>,<ファイル サイズ>,<属性>,<日付>,<時間> • 例)/DCIM,100__TSB,0,16,9944,129 • ファイル名やディレクトリ名に,が入ってる場合もあり うる!
  23. 23. ファイルの一覧を表示する(2) • ファイルサイズはバイト単位 • 属性は16ビット整数の10進数表記 • ビット5 : アーカイブ • ビット4 : ディレクトリ • ビット3 : ボリューム • ビット2 : システムファイル • ビット1 : 隠しファイル • ビット0 : 読み取り専用
  24. 24. ファイルの一覧を表示する(3) • 日付は16ビット整数の10進数表記 • ビット15-9 : 1980年を0とした値 • ビット8-5 : 月(1∼12) • ビット4-0 : 日(1∼31) • 時刻は16ビット整数の10進数表記 • ビット15-11 : 時 • ビット10-5 : 分 • ビット4-0 : 秒/2
  25. 25. FlashAirFileInfo.java public class FlashAirFileInfo { public FlashAirFileInfo(String info, String dir) { int start; int end; start = info.lastIndexOf(","); int time = Integer.parseInt(info.substring(start + 1).trim()); end = start; start = info.lastIndexOf(",", end - 1); int date = Integer.parseInt(info.substring(start + 1, end).trim()); end = start; start = info.lastIndexOf(",", end - 1); mAttribute = Integer.parseInt(info.substring(start + 1, end).trim()); end = start; start = info.lastIndexOf(",", end - 1); mSize = info.substring(start + 1, end); end = start; start = info.indexOf(",", dir.length()); mFileName = info.substring(start + 1, end); ... ファイル情報用のクラス
  26. 26. FlashAirFileInfo.java ... mDir = dir; int year = ((date >> 9) & 0x0000007f) + 1980; int month = (date >> 5) & 0x0000000f - 1; int day = (date) & 0x0000001f; int hourOfDay = (time >> 11) & 0x0000001f; int minute = (time >> 5) & 0x0000003f; int second = ((time) & 0x0000001f) * 2; mCalendar = Calendar.getInstance(); mCalendar.set(year, month, day, hourOfDay, minute, second); } public String mDir; public String mFileName; public String mSize; public int mAttribute; public Calendar mCalendar; ... ファイル情報用のクラス
  27. 27. FlashAirFileInfo.java ... public static final int ATTR_MASK_ARCHIVE = 0x00000020; public static final int ATTR_MASK_DIRECTORY = 0x00000010; public static final int ATTR_MASK_VOLUME = 0x00000008; public static final int ATTR_MASK_SYSTEM_FILE = 0x00000004; public static final int ATTR_MASK_HIDDEN_FILE = 0x00000002; public static final int ATTR_MASK_READ_ONLY = 0x00000001; public boolean isDirectory() { return (mAttribute & ATTR_MASK_DIRECTORY) > 0; } @Override public String toString() { return "DIR=" + mDir + " FILENAME=" + mFileName + " SIZE=" + mSize + " ATTRIBUTE=" + mAttribute + " DATE=" + DateFormat.format("yyyy-MM-dd kk:mm:ss", mCalendar); } } ファイル情報用のクラス
  28. 28. FlashAirUtils.java public class FlashAirUtils { ... public static List<FlashAirFileInfo> getFileList(String dir) { try { String result = Utils.accessToFlashAir(FILE_LIST + dir); if (TextUtils.isEmpty(result)) { return null; } ArrayList<FlashAirFileInfo> list = new ArrayList<FlashAirFileInfo>(); for (String line : result.split("n")) { if (TextUtils.isEmpty(line)) { continue; } if (line.split(",").length < 6) { continue; } FlashAirFileInfo info = new FlashAirFileInfo(line, dir); list.add(info); } return list; ... ファイル情報取得
  29. 29. FlashAirUtils.java ... } catch (IOException e) { e.printStackTrace(); } return null; } ファイル情報取得
  30. 30. res/layout/activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" ... tools:context=".MainActivity" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/textView1" /> </RelativeLayout> 一覧用ListView追加
  31. 31. MainActivity.java public class MainActivity extends Activity { ... @Override public boolean onOptionsItemSelected(MenuItem item) { int itemId = item.getItemId(); switch (itemId) { ... case R.id.action_reload: String dir = "/DCIM"; getFileCount(dir); getFileList(dir); return true; } return super.onOptionsItemSelected(item); } ... } ファイル一覧取得
  32. 32. MainActivity.java public class MainActivity extends Activity { ... private void getFileList(final String dir) { new AsyncTask<Void, Void, List<FlashAirFileInfo>>() { @Override protected List<FlashAirFileInfo> doInBackground(Void... params) { return FlashAirUtils.getFileList(dir); } @Override protected void onPostExecute(List<FlashAirFileInfo> result) { ListView lv = (ListView) findViewById(R.id.listView1); lv.setAdapter(new FileListAdapter(MainActivity.this, result)); } }.execute(); } public class FileListAdapter extends ArrayAdapter<FlashAirFileInfo> { public FileListAdapter(Context context, List<FlashAirFileInfo> data) { super(context, android.R.layout.simple_list_item_1, data); } } } ファイル一覧をListViewにセット
  33. 33. FlashAirに保存されている 画像ファイルのサムネイル を表示する
  34. 34. サムネイルを表示する(1) • 画像ファイルのサムネイルを取得する • http://flashair/thumbnail.cgi?[path] • 例)http://flashair/thumbnail.cgi?/DCIM/IMG_xxx.jpg • https://www.flashair-developers.com/ja/documents/ api/thumbnailcgi/ • EXIF規格で定められているサムネイル画像 • JPEG(image/jpeg)形式 • JPEGでない場合、EXIF規格で定められたサムネイル画像 がない場合、404 Not Found が返る
  35. 35. サムネイルを表示する(2) • ListViewにサムネイルを表示する • Volleyを利用する • Androidのネットワーク処理用のライブラリ • https://android.googlesource.com/platform/ frameworks/volley/ • http://y-anz-m.blogspot.jp/2013/05/google- io-2013-android-volley-easy-fast.html • 通信処理が組み込まれた ImageView である NetworkImageView が用意されている
  36. 36. サムネイルを表示する(3) • VolleyのNetworkImagView • <com.android.volley.toolbox.NetworkImageView> • setImageUrl(String url, ImageLoader loader)
  37. 37. • Volleyはライブラリプロジェクト • git clone https://android.googlesource.com/ platform/frameworks/volley • [File] - [Import] - [Android] - [Existing Android Code Into Workspace] • Select root directory: • volleyフォルダを指定 サムネイルを表示する(4)
  38. 38. • FlashAirSampleのプロパティを開く • [Android] - [Library] - [Add] • volley を選択 サムネイルを表示する(5) Volleyが選択肢に出てこない場合は、 VolleyプロジェクトのIs Libraryに チェックが付いてることを確認
  39. 39. res/layout/list_row.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <com.android.volley.toolbox.NetworkImageView android:id="@+id/imageView1" android:layout_width="100dp" android:layout_height="80dp" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Medium Text" android:textAppearance="?android:attr/textAppearanceMedium" /> </LinearLayout> リスト用レイアウト
  40. 40. MainActivity.java public class MainActivity extends Activity { private RequestQueue mQueue; private ImageLoader mImageLoader; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mQueue = Volley.newRequestQueue(getApplicationContext()); mImageLoader = new ImageLoader(mQueue, new BitmapCache()); } ... Volleyの準備
  41. 41. MainActivity.java ... public class BitmapCache implements ImageCache { private LruCache<String, Bitmap> mCache; public BitmapCache() { int maxSize = 5 * 1024 * 1024; // 5MB mCache = new LruCache<String, Bitmap>(maxSize) { @Override protected int sizeOf(String key, Bitmap value) { return value.getRowBytes() * value.getHeight(); } }; } @Override public Bitmap getBitmap(String url) { return mCache.get(url); } @Override public void putBitmap(String url, Bitmap bitmap) { mCache.put(url, bitmap); } } Volleyの準備
  42. 42. MainActivity.java public class MainActivity extends Activity { ... public class FileListAdapter extends ArrayAdapter<FlashAirFileInfo> { LayoutInflater mInflater; public FileListAdapter(Context context, List<FlashAirFileInfo> data) { super(context, 0, data); mInflater = LayoutInflater.from(context); } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = mInflater.inflate(R.layout.list_row, parent, false); } FlashAirFileInfo item = getItem(position); TextView tv = (TextView) convertView.findViewById(R.id.textView1); tv.setText(item.mFileName); ... リスト用Adapterを拡張
  43. 43. MainActivity.java ... NetworkImageView niv = (NetworkImageView) convertView .findViewById(R.id.imageView1); if (item.mFileName.endsWith(".jpg") || item.mFileName.endsWith(".jpeg")) { niv.setImageUrl( FlashAirUtils.getThumbnailUrl(item.mDir, item.mFileName), mImageLoader); } else { niv.setImageUrl(null, mImageLoader); } return convertView; } } } NetworkImageViewにURLをセット
  44. 44. FlashAirUtils.java public class FlashAirUtils { public static final String BASE = "http://flashair/"; public static final String THUMBNAIL = BASE + "thumbnail.cgi?"; public static String getThumbnailUrl(String dir, String fileName) { return THUMBNAIL + dir + "/" + fileName; } ... }
  45. 45. FlashAirに保存されている画像 ファイルをダウンロードする
  46. 46. 画像をダウンロードする(1) • 画像ファイルを取得する • http://flashair/[path] • 例)http://flashair/DCIM/IMG_xxx.jpg • DownloadManager を利用する • http://developer.android.com/reference/android/ app/DownloadManager.html
  47. 47. 画像をダウンロードする(2) • DownloadManager • getSystemService(Context.DOWNLOAD_SERVICE) でイ ンスタンスを取得 • Request request = new DownloadManager.Request(uri) でダウンロードリクエストを作成 • downloadManager.enqueue(request) でダウンロードリク エストを追加 • SDカードにダウンロードする場合はパーミッションが必要
  48. 48. AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.flashairsample" android:versionCode="1" android:versionName="1.0" > <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ... </manifest>
  49. 49. MainActivity.java public class MainActivity extends Activity implements OnItemClickListener { ... private void getFileList(final String dir) { new AsyncTask<Void, Void, List<FlashAirFileInfo>>() { @Override protected List<FlashAirFileInfo> doInBackground(Void... params) { return FlashAirUtils.getFileList(dir); } @Override protected void onPostExecute(List<FlashAirFileInfo> result) { ListView lv = (ListView) findViewById(R.id.listView1); lv.setAdapter(new FileListAdapter(MainActivity.this, result)); lv.setOnItemClickListener(MainActivity.this); } }.execute(); } ... リストにリスナーをセット
  50. 50. MainActivity.java public class MainActivity extends Activity implements OnItemClickListener { ... @Override public void onItemClick(AdapterView<?> adapter, View v, int position, long l) { FlashAirFileInfo info = (FlashAirFileInfo) adapter .getItemAtPosition(position); File path = Environment .getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM); File file = new File(path, info.mFileName); if (!file.exists()) { startDownload(info); return; } openDownloadedFile(file.toString()); } ... リストにリスナーをセット
  51. 51. MainActivity.java ... private void openDownloadedFile(String filePath) { MediaScannerConnection.scanFile(this, new String[] { filePath }, null, new MediaScannerConnection.OnScanCompletedListener() { public void onScanCompleted(String path, Uri uri) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(uri); startActivity(intent); } }); } private void startDownload(FlashAirFileInfo info) { Uri uri = FlashAirUtils.getFileUri(info.mDir, info.mFileName); DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); DownloadManager.Request request = new DownloadManager.Request(uri); request.allowScanningByMediaScanner(); request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DCIM, info.mFileName); manager.enqueue(request); } ...
  52. 52. MainActivity.java ... @Override protected void onResume() { super.onResume(); IntentFilter filter = new IntentFilter( DownloadManager.ACTION_DOWNLOAD_COMPLETE); registerReceiver(receiver, filter); } @Override protected void onPause() { super.onPause(); unregisterReceiver(receiver); } ...
  53. 53. MainActivity.java ... BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); if (id > 0) { DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); Uri fileUri = manager.getUriForDownloadedFile(id); openDownloadedFile(fileUri.getPath()); } } }; }

×