CameraBrowser: new implementation based on new MTP host APIs

Change-Id: I81300e3218d6f6fce87432ce506fc282aa4dc4b8
Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
Mike Lockwood
2011-01-06 18:17:48 -05:00
parent 47063a859a
commit 20bc97fc54
13 changed files with 1074 additions and 0 deletions

View File

@@ -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)

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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