SlideShare uma empresa Scribd logo
1 de 56
Baixar para ler offline
FlashAir Android App
Development
Sep. 18 2013
Yuki Anzai
uPhyca Inc.
Steps

• Access the FlashAir
• Display a list of files stored on the
FlashAir

• Display thumbnail images
• Download images
Set up a Project
•

[File] - [New] - [Android Application Project]

•

Application Name: FlashAirSample

•

Project Name: FlashAirSample

•

Package Name: com.example.flashairsample

•

Mininum Required SDK: API 9

•

Use default settings for everything else
Access the FlashAir
Access the FlashAir #1

•

Connect your Android device to the FlashAir's
wireless network.

•

Create a shortcut to open the WiFi configuration
window.
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>
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);
}
Access the FlashAir #2

•

Since the FlashAir uses HTTP, your app will require
android.permission.INTERNET.

•
•

Default SSID: flashair_xxxxx
Default Password: 12345678
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>
Access the FlashAir #3
•
•

Use a library project
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:

•

Set FlashAirDev folder
Access FlashAir #4
•
•

Add the FlashAirDev library project
[Android] - [Library] - [Add]

•

Select FlashAirDev
Access FlashAir #5

•
•
•
•

To get the number of files in a folder:
Use http://flashair/command.cgi?op=101&DIR=[path]
The number of files will be returned
See: https://www.flashairdevelopers.com/ja/documents/api/commandcgi/#101
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>
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>
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);
}
...
}
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();
FlashAirUtils.java

Get the number of files

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;

...
Utils.java

For HTTP Access

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;

...
Utils.java

For HTTP Access

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();
}
}

...
Display a list of files stored
on the FlashAir
Display a list of files #1
•
•
•

Get a list of the DCIM folder

•

<directory>,<file name>,<file
size>,<attribute>,<date>,and <time> are returned.

•
•

e.g. /DCIM,100__TSB,0,16,9944,129

Use: http://flashair/command.cgi?op=100&DIR=[path]
See: https://www.flashairdevelopers.com/ja/documents/api/commandcgi/#100

NOTE: A comma could be returned as part of a filename.
Display a list of files #2

•
•
•
•
•
•
•
•

The file's size is in bytes
Attribute is a 16-bit integer
Bit 5 : Archive
Bit 4 : Directly
Bit 3 : Volume
Bit 2 : System file
Bit 1 : Hidden file
Bit 0 : Read only
Display a list of files #3
•

Date is also a 16-bit integer

•
•
•
•

Bit 15-9 : A value based on 0 as a 1980
Bit 8-5 : Month from 1 to 12
Bit 4-0 : Day from 1 to 31

So is the Timestamp

•
•
•

Bit 15-11 : Hour
Bit 10-5 : Minute
Bit 4-0 : Second/2
FlashAirFileInfo.java

Class for a file information

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);
FlashAirFileInfo.java
...

Class for a file information

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
public
public
public
public
...

String mDir;
String mFileName;
String mSize;
int mAttribute;
Calendar mCalendar;
FlashAirFileInfo.java
...
public
public
public
public
public
public

static
static
static
static
static
static

final
final
final
final
final
final

int
int
int
int
int
int

Class for a file information
ATTR_MASK_ARCHIVE = 0x00000020;
ATTR_MASK_DIRECTORY = 0x00000010;
ATTR_MASK_VOLUME = 0x00000008;
ATTR_MASK_SYSTEM_FILE = 0x00000004;
ATTR_MASK_HIDDEN_FILE = 0x00000002;
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);
}
FlashAirUtils.java

Get a file information

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;
FlashAirUtils.java
...
} catch (IOException e) {
e.printStackTrace();
}
}

return null;

Get a file information
res/layout/activity_main.xml

Add ListView

<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>
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);
}
...
}

Get a file list
MainActivity.java

Set a file list to ListView

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);
}
Display thumbnail of
images
Display thumbnails #1
•
•
•
•

To get thumbnails from image files:

•

