summaryrefslogtreecommitdiffstats
path: root/media/tests/CameraBrowser
diff options
context:
space:
mode:
authorMike Lockwood <lockwood@android.com>2011-01-06 18:17:48 -0500
committerMike Lockwood <lockwood@android.com>2011-01-22 16:01:30 -0800
commit20bc97fc541610a296d12e25570ac3eb6d599673 (patch)
tree92fc391e377f02f60c5648b7037b557375b9ae7e /media/tests/CameraBrowser
parent47063a859ada034d9181b58ffb9875902a4e2531 (diff)
downloadframeworks_base-20bc97fc541610a296d12e25570ac3eb6d599673.zip
frameworks_base-20bc97fc541610a296d12e25570ac3eb6d599673.tar.gz
frameworks_base-20bc97fc541610a296d12e25570ac3eb6d599673.tar.bz2
CameraBrowser: new implementation based on new MTP host APIs
Change-Id: I81300e3218d6f6fce87432ce506fc282aa4dc4b8 Signed-off-by: Mike Lockwood <lockwood@android.com>
Diffstat (limited to 'media/tests/CameraBrowser')
-rw-r--r--media/tests/CameraBrowser/Android.mk10
-rw-r--r--media/tests/CameraBrowser/AndroidManifest.xml31
-rw-r--r--media/tests/CameraBrowser/res/layout/object_info.xml169
-rw-r--r--media/tests/CameraBrowser/res/layout/object_list.xml33
-rw-r--r--media/tests/CameraBrowser/res/values/strings.xml46
-rw-r--r--media/tests/CameraBrowser/res/values/styles.xml34
-rw-r--r--media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowser.java139
-rw-r--r--media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowserApplication.java41
-rw-r--r--media/tests/CameraBrowser/src/com/android/camerabrowser/DeviceDisconnectedReceiver.java52
-rw-r--r--media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java147
-rw-r--r--media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java203
-rw-r--r--media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java121
-rw-r--r--media/tests/CameraBrowser/src/com/android/camerabrowser/UsbReceiver.java48
13 files changed, 1074 insertions, 0 deletions
diff --git a/media/tests/CameraBrowser/Android.mk b/media/tests/CameraBrowser/Android.mk
new file mode 100644
index 0000000..1d81129
--- /dev/null
+++ b/media/tests/CameraBrowser/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := CameraBrowser
+
+include $(BUILD_PACKAGE)
diff --git a/media/tests/CameraBrowser/AndroidManifest.xml b/media/tests/CameraBrowser/AndroidManifest.xml
new file mode 100644
index 0000000..f167f4b
--- /dev/null
+++ b/media/tests/CameraBrowser/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.camerabrowser">
+
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.ACCESS_USB" />
+
+ <application android:label="@string/app_label"
+ android:name="com.android.camerabrowser.CameraBrowserApplication">
+
+ <activity android:name="CameraBrowser" android:label="Camera Browser">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="StorageBrowser" />
+ <activity android:name="ObjectBrowser" />
+ <activity android:name="ObjectViewer" />
+
+<!--
+ <receiver android:name="UsbReceiver">
+ <intent-filter>
+ <action android:name="android.hardware.action.USB_DEVICE_ATTACHED" />
+ </intent-filter>
+ </receiver>
+-->
+ </application>
+
+
+</manifest>
diff --git a/media/tests/CameraBrowser/res/layout/object_info.xml b/media/tests/CameraBrowser/res/layout/object_info.xml
new file mode 100644
index 0000000..a0499f2
--- /dev/null
+++ b/media/tests/CameraBrowser/res/layout/object_info.xml
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/object_info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TableRow>
+ <TextView android:id="@+id/name_label"
+ android:text="@string/name_label"
+ android:layout_gravity="right"
+ android:layout_marginRight="8dip"
+ style="@style/info_label" />
+
+ <TextView android:id="@+id/name"
+ style="@style/info_value" />
+ </TableRow>
+ <TableRow>
+ <TextView android:id="@+id/size_label"
+ android:text="@string/size_label"
+ android:layout_gravity="right"
+ android:layout_marginRight="8dip"
+ style="@style/info_label" />
+
+ <TextView android:id="@+id/size"
+ style="@style/info_value" />
+ </TableRow>
+ <TableRow>
+ <TextView android:id="@+id/format_label"
+ android:text="@string/format_label"
+ android:layout_gravity="right"
+ android:layout_marginRight="8dip"
+ style="@style/info_label" />
+
+ <TextView android:id="@+id/format"
+ style="@style/info_value" />
+ </TableRow>
+ <TableRow>
+ <TextView android:id="@+id/thumb_width_label"
+ android:text="@string/thumb_width_label"
+ android:layout_gravity="right"
+ android:layout_marginRight="8dip"
+ style="@style/info_label" />
+
+ <TextView android:id="@+id/thumb_width"
+ style="@style/info_value" />
+ </TableRow>
+ <TableRow>
+ <TextView android:id="@+id/thumb_height_label"
+ android:text="@string/thumb_height_label"
+ android:layout_gravity="right"
+ android:layout_marginRight="8dip"
+ style="@style/info_label" />
+
+ <TextView android:id="@+id/thumb_height"
+ style="@style/info_value" />
+ </TableRow>
+ <TableRow>
+ <TextView android:id="@+id/thumb_size_label"
+ android:text="@string/thumb_size_label"
+ android:layout_gravity="right"
+ android:layout_marginRight="8dip"
+ style="@style/info_label" />
+
+ <TextView android:id="@+id/thumb_size"
+ style="@style/info_value" />
+ </TableRow>
+ <TableRow>
+ <TextView android:id="@+id/width_label"
+ android:text="@string/width_label"
+ android:layout_gravity="right"
+ android:layout_marginRight="8dip"
+ style="@style/info_label" />
+
+ <TextView android:id="@+id/width"
+ style="@style/info_value" />
+ </TableRow>
+ <TableRow>
+ <TextView android:id="@+id/height_label"
+ android:text="@string/height_label"
+ android:layout_gravity="right"
+ android:layout_marginRight="8dip"
+ style="@style/info_label" />
+
+ <TextView android:id="@+id/height"
+ style="@style/info_value" />
+ </TableRow>
+ <TableRow>
+ <TextView android:id="@+id/depth_label"
+ android:text="@string/depth_label"
+ android:layout_gravity="right"
+ android:layout_marginRight="8dip"
+ style="@style/info_label" />
+
+ <TextView android:id="@+id/depth"
+ style="@style/info_value" />
+ </TableRow>
+ <TableRow>
+ <TextView android:id="@+id/sequence_label"
+ android:text="@string/sequence_label"
+ android:layout_gravity="right"
+ android:layout_marginRight="8dip"
+ style="@style/info_label" />
+
+ <TextView android:id="@+id/sequence"
+ style="@style/info_value" />
+ </TableRow>
+ <TableRow>
+ <TextView android:id="@+id/created_label"
+ android:text="@string/created_label"
+ android:layout_gravity="right"
+ android:layout_marginRight="8dip"
+ style="@style/info_label" />
+
+ <TextView android:id="@+id/created"
+ style="@style/info_value" />
+ </TableRow>
+ <TableRow>
+ <TextView android:id="@+id/modified_label"
+ android:text="@string/modified_label"
+ android:layout_gravity="right"
+ android:layout_marginRight="8dip"
+ style="@style/info_label" />
+
+ <TextView android:id="@+id/modified"
+ style="@style/info_value" />
+ </TableRow>
+ <TableRow>
+ <TextView android:id="@+id/keywords_label"
+ android:text="@string/keywords_label"
+ android:layout_gravity="right"
+ android:layout_marginRight="8dip"
+ style="@style/info_label" />
+
+ <TextView android:id="@+id/keywords"
+ style="@style/info_value" />
+ </TableRow>
+ <TableRow>
+ <ImageView android:id="@+id/thumbnail" />
+ </TableRow>
+ <TableRow>
+ <Button android:id="@+id/import_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/import_label">
+ </Button>
+ <Button android:id="@+id/delete_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/delete_label">
+ </Button>
+ </TableRow>
+</TableLayout>
+
diff --git a/media/tests/CameraBrowser/res/layout/object_list.xml b/media/tests/CameraBrowser/res/layout/object_list.xml
new file mode 100644
index 0000000..30c18bb
--- /dev/null
+++ b/media/tests/CameraBrowser/res/layout/object_list.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <ImageView android:id="@+id/thumbnail"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <TextView android:id="@+id/name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:gravity="center_vertical"
+ android:paddingLeft="6dip"
+ android:minHeight="?android:attr/listPreferredItemHeight" />
+</LinearLayout>
diff --git a/media/tests/CameraBrowser/res/values/strings.xml b/media/tests/CameraBrowser/res/values/strings.xml
new file mode 100644
index 0000000..932aaec
--- /dev/null
+++ b/media/tests/CameraBrowser/res/values/strings.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <string name="app_label">Camera Browser</string>
+
+ <!-- for object info -->
+ <string name="name_label">Name: </string>
+ <string name="size_label">Size: </string>
+ <string name="format_label">Format: </string>
+ <string name="thumb_width_label">Thumb Width: </string>
+ <string name="thumb_height_label">Thumb Height: </string>
+ <string name="thumb_size_label">Thumb Size: </string>
+ <string name="width_label">Width: </string>
+ <string name="height_label">Height: </string>
+ <string name="depth_label">Depth: </string>
+ <string name="sequence_label">Sequence: </string>
+ <string name="created_label">Created: </string>
+ <string name="modified_label">Modified: </string>
+ <string name="keywords_label">Keywords: </string>
+
+ <!-- button labels -->
+ <string name="import_label">Import</string>
+ <string name="delete_label">Delete</string>
+
+ <!-- toasts -->
+ <string name="object_saved_message">Object saved</string>
+ <string name="save_failed_message">Could not save object</string>
+ <string name="object_deleted_message">Object deleted</string>
+ <string name="delete_failed_message">Could not delete object</string>
+ <string name="start_activity_failed_message">Import succeeded, but could not display object</string>
+
+</resources>
diff --git a/media/tests/CameraBrowser/res/values/styles.xml b/media/tests/CameraBrowser/res/values/styles.xml
new file mode 100644
index 0000000..c869985
--- /dev/null
+++ b/media/tests/CameraBrowser/res/values/styles.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <style name="info_label">
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:textStyle">bold</item>
+ <item name="android:paddingRight">4dip</item>
+ </style>
+
+ <style name="info_value">
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:textStyle">normal</item>
+ </style>
+
+</resources>
+
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowser.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowser.java
new file mode 100644
index 0000000..f642d93
--- /dev/null
+++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowser.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camerabrowser;
+
+import android.app.ListActivity;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.mtp.MtpClient;
+import android.mtp.MtpDevice;
+import android.mtp.MtpDeviceInfo;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.TwoLineListItem;
+
+import java.util.List;
+
+ /**
+ * A list view displaying all connected cameras.
+ */
+public class CameraBrowser extends ListActivity implements MtpClient.Listener {
+
+ private static final String TAG = "CameraBrowser";
+
+ private MtpClient mClient;
+ private List<MtpDevice> mDeviceList;
+
+ private static final int MODEL_COLUMN = 0;
+ private static final int MANUFACTURER_COLUMN = 1;
+ private static final int COLUMN_COUNT = 2;
+
+ private class CameraAdapter extends BaseAdapter {
+ private final Context mContext;
+ private final LayoutInflater mInflater;
+
+ public CameraAdapter(Context c) {
+ mContext = c;
+ mInflater = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ public int getCount() {
+ return mDeviceList.size();
+ }
+
+ public Object getItem(int position) {
+ return mDeviceList.get(position);
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ TwoLineListItem view;
+ if (convertView == null) {
+ view = (TwoLineListItem)mInflater.inflate(
+ android.R.layout.simple_list_item_2, parent, false);
+ } else {
+ view = (TwoLineListItem)convertView;
+ }
+
+ TextView textView1 = (TextView)view.findViewById(com.android.internal.R.id.text1);
+ TextView textView2 = (TextView)view.findViewById(com.android.internal.R.id.text2);
+ MtpDevice device = mDeviceList.get(position);
+ MtpDeviceInfo info = device.getDeviceInfo();
+ if (info != null) {
+ textView1.setText(info.getManufacturer());
+ textView2.setText(info.getModel());
+ } else {
+ textView1.setText("???");
+ textView2.setText("???");
+ }
+ return view;
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mClient = ((CameraBrowserApplication)getApplication()).getMtpClient();
+ mClient.addListener(this);
+ mDeviceList = mClient.getDeviceList();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ reload();
+ }
+
+ @Override
+ protected void onDestroy() {
+ mClient.removeListener(this);
+ super.onDestroy();
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ Intent intent = new Intent(this, StorageBrowser.class);
+ intent.putExtra("device", mDeviceList.get(position).getDeviceName());
+ startActivity(intent);
+ }
+
+ private void reload() {
+ setListAdapter(new CameraAdapter(this));
+ }
+
+ public void deviceAdded(MtpDevice device) {
+ Log.d(TAG, "deviceAdded: " + device.getDeviceName());
+ mDeviceList = mClient.getDeviceList();
+ reload();
+ }
+
+ public void deviceRemoved(MtpDevice device) {
+ Log.d(TAG, "deviceRemoved: " + device.getDeviceName());
+ mDeviceList = mClient.getDeviceList();
+ reload();
+ }
+}
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowserApplication.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowserApplication.java
new file mode 100644
index 0000000..6f1edfea
--- /dev/null
+++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowserApplication.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camerabrowser;
+
+import android.app.Application;
+import android.mtp.MtpClient;
+
+
+public class CameraBrowserApplication extends Application {
+
+ private MtpClient mClient;
+
+ @Override
+ public void onCreate() {
+ mClient = new MtpClient(this);
+ }
+
+ @Override
+ public void onTerminate() {
+ mClient.close();
+ mClient = null;
+ }
+
+ public MtpClient getMtpClient() {
+ return mClient;
+ }
+}
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/DeviceDisconnectedReceiver.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/DeviceDisconnectedReceiver.java
new file mode 100644
index 0000000..736af1f
--- /dev/null
+++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/DeviceDisconnectedReceiver.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camerabrowser;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.UsbManager;
+import android.util.Log;
+
+public class DeviceDisconnectedReceiver extends BroadcastReceiver {
+
+ private static final String TAG = "DeviceDisconnectedReceiver";
+
+ private final Activity mActivity;
+ private final String mDeviceName;
+
+ public DeviceDisconnectedReceiver(Activity activity, String deviceName) {
+ mActivity = activity;
+ mDeviceName = deviceName;
+
+ IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED);
+ activity.registerReceiver(this, filter);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String deviceName = intent.getStringExtra(UsbManager.EXTRA_DEVICE_NAME);
+ Log.d(TAG, "ACTION_USB_DEVICE_DETACHED " + deviceName);
+
+ // close our activity if the device it is displaying is disconnected
+ if (deviceName.equals(mDeviceName)) {
+ mActivity.finish();
+ }
+ }
+} \ No newline at end of file
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java
new file mode 100644
index 0000000..82251d9
--- /dev/null
+++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camerabrowser;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.mtp.MtpClient;
+import android.mtp.MtpConstants;
+import android.mtp.MtpDevice;
+import android.mtp.MtpObjectInfo;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.List;
+
+ /**
+ * A list view displaying all objects within a container (folder or storage unit).
+ */
+public class ObjectBrowser extends ListActivity {
+
+ private static final String TAG = "ObjectBrowser";
+
+ private MtpClient mClient;
+ private List<MtpObjectInfo> mObjectList;
+ private String mDeviceName;
+ private int mStorageID;
+ private int mObjectID;
+ private DeviceDisconnectedReceiver mDisconnectedReceiver;
+
+ private class ObjectAdapter extends BaseAdapter {
+ private final Context mContext;
+ private final LayoutInflater mInflater;
+
+ public ObjectAdapter(Context c) {
+ mContext = c;
+ mInflater = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ public int getCount() {
+ if (mObjectList == null) {
+ return 0;
+ } else {
+ return mObjectList.size();
+ }
+ }
+
+ public Object getItem(int position) {
+ return mObjectList.get(position);
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View view;
+ if (convertView == null) {
+ view = mInflater.inflate(R.layout.object_list, parent, false);
+ } else {
+ view = convertView;
+ }
+
+ TextView nameView = (TextView)view.findViewById(R.id.name);
+ MtpObjectInfo info = mObjectList.get(position);
+ nameView.setText(info.getName());
+
+ int thumbFormat = info.getThumbFormat();
+ if (thumbFormat == MtpConstants.FORMAT_EXIF_JPEG
+ || thumbFormat == MtpConstants.FORMAT_JFIF) {
+ byte[] thumbnail = mClient.getThumbnail(mDeviceName, info.getObjectHandle());
+ if (thumbnail != null) {
+ Bitmap bitmap = BitmapFactory.decodeByteArray(thumbnail, 0, thumbnail.length);
+ if (bitmap != null) {
+ ImageView thumbView = (ImageView)view.findViewById(R.id.thumbnail);
+ thumbView.setImageBitmap(bitmap);
+ }
+ }
+ }
+ return view;
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mClient = ((CameraBrowserApplication)getApplication()).getMtpClient();
+ mDeviceName = getIntent().getStringExtra("device");
+ mStorageID = getIntent().getIntExtra("storage", 0);
+ mObjectID = getIntent().getIntExtra("object", 0);
+ mDisconnectedReceiver = new DeviceDisconnectedReceiver(this, mDeviceName);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ mObjectList = mClient.getObjectList(mDeviceName, mStorageID, mObjectID);
+ setListAdapter(new ObjectAdapter(this));
+ }
+
+ @Override
+ protected void onDestroy() {
+ unregisterReceiver(mDisconnectedReceiver);
+ super.onDestroy();
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ MtpObjectInfo info = mObjectList.get(position);
+ Intent intent;
+ if (info.getFormat() == MtpConstants.FORMAT_ASSOCIATION) {
+ intent = new Intent(this, ObjectBrowser.class);
+ } else {
+ intent = new Intent(this, ObjectViewer.class);
+ }
+ intent.putExtra("device", mDeviceName);
+ intent.putExtra("storage", mStorageID);
+ intent.putExtra("object", info.getObjectHandle());
+ startActivity(intent);
+ }
+}
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java
new file mode 100644
index 0000000..e9ea9f3
--- /dev/null
+++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camerabrowser;
+
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.media.MediaScannerConnection;
+import android.media.MediaScannerConnection.MediaScannerConnectionClient;
+import android.mtp.MtpClient;
+import android.mtp.MtpConstants;
+import android.mtp.MtpObjectInfo;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.io.File;
+import java.util.Date;
+
+/**
+ * A view to display the properties of an object.
+ */
+public class ObjectViewer extends Activity implements View.OnClickListener {
+
+ private static final String TAG = "ObjectViewer";
+
+ private MtpClient mClient;
+ private String mDeviceName;
+ private int mStorageID;
+ private int mObjectID;
+ private String mFileName;
+ private Button mImportButton;
+ private Button mDeleteButton;
+ private DeviceDisconnectedReceiver mDisconnectedReceiver;
+
+ private final class ScannerClient implements MediaScannerConnectionClient {
+ private final Context mContext;
+ private String mPath;
+
+ public ScannerClient(Context context) {
+ mContext = context;
+ }
+
+ public void setScanPath(String path) {
+ mPath = path;
+ }
+
+ @Override
+ public void onMediaScannerConnected() {
+ mScannerConnection.scanFile(mPath, null);
+ }
+
+ @Override
+ public void onScanCompleted(String path, Uri uri) {
+ mScannerConnection.disconnect();
+
+ // try to start an activity to view the file
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ try {
+ mContext.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(mContext, R.string.start_activity_failed_message,
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+
+ private MediaScannerConnection mScannerConnection;
+ private ScannerClient mScannerClient;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mClient = ((CameraBrowserApplication)getApplication()).getMtpClient();
+
+ setContentView(R.layout.object_info);
+
+ mImportButton = (Button)findViewById(R.id.import_button);
+ mImportButton.setOnClickListener(this);
+ mDeleteButton = (Button)findViewById(R.id.delete_button);
+ mDeleteButton.setOnClickListener(this);
+
+ mDeviceName = getIntent().getStringExtra("device");
+ mStorageID = getIntent().getIntExtra("storage", 0);
+ mObjectID = getIntent().getIntExtra("object", 0);
+ mDisconnectedReceiver = new DeviceDisconnectedReceiver(this, mDeviceName);
+ mScannerClient = new ScannerClient(this);
+ mScannerConnection = new MediaScannerConnection(this, mScannerClient);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ MtpObjectInfo info = mClient.getObjectInfo(mDeviceName, mObjectID);
+ if (info != null) {
+ TextView view = (TextView)findViewById(R.id.name);
+ mFileName = info.getName();
+ view.setText(mFileName);
+ view = (TextView)findViewById(R.id.format);
+ view.setText(Integer.toHexString(info.getFormat()).toUpperCase());
+ view = (TextView)findViewById(R.id.size);
+ view.setText(Long.toString(info.getCompressedSize()));
+ view = (TextView)findViewById(R.id.thumb_width);
+ view.setText(Long.toString(info.getThumbPixWidth()));
+ view = (TextView)findViewById(R.id.thumb_height);
+ view.setText(Long.toString(info.getThumbPixHeight()));
+ view = (TextView)findViewById(R.id.thumb_size);
+ view.setText(Long.toString(info.getThumbCompressedSize()));
+ view = (TextView)findViewById(R.id.width);
+ view.setText(Long.toString(info.getImagePixWidth()));
+ view = (TextView)findViewById(R.id.height);
+ view.setText(Long.toString(info.getImagePixHeight()));
+ view = (TextView)findViewById(R.id.depth);
+ view.setText(Long.toString(info.getImagePixDepth()));
+ view = (TextView)findViewById(R.id.sequence);
+ view.setText(Long.toString(info.getSequenceNumber()));
+ view = (TextView)findViewById(R.id.created);
+ Date date = new Date(info.getDateCreated() * 1000);
+ view.setText(date.toString());
+ view = (TextView)findViewById(R.id.modified);
+ date = new Date(info.getDateModified() * 1000);
+ view.setText(date.toString());
+ view = (TextView)findViewById(R.id.keywords);
+ view.setText(info.getKeywords());
+ int thumbFormat = info.getThumbFormat();
+ if (thumbFormat == MtpConstants.FORMAT_EXIF_JPEG
+ || thumbFormat == MtpConstants.FORMAT_JFIF) {
+ byte[] thumbnail = mClient.getThumbnail(mDeviceName, info.getObjectHandle());
+ if (thumbnail != null) {
+ Bitmap bitmap = BitmapFactory.decodeByteArray(thumbnail, 0, thumbnail.length);
+ if (bitmap != null) {
+ ImageView thumbView = (ImageView)findViewById(R.id.thumbnail);
+ thumbView.setImageBitmap(bitmap);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ unregisterReceiver(mDisconnectedReceiver);
+ super.onDestroy();
+ }
+
+ private void importObject() {
+ // copy file to /mnt/sdcard/imported/<filename>
+ File dest = Environment.getExternalStorageDirectory();
+ dest = new File(dest, "imported");
+ dest.mkdirs();
+ dest = new File(dest, mFileName);
+
+ if (mClient.importFile(mDeviceName, mObjectID, dest.getAbsolutePath())) {
+ Toast.makeText(this, R.string.object_saved_message, Toast.LENGTH_SHORT).show();
+
+ mScannerClient.setScanPath(dest.getAbsolutePath());
+ mScannerConnection.connect();
+ } else {
+ Toast.makeText(this, R.string.save_failed_message, Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ private void deleteObject() {
+ if (mClient.deleteObject(mDeviceName, mObjectID)) {
+ Toast.makeText(this, R.string.object_deleted_message, Toast.LENGTH_SHORT).show();
+ finish();
+ } else {
+ Toast.makeText(this, R.string.delete_failed_message, Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ public void onClick(View v) {
+ if (v == mImportButton) {
+ importObject();
+ } else if (v == mDeleteButton) {
+ deleteObject();
+ }
+ }
+}
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java
new file mode 100644
index 0000000..7d5a5da
--- /dev/null
+++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camerabrowser;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.content.Intent;
+import android.mtp.MtpClient;
+import android.mtp.MtpDevice;
+import android.mtp.MtpStorageInfo;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.List;
+
+/**
+ * A list view displaying all storage units on a device.
+ */
+public class StorageBrowser extends ListActivity {
+
+ private static final String TAG = "StorageBrowser";
+
+ private MtpClient mClient;
+ private String mDeviceName;
+ private List<MtpStorageInfo> mStorageList;
+ private DeviceDisconnectedReceiver mDisconnectedReceiver;
+
+ private class StorageAdapter extends BaseAdapter {
+ private final Context mContext;
+ private final LayoutInflater mInflater;
+
+ public StorageAdapter(Context c) {
+ mContext = c;
+ mInflater = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ public int getCount() {
+ if (mStorageList == null) {
+ return 0;
+ } else {
+ return mStorageList.size();
+ }
+ }
+
+ public Object getItem(int position) {
+ return mStorageList.get(position);
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ TextView view;
+ if (convertView == null) {
+ view = (TextView)mInflater.inflate(
+ android.R.layout.simple_list_item_1, parent, false);
+ } else {
+ view = (TextView)convertView;
+ }
+
+ MtpStorageInfo info = mStorageList.get(position);
+ if (info != null) {
+ view.setText(info.getDescription());
+ } else {
+ view.setText("???");
+ }
+ return view;
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mClient = ((CameraBrowserApplication)getApplication()).getMtpClient();
+ mDeviceName = getIntent().getStringExtra("device");
+ mDisconnectedReceiver = new DeviceDisconnectedReceiver(this, mDeviceName);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mStorageList = mClient.getStorageList(mDeviceName);
+ setListAdapter(new StorageAdapter(this));
+ }
+
+ @Override
+ protected void onDestroy() {
+ unregisterReceiver(mDisconnectedReceiver);
+ super.onDestroy();
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ Intent intent = new Intent(this, ObjectBrowser.class);
+ intent.putExtra("device", mDeviceName);
+ intent.putExtra("storage", mStorageList.get(position).getStorageId());
+ startActivity(intent);
+ }
+}
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/UsbReceiver.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/UsbReceiver.java
new file mode 100644
index 0000000..22d9443
--- /dev/null
+++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/UsbReceiver.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camerabrowser;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.BroadcastReceiver;
+import android.hardware.UsbDevice;
+import android.hardware.UsbManager;
+import android.mtp.MtpClient;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.Log;
+
+public class UsbReceiver extends BroadcastReceiver
+{
+ private static final String TAG = "UsbReceiver";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.d(TAG, "onReceive " + intent);
+ if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) {
+ UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+ if (MtpClient.isCamera(device)) {
+ String deviceName = device.getDeviceName();
+ Log.d(TAG, "Got camera: " + deviceName);
+ intent = new Intent(context, StorageBrowser.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra("device", deviceName);
+ context.startActivity(intent);
+ }
+ }
+ }
+}