SlideShare ist ein Scribd-Unternehmen logo
1 von 56
Downloaden Sie, um offline zu lesen
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

Weitere ähnliche Inhalte

Was ist angesagt?

Legacy applications - 4Developes konferencja, Piotr Pasich
Legacy applications  - 4Developes konferencja, Piotr PasichLegacy applications  - 4Developes konferencja, Piotr Pasich
Legacy applications - 4Developes konferencja, Piotr Pasich
Piotr Pasich
 
Aspectual Components Implementation: Examples
Aspectual Components Implementation: ExamplesAspectual Components Implementation: Examples
Aspectual Components Implementation: Examples
mukhtarhudaya
 

Was ist angesagt? (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
 

Ähnlich wie FlashAir Android App Development

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
kim.mens
 
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
meerobertsonheyde608
 
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
 

Ähnlich wie 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
 

Kürzlich hochgeladen

Kürzlich hochgeladen (20)

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
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
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...
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
[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
 

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

Hinweis der Redaktion

  1. {}