Thumbnail images are defined by EXIF standard, and are only
available in JPEG format

•

If a file is not JPEG or no thumbnails are defined, a 404 error
is returned

Use http://flashair/thumbnail.cgi?[path]
e.g. http://flashair/thumbnail.cgi?/DCIM/IMG_xxx.jpg
See: https://www.flashairdevelopers.com/ja/documents/api/thumbnailcgi/
Display thumbnails #2
•
•

Display the thumbnails in a ListView
Use Volley!

•
•

A network processing library for Android

•

http://y-anz-m.blogspot.jp/2013/05/google-io-2013android-volley-easy-fast.html

•

NetworkImageView is available

https://android.googlesource.com/platform/frameworks/v
olley/

•

NetworkImageView is an ImageView with
communication processing
Display thumbnails #3

•

NetworkImagView of Vollay

•
•

<com.android.volley.toolbox.NetworkImageView>
setImageUrl(String url, ImageLoader loader)
Display thumbnails #4
•

Volley is a library project, so we need to add it.

•

git clone
https://android.googlesource.com/platform/frameworks/vo
lley

•

[File] - [Import] - [Android] - [Existing Android Code Into
Workspace]

•

Select root directory:

•

Set volley folder
Display thumbnails #5
•
•

Open Properties for FlashAirSample
[Android] - [Library] - [Add]

•

Select volley

If Volley is not appear on the list, make
sure Is Library od Volley project is
checked!
res/layout/list_row.xml

Layout for list

<?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>
MainActivity.java

Prepare Volley

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());
}
...
MainActivity.java

Prepare Volley

...
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);
}
MainActivity.java

Expand Adapter for list

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);
...
MainActivity.java

Set URL at NetworkImageView

...
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;
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;
}
}

...
Download images
Download images #1

•
•
•
•

To get an image file
Use http://flashair/[path]
e.g. http://flashair/DCIM/IMG_xxx.jpg
Use DownloadManager

•

http://developer.android.com/reference/android/app/Dow
nloadManager.html
Download images #2

•

Using DownloadManager

•
•

Create a download request with Request request = new
DownloadManager.Request(uri)

•
•

Get an instance with
getSystemService(Context.DOWNLOAD_SERVICE)

Add the request with downloadManager.enqueue(request)

To save image to your device, you will need
android.permission.WRITE_EXTERNAL_STORAGE.
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>
MainActivity.java

Set Listener in list

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();
MainActivity.java

Set Listener in list

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());
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);
}
...
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);
}
...
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());
}
}
};
FlashAir Android App Development

Mais conteúdo relacionado

Mais procurados

The Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveThe Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveEleanor McHugh
 
EuroPython 2015 - Decorators demystified
EuroPython 2015 - Decorators demystifiedEuroPython 2015 - Decorators demystified
EuroPython 2015 - Decorators demystifiedPablo Enfedaque
 
The Ring programming language version 1.5.4 book - Part 79 of 185
The Ring programming language version 1.5.4 book - Part 79 of 185The Ring programming language version 1.5.4 book - Part 79 of 185
The Ring programming language version 1.5.4 book - Part 79 of 185Mahmoud Samir Fayed
 
AIWolfPy v0.4.9
AIWolfPy v0.4.9AIWolfPy v0.4.9
AIWolfPy v0.4.9Harada Kei
 
Geeks Anonymes - Le langage Go
Geeks Anonymes - Le langage GoGeeks Anonymes - Le langage Go
Geeks Anonymes - Le langage GoGeeks Anonymes
 
Testing CLI tools with Go
Testing CLI tools with GoTesting CLI tools with Go
Testing CLI tools with GoRicardo Gerardi
 
A Skeptics guide to functional style javascript
A Skeptics guide to functional style javascriptA Skeptics guide to functional style javascript
A Skeptics guide to functional style javascriptjonathanfmills
 
多治見IT勉強会 Groovy Grails
多治見IT勉強会 Groovy Grails多治見IT勉強会 Groovy Grails
多治見IT勉強会 Groovy GrailsTsuyoshi Yamamoto
 
