ImageRecord.java revision eac4f94910e1f034d57c54e4f53a34786bc4bb4c
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.apps.tag.record; 18 19import com.android.apps.tag.R; 20import com.google.common.base.Preconditions; 21 22import android.app.Activity; 23import android.content.Context; 24import android.content.Intent; 25import android.content.pm.PackageManager; 26import android.content.pm.ResolveInfo; 27import android.database.Cursor; 28import android.graphics.Bitmap; 29import android.graphics.BitmapFactory; 30import android.nfc.NdefRecord; 31import android.os.Parcel; 32import android.os.Parcelable; 33import android.provider.MediaStore; 34import android.provider.OpenableColumns; 35import android.view.LayoutInflater; 36import android.view.View; 37import android.view.ViewGroup; 38import android.widget.ImageView; 39import android.widget.TextView; 40 41import java.io.ByteArrayOutputStream; 42import java.util.List; 43 44/** 45 * A NdefRecord corresponding to an image type. 46 */ 47public class ImageRecord implements ParsedNdefRecord { 48 49 public static final String RECORD_TYPE = "ImageRecord"; 50 51 private final Bitmap mBitmap; 52 53 private ImageRecord(Bitmap bitmap) { 54 mBitmap = Preconditions.checkNotNull(bitmap); 55 } 56 57 @Override 58 public View getView(Activity activity, LayoutInflater inflater, ViewGroup parent) { 59 ImageView image = (ImageView) inflater.inflate(R.layout.tag_image, parent, false); 60 image.setImageBitmap(mBitmap); 61 return image; 62 } 63 64 /** 65 * Returns a view in a list of record types for adding new records to a message. 66 */ 67 public static View getAddView(Context context, LayoutInflater inflater, ViewGroup parent) { 68 ViewGroup root = (ViewGroup) inflater.inflate( 69 R.layout.tag_add_record_list_item, parent, false); 70 71 // Determine which Activity can retrieve images. 72 Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 73 intent.addCategory(Intent.CATEGORY_OPENABLE); 74 intent.setType("image/*"); 75 76 PackageManager pm = context.getPackageManager(); 77 List<ResolveInfo> activities = pm.queryIntentActivities(intent, 0); 78 if (activities.isEmpty()) { 79 return null; 80 } 81 82 ResolveInfo info = activities.get(0); 83 ((ImageView) root.findViewById(R.id.image)).setImageDrawable(info.loadIcon(pm)); 84 ((TextView) root.findViewById(R.id.text)).setText(context.getString(R.string.photo)); 85 86 root.setTag(new ImageRecordEditInfo(intent)); 87 return root; 88 } 89 90 public static ImageRecord parse(NdefRecord record) { 91 MimeRecord underlyingRecord = MimeRecord.parse(record); 92 Preconditions.checkArgument(underlyingRecord.getMimeType().startsWith("image/")); 93 94 // Try to ensure it's a legal, valid image 95 byte[] content = underlyingRecord.getContent(); 96 Bitmap bitmap = BitmapFactory.decodeByteArray(content, 0, content.length); 97 if (bitmap == null) { 98 throw new IllegalArgumentException("not a valid image file"); 99 } 100 return new ImageRecord(bitmap); 101 } 102 103 public static boolean isImage(NdefRecord record) { 104 try { 105 parse(record); 106 return true; 107 } catch (IllegalArgumentException e) { 108 return false; 109 } 110 } 111 112 public static NdefRecord newImageRecord(Bitmap bitmap) { 113 ByteArrayOutputStream out = new ByteArrayOutputStream(); 114 bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); 115 byte[] content = out.toByteArray(); 116 return MimeRecord.newMimeRecord("image/png", content); 117 } 118 119 private static class ImageRecordEditInfo extends RecordEditInfo { 120 private final Intent mIntent; 121 private String mCurrentPath; 122 private Bitmap mCachedValue; 123 124 public ImageRecordEditInfo(Intent intent) { 125 super(RECORD_TYPE); 126 mIntent = intent; 127 mCurrentPath = ""; 128 } 129 130 protected ImageRecordEditInfo(Parcel parcel) { 131 super(parcel); 132 mIntent = parcel.readParcelable(null); 133 mCurrentPath = parcel.readString(); 134 } 135 136 @Override 137 public Intent getPickIntent() { 138 return mIntent; 139 } 140 141 @Override 142 public NdefRecord getValue() { 143 return ImageRecord.newImageRecord(getValueInternal()); 144 } 145 146 private Bitmap getValueInternal() { 147 if (mCachedValue == null) { 148 mCachedValue = BitmapFactory.decodeFile(mCurrentPath); 149 } 150 return mCachedValue; 151 } 152 153 @Override 154 public void handlePickResult(Context context, Intent data) { 155 Cursor cursor = null; 156 mCachedValue = null; 157 try { 158 String[] projection = { MediaStore.Images.Media.DATA, OpenableColumns.SIZE }; 159 cursor = context.getContentResolver().query( 160 data.getData(), projection, null, null, null); 161 cursor.moveToFirst(); 162 int size = cursor.getInt(1); 163 mCurrentPath = cursor.getString(0); 164 165 // TODO: enforce a size limit. May be tricky. 166 167 } finally { 168 if (cursor != null) { 169 cursor.close(); 170 } 171 } 172 } 173 174 @Override 175 public View getEditView(Activity activity, LayoutInflater inflater, ViewGroup parent) { 176 // TODO: make a nicer edit view for images. Right now we just plop the entire image 177 // down. It should also be tappable to select a new image. 178 return new ImageRecord(getValueInternal()).getView(activity, inflater, parent); 179 } 180 181 @Override 182 public void writeToParcel(Parcel out, int flags) { 183 super.writeToParcel(out, flags); 184 out.writeParcelable(mIntent, flags); 185 out.writeString(mCurrentPath); 186 } 187 188 @SuppressWarnings("unused") 189 public static final Parcelable.Creator<ImageRecordEditInfo> CREATOR = 190 new Parcelable.Creator<ImageRecordEditInfo>() { 191 public ImageRecordEditInfo createFromParcel(Parcel in) { 192 return new ImageRecordEditInfo(in); 193 } 194 195 public ImageRecordEditInfo[] newArray(int size) { 196 return new ImageRecordEditInfo[size]; 197 } 198 }; 199 200 @Override 201 public int describeContents() { 202 return 0; 203 } 204 } 205} 206