diff options
author | Mike Lockwood <lockwood@android.com> | 2011-01-06 18:17:48 -0500 |
---|---|---|
committer | Mike Lockwood <lockwood@android.com> | 2011-01-22 16:01:30 -0800 |
commit | 20bc97fc541610a296d12e25570ac3eb6d599673 (patch) | |
tree | 92fc391e377f02f60c5648b7037b557375b9ae7e /media/tests/CameraBrowser | |
parent | 47063a859ada034d9181b58ffb9875902a4e2531 (diff) | |
download | frameworks_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')
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); + } + } + } +} |