Python于Web 2.0网站的应用 - QCon Beijing 2010
Python于Web 2.0网站的应用 - QCon Beijing 2010Python于Web 2.0网站的应用 - QCon Beijing 2010
Python于Web 2.0网站的应用 - QCon Beijing 2010Qiangning Hong
 
Legacy applications - 4Developes konferencja, Piotr Pasich
Legacy applications  - 4Developes konferencja, Piotr PasichLegacy applications  - 4Developes konferencja, Piotr Pasich
Legacy applications - 4Developes konferencja, Piotr PasichPiotr Pasich
 
Java 8 - Nuts and Bold - SFEIR Benelux
Java 8 - Nuts and Bold - SFEIR BeneluxJava 8 - Nuts and Bold - SFEIR Benelux
Java 8 - Nuts and Bold - SFEIR Beneluxyohanbeschi
 
Aspectual Components Implementation: Examples
Aspectual Components Implementation: ExamplesAspectual Components Implementation: Examples
Aspectual Components Implementation: Examplesmukhtarhudaya
 

Mais procurados (20)

Ontopia tutorial
Ontopia tutorialOntopia tutorial
Ontopia tutorial
 
The Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveThe Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's Perspective
 
EuroPython 2015 - Decorators demystified
EuroPython 2015 - Decorators demystifiedEuroPython 2015 - Decorators demystified
EuroPython 2015 - Decorators demystified
 
Pdr ppt
Pdr pptPdr ppt
Pdr ppt
 
The Ring programming language version 1.5.4 book - Part 79 of 185
The Ring programming language version 1.5.4 book - Part 79 of 185The Ring programming language version 1.5.4 book - Part 79 of 185
The Ring programming language version 1.5.4 book - Part 79 of 185
 
Scala 2 + 2 > 4
Scala 2 + 2 > 4Scala 2 + 2 > 4
Scala 2 + 2 > 4
 
AIWolfPy v0.4.9
AIWolfPy v0.4.9AIWolfPy v0.4.9
AIWolfPy v0.4.9
 
Geeks Anonymes - Le langage Go
Geeks Anonymes - Le langage GoGeeks Anonymes - Le langage Go
Geeks Anonymes - Le langage Go
 
Linq introduction
Linq introductionLinq introduction
Linq introduction
 
Testing CLI tools with Go
Testing CLI tools with GoTesting CLI tools with Go
Testing CLI tools with Go
 
A Skeptics guide to functional style javascript
A Skeptics guide to functional style javascriptA Skeptics guide to functional style javascript
A Skeptics guide to functional style javascript
 
Data structures
Data structuresData structures
Data structures
 
Collection Core Concept
Collection Core ConceptCollection Core Concept
Collection Core Concept
 
多治見IT勉強会 Groovy Grails
多治見IT勉強会 Groovy Grails多治見IT勉強会 Groovy Grails
多治見IT勉強会 Groovy Grails
 
JavaFX, because you're worth it
JavaFX, because you're worth itJavaFX, because you're worth it
JavaFX, because you're worth it
 
Python于Web 2.0网站的应用 - QCon Beijing 2010
Python于Web 2.0网站的应用 - QCon Beijing 2010Python于Web 2.0网站的应用 - QCon Beijing 2010
Python于Web 2.0网站的应用 - QCon Beijing 2010
 
Legacy applications - 4Developes konferencja, Piotr Pasich
Legacy applications  - 4Developes konferencja, Piotr PasichLegacy applications  - 4Developes konferencja, Piotr Pasich
Legacy applications - 4Developes konferencja, Piotr Pasich
 
Java 8 - Nuts and Bold - SFEIR Benelux
Java 8 - Nuts and Bold - SFEIR BeneluxJava 8 - Nuts and Bold - SFEIR Benelux
Java 8 - Nuts and Bold - SFEIR Benelux
 
Introduction to JavaFX 2
Introduction to JavaFX 2Introduction to JavaFX 2
Introduction to JavaFX 2
 
Aspectual Components Implementation: Examples
Aspectual Components Implementation: ExamplesAspectual Components Implementation: Examples
Aspectual Components Implementation: Examples
 

Semelhante a FlashAir Android App Development

Paris js extensions
Paris js extensionsParis js extensions
Paris js extensionserwanl
 
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVEActive Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVEkim.mens
 
Deep Dumpster Diving
Deep Dumpster DivingDeep Dumpster Diving
Deep Dumpster DivingRonnBlack
 
Application-Specific Models and Pointcuts using a Logic Meta Language
Application-Specific Models and Pointcuts using a Logic Meta LanguageApplication-Specific Models and Pointcuts using a Logic Meta Language
Application-Specific Models and Pointcuts using a Logic Meta LanguageESUG
 
The Ring programming language version 1.8 book - Part 31 of 202
The Ring programming language version 1.8 book - Part 31 of 202The Ring programming language version 1.8 book - Part 31 of 202
The Ring programming language version 1.8 book - Part 31 of 202Mahmoud Samir Fayed
 
Ingesting and Manipulating Data with JavaScript
Ingesting and Manipulating Data with JavaScriptIngesting and Manipulating Data with JavaScript
Ingesting and Manipulating Data with JavaScriptLucidworks
 
Writing Swift code with great testability
Writing Swift code with great testabilityWriting Swift code with great testability
Writing Swift code with great testabilityJohn Sundell
 
2008 - TechDays PT: WCF, JSON and AJAX for performance and manageability
2008 - TechDays PT: WCF, JSON and AJAX for performance and manageability2008 - TechDays PT: WCF, JSON and AJAX for performance and manageability
2008 - TechDays PT: WCF, JSON and AJAX for performance and manageabilityDaniel Fisher
 
Need help on creating code using cart. The output has to show multip.pdf
Need help on creating code using cart. The output has to show multip.pdfNeed help on creating code using cart. The output has to show multip.pdf
Need help on creating code using cart. The output has to show multip.pdfmeerobertsonheyde608
 
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...Databricks
 
Creating a Facebook Clone - Part XXXI.pdf
Creating a Facebook Clone - Part XXXI.pdfCreating a Facebook Clone - Part XXXI.pdf
Creating a Facebook Clone - Part XXXI.pdfShaiAlmog1
 
Exmaples of file handling
Exmaples of file handlingExmaples of file handling
Exmaples of file handlingsparkishpearl
 
The Ring programming language version 1.6 book - Part 28 of 189
The Ring programming language version 1.6 book - Part 28 of 189The Ring programming language version 1.6 book - Part 28 of 189
The Ring programming language version 1.6 book - Part 28 of 189Mahmoud Samir Fayed
 

Semelhante a FlashAir Android App Development (20)

Anti patterns
Anti patternsAnti patterns
Anti patterns
 
Paris js extensions
Paris js extensionsParis js extensions
Paris js extensions
 
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVEActive Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
 
Deep Dumpster Diving
Deep Dumpster DivingDeep Dumpster Diving
Deep Dumpster Diving
 
Android workshop
Android workshopAndroid workshop
Android workshop
 
Application-Specific Models and Pointcuts using a Logic Meta Language
Application-Specific Models and Pointcuts using a Logic Meta LanguageApplication-Specific Models and Pointcuts using a Logic Meta Language
Application-Specific Models and Pointcuts using a Logic Meta Language
 
The Ring programming language version 1.8 book - Part 31 of 202
The Ring programming language version 1.8 book - Part 31 of 202The Ring programming language version 1.8 book - Part 31 of 202
The Ring programming language version 1.8 book - Part 31 of 202
 
srgoc
srgocsrgoc
srgoc
 
Ingesting and Manipulating Data with JavaScript
Ingesting and Manipulating Data with JavaScriptIngesting and Manipulating Data with JavaScript
Ingesting and Manipulating Data with JavaScript
 
Writing Swift code with great testability
Writing Swift code with great testabilityWriting Swift code with great testability
Writing Swift code with great testability
 
Dartprogramming
DartprogrammingDartprogramming
Dartprogramming
 
2008 - TechDays PT: WCF, JSON and AJAX for performance and manageability
2008 - TechDays PT: WCF, JSON and AJAX for performance and manageability2008 - TechDays PT: WCF, JSON and AJAX for performance and manageability
2008 - TechDays PT: WCF, JSON and AJAX for performance and manageability
 
working with files
working with filesworking with files
working with files
 
C Programming Project
C Programming ProjectC Programming Project
C Programming Project
 
Need help on creating code using cart. The output has to show multip.pdf
Need help on creating code using cart. The output has to show multip.pdfNeed help on creating code using cart. The output has to show multip.pdf
Need help on creating code using cart. The output has to show multip.pdf
 
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...
 
Creating a Facebook Clone - Part XXXI.pdf
Creating a Facebook Clone - Part XXXI.pdfCreating a Facebook Clone - Part XXXI.pdf
Creating a Facebook Clone - Part XXXI.pdf
 
Dojo and Adobe AIR
Dojo and Adobe AIRDojo and Adobe AIR
Dojo and Adobe AIR
 
Exmaples of file handling
Exmaples of file handlingExmaples of file handling
Exmaples of file handling
 
The Ring programming language version 1.6 book - Part 28 of 189
The Ring programming language version 1.6 book - Part 28 of 189The Ring programming language version 1.6 book - Part 28 of 189
The Ring programming language version 1.6 book - Part 28 of 189
 

Último

Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 

Último (20)

Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 

FlashAir Android App Development

  • 1. FlashAir Android App Development Sep. 18 2013 Yuki Anzai uPhyca Inc.
  • 2. Steps • Access the FlashAir • Display a list of files stored on the FlashAir • Display thumbnail images • Download images
  • 3. Set up a Project
  • 4. • [File] - [New] - [Android Application Project] • Application Name: FlashAirSample • Project Name: FlashAirSample • Package Name: com.example.flashairsample • Mininum Required SDK: API 9 • Use default settings for everything else
  • 6. Access the FlashAir #1 • Connect your Android device to the FlashAir's wireless network. • Create a shortcut to open the WiFi configuration window.
  • 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. Access the FlashAir #2 • Since the FlashAir uses HTTP, your app will require android.permission.INTERNET. • • Default SSID: flashair_xxxxx Default Password: 12345678
  • 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. Access the FlashAir #3 • • Use a library project 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: • Set FlashAirDev folder
  • 12. Access FlashAir #4 • • Add the FlashAirDev library project [Android] - [Library] - [Add] • Select FlashAirDev
  • 13. Access FlashAir #5 • • • • To get the number of files in a folder: Use http://flashair/command.cgi?op=101&DIR=[path] The number of files will be returned See: https://www.flashairdevelopers.com/ja/documents/api/commandcgi/#101
  • 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. 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. 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. FlashAirUtils.java Get the number of files 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. Utils.java For HTTP Access 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; ...
  • 20. Utils.java For HTTP Access 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(); } } ...
  • 21. Display a list of files stored on the FlashAir
  • 22. Display a list of files #1 • • • Get a list of the DCIM folder • <directory>,<file name>,<file size>,<attribute>,<date>,and <time> are returned. • • e.g. /DCIM,100__TSB,0,16,9944,129 Use: http://flashair/command.cgi?op=100&DIR=[path] See: https://www.flashairdevelopers.com/ja/documents/api/commandcgi/#100 NOTE: A comma could be returned as part of a filename.
  • 23. Display a list of files #2 • • • • • • • • The file's size is in bytes Attribute is a 16-bit integer Bit 5 : Archive Bit 4 : Directly Bit 3 : Volume Bit 2 : System file Bit 1 : Hidden file Bit 0 : Read only
  • 24. Display a list of files #3 • Date is also a 16-bit integer • • • • Bit 15-9 : A value based on 0 as a 1980 Bit 8-5 : Month from 1 to 12 Bit 4-0 : Day from 1 to 31 So is the Timestamp • • • Bit 15-11 : Hour Bit 10-5 : Minute Bit 4-0 : Second/2
  • 25. FlashAirFileInfo.java Class for a file information 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. FlashAirFileInfo.java ... Class for a file information 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 public public public public ... String mDir; String mFileName; String mSize; int mAttribute; Calendar mCalendar;
  • 27. FlashAirFileInfo.java ... public public public public public public static static static static static static final final final final final final int int int int int int Class for a file information ATTR_MASK_ARCHIVE = 0x00000020; ATTR_MASK_DIRECTORY = 0x00000010; ATTR_MASK_VOLUME = 0x00000008; ATTR_MASK_SYSTEM_FILE = 0x00000004; ATTR_MASK_HIDDEN_FILE = 0x00000002; 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. FlashAirUtils.java Get a file information 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. FlashAirUtils.java ... } catch (IOException e) { e.printStackTrace(); } } return null; Get a file information
  • 30. res/layout/activity_main.xml Add ListView <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>
  • 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); } ... } Get a file list
  • 32. MainActivity.java Set a file list to ListView 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); }
  • 33.
  • 35. Display thumbnails #1 • • • • To get thumbnails from image files: • Thumbnail images are defined by EXIF standard, and are only available in JPEG format • If a file is not JPEG or no thumbnails are defined, a 404 error is returned Use http://flashair/thumbnail.cgi?[path] e.g. http://flashair/thumbnail.cgi?/DCIM/IMG_xxx.jpg See: https://www.flashairdevelopers.com/ja/documents/api/thumbnailcgi/
  • 36. Display thumbnails #2 • • Display the thumbnails in a ListView Use Volley! • • A network processing library for Android • http://y-anz-m.blogspot.jp/2013/05/google-io-2013android-volley-easy-fast.html • NetworkImageView is available https://android.googlesource.com/platform/frameworks/v olley/ • NetworkImageView is an ImageView with communication processing
  • 37. Display thumbnails #3 • NetworkImagView of Vollay • • <com.android.volley.toolbox.NetworkImageView> setImageUrl(String url, ImageLoader loader)
  • 38. Display thumbnails #4 • Volley is a library project, so we need to add it. • git clone https://android.googlesource.com/platform/frameworks/vo lley • [File] - [Import] - [Android] - [Existing Android Code Into Workspace] • Select root directory: • Set volley folder
  • 39. Display thumbnails #5 • • Open Properties for FlashAirSample [Android] - [Library] - [Add] • Select volley If Volley is not appear on the list, make sure Is Library od Volley project is checked!
  • 40. res/layout/list_row.xml Layout for list <?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>
  • 41. MainActivity.java Prepare Volley 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()); } ...
  • 42. MainActivity.java Prepare Volley ... 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); }
  • 43. MainActivity.java Expand Adapter for list 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); ...
  • 44. MainActivity.java Set URL at NetworkImageView ... 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;
  • 45. 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; } } ...
  • 46.
  • 48. Download images #1 • • • • To get an image file Use http://flashair/[path] e.g. http://flashair/DCIM/IMG_xxx.jpg Use DownloadManager • http://developer.android.com/reference/android/app/Dow nloadManager.html
  • 49. Download images #2 • Using DownloadManager • • Create a download request with Request request = new DownloadManager.Request(uri) • • Get an instance with getSystemService(Context.DOWNLOAD_SERVICE) Add the request with downloadManager.enqueue(request) To save image to your device, you will need android.permission.WRITE_EXTERNAL_STORAGE.
  • 50. 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>
  • 51. MainActivity.java Set Listener in list 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();
  • 52. MainActivity.java Set Listener in list 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());
  • 53. 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); } ...
  • 54. 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); } ...
  • 55. 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()); } } };

Notas do Editor

  1. {}