1/* 2 * Copyright (C) 2011 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.contacts.tests.streamitems; 18 19import android.app.Activity; 20import android.content.ContentProviderOperation; 21import android.content.ContentUris; 22import android.content.ContentValues; 23import android.content.Intent; 24import android.database.Cursor; 25import android.net.Uri; 26import android.os.Bundle; 27import android.provider.ContactsContract; 28import android.provider.ContactsContract.RawContacts; 29import android.provider.ContactsContract.StreamItemPhotos; 30import android.provider.ContactsContract.StreamItems; 31import android.view.View; 32import android.widget.Button; 33import android.widget.Toast; 34 35import com.android.contacts.model.account.GoogleAccountType; 36import com.android.contacts.tests.R; 37import com.google.common.collect.Lists; 38 39import java.io.IOException; 40import java.io.InputStream; 41import java.util.ArrayList; 42import java.util.Random; 43 44/** 45 * Testing activity that will populate stream items and stream item photos to selected 46 * entries in the user's contacts list. 47 * 48 * The contact selected must have at least one raw contact that was provided by Google. 49 */ 50public class StreamItemPopulatorActivity extends Activity { 51 52 // Test data to randomly select from. 53 private String[] snippetStrings = new String[]{ 54 "Just got back from a vacation in %1$s - what a great place! Can't wait to go back.", 55 "If I never see %1$s again it will be too soon.", 56 "This is a public service announcement. If you were even close to considering visiting" 57 + " %1$s, I strongly advise you to reconsider. The food was terrible, the people were " 58 + "rude, the hygiene of the bus and taxi drivers was positively <i>barbaric</i>. I " 59 + "feared for my life almost the entire time I was there, and feel lucky to be back " 60 + "<b>home</b>.", 61 "Check out these pictures! I took them in %1$s" 62 }; 63 64 private String[] placeNames = new String[]{ 65 "the Google campus in Mountain View", 66 "the deserts on Arrakis", 67 "Iceland", 68 "Japan", 69 "Sydney", 70 "San Francisco", 71 "Munich", 72 "Istanbul", 73 "Tanagra", 74 "the restricted section of Area 51", 75 "the middle of nowhere" 76 }; 77 78 private String[] commentStrings = new String[]{ 79 "3 retweets", 80 "5 shares", 81 "4 likes", 82 "4 +1s", 83 "<i>24567</i> <font color='blue' size='+1'><b>likes</b></font>" 84 }; 85 86 private String[] labelResources = new String[] { 87 "attribution_google_plus", 88 "attribution_google_talk", 89 "attribution_flicker", 90 "attribution_twitter" 91 }; 92 93 public String[] iconResources = new String[] { 94 "default_icon" 95 }; 96 97 // Photos to randomly select from. 98 private Integer[] imageIds = new Integer[]{ 99 R.drawable.android, 100 R.drawable.goldengate, 101 R.drawable.iceland, 102 R.drawable.japan, 103 R.drawable.sydney, 104 R.drawable.wharf, 105 R.drawable.whiskey 106 }; 107 108 // Only some photos have actions. 109 private String[] imageStrings = new String[]{ 110 "android", 111 "goldengate", 112 "iceland", 113 "japan", 114 }; 115 116 // The contact ID that was picked. 117 private long mContactId = -1; 118 119 private Random mRandom; 120 121 @Override 122 protected void onCreate(Bundle savedInstanceState) { 123 super.onCreate(savedInstanceState); 124 125 mRandom = new Random(System.currentTimeMillis()); 126 127 setContentView(R.layout.stream_item_populator); 128 Button pickButton = (Button) findViewById(R.id.add); 129 pickButton.setOnClickListener(new View.OnClickListener(){ 130 @Override 131 public void onClick(View v) { 132 // Reset the contact ID. 133 mContactId = -1; 134 135 // Forward the Intent to the picker 136 final Intent pickerIntent = 137 new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI); 138 pickerIntent.setFlags( 139 Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); 140 startActivityForResult(pickerIntent, 0); 141 } 142 }); 143 144 Button exitButton = (Button) findViewById(R.id.exit); 145 exitButton.setOnClickListener(new View.OnClickListener() { 146 @Override 147 public void onClick(View v) { 148 finish(); 149 } 150 }); 151 } 152 153 @Override 154 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 155 if (resultCode == Activity.RESULT_OK) { 156 Uri contactUri = data.getData(); 157 mContactId = ContentUris.parseId(contactUri); 158 } 159 } 160 161 @Override 162 protected void onResume() { 163 super.onResume(); 164 if (mContactId != -1) { 165 long rawContactId = -1; 166 String accountType = null; 167 String accountName = null; 168 String dataSet = null; 169 170 // Lookup the com.google raw contact for the contact. 171 Cursor c = getContentResolver().query(RawContacts.CONTENT_URI, 172 new String[]{ 173 RawContacts._ID, 174 RawContacts.ACCOUNT_TYPE, 175 RawContacts.ACCOUNT_NAME 176 }, 177 RawContacts.CONTACT_ID + "=? AND " + RawContacts.ACCOUNT_TYPE + "=?", 178 new String[]{String.valueOf(mContactId), GoogleAccountType.ACCOUNT_TYPE}, null); 179 try { 180 c.moveToFirst(); 181 rawContactId = c.getLong(0); 182 accountType = c.getString(1); 183 accountName = c.getString(2); 184 } finally { 185 c.close(); 186 } 187 if (rawContactId != -1) { 188 addStreamItemsToRawContact(rawContactId, accountType, accountName); 189 } else { 190 Toast.makeText(this, 191 "Failed to find raw contact ID for contact ID " + mContactId, 5).show(); 192 } 193 } 194 } 195 196 protected byte[] loadPhotoFromResource(int resourceId) { 197 InputStream is = getResources().openRawResource(resourceId); 198 return readInputStreamFully(is); 199 } 200 201 protected byte[] readInputStreamFully(InputStream is) { 202 try { 203 byte[] buffer = new byte[is.available()]; 204 is.read(buffer); 205 is.close(); 206 return buffer; 207 } catch (IOException e) { 208 throw new RuntimeException(e); 209 } 210 } 211 212 private void addStreamItemsToRawContact(long rawContactId, String accountType, 213 String accountName) { 214 ArrayList<ContentProviderOperation> ops = Lists.newArrayList(); 215 216 // Add from 1-5 stream items. 217 int itemsToAdd = randInt(5) + 1; 218 int opCount = 0; 219 for (int i = 0; i < itemsToAdd; i++) { 220 ContentValues streamItemValues = buildStreamItemValues(accountType, accountName); 221 ops.add(ContentProviderOperation.newInsert( 222 Uri.withAppendedPath( 223 ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, 224 rawContactId), 225 ContactsContract.RawContacts.StreamItems.CONTENT_DIRECTORY)) 226 .withValues(streamItemValues).build()); 227 228 // Maybe add photos - 30% chance per stream item. 229 boolean includePhotos = randInt(100) < 30; 230 if (includePhotos) { 231 // Add 1-5 photos if we're including any. 232 int numPhotos = randInt(5) + 1; 233 for (int j = 0; j < numPhotos; j++) { 234 ContentValues streamItemPhotoValues = 235 buildStreamItemPhotoValues(j, accountType, accountName); 236 ops.add(ContentProviderOperation.newInsert(StreamItems.CONTENT_PHOTO_URI) 237 .withValues(streamItemPhotoValues) 238 .withValueBackReference(StreamItemPhotos.STREAM_ITEM_ID, opCount) 239 .build()); 240 } 241 opCount += numPhotos; 242 } 243 opCount++; 244 } 245 try { 246 getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 247 } catch (Exception e) { 248 // We don't care. This is just for test purposes. 249 throw new RuntimeException(e); 250 } 251 Toast.makeText(this, "Added " + itemsToAdd + " stream item(s) and " 252 + (opCount - itemsToAdd) + " photos", 5).show(); 253 } 254 255 private ContentValues buildStreamItemValues(String accountType, String accountName) { 256 boolean includeAttribution = randInt(100) < 70; 257 boolean includeComments = randInt(100) < 30; 258 boolean includeAction = randInt(100) < 30; 259 ContentValues values = new ContentValues(); 260 String place = pickRandom(placeNames); 261 values.put(StreamItems.TEXT, 262 String.format(pickRandom(snippetStrings) , place) 263 + (includeComments ? " [c]" : "") 264 + (includeAction ? " [a]" : "")); 265 if (includeAttribution) { 266 values.put(StreamItems.RES_PACKAGE, "com.android.contacts.tests"); 267 int sourceIndex = randInt(labelResources.length); 268 values.put(StreamItems.RES_LABEL, labelResources[sourceIndex]); 269 if (sourceIndex < iconResources.length) { 270 values.put(StreamItems.RES_ICON, iconResources[sourceIndex]); 271 } 272 } 273 if (includeComments) { 274 values.put(StreamItems.COMMENTS, pickRandom(commentStrings)); 275 } else { 276 values.put(StreamItems.COMMENTS, ""); 277 } 278 // Set the timestamp to some point in the past. 279 values.put(StreamItems.TIMESTAMP, 280 System.currentTimeMillis() - randInt(360000000)); 281 values.put(RawContacts.ACCOUNT_TYPE, accountType); 282 values.put(RawContacts.ACCOUNT_NAME, accountName); 283 return values; 284 } 285 286 private ContentValues buildStreamItemPhotoValues(int index, String accountType, 287 String accountName) { 288 Integer imageIndex = pickRandom(imageIds); 289 ContentValues values = new ContentValues(); 290 values.put(StreamItemPhotos.SORT_INDEX, index); 291 values.put(StreamItemPhotos.PHOTO, loadPhotoFromResource(imageIndex)); 292 values.put(RawContacts.ACCOUNT_TYPE, accountType); 293 values.put(RawContacts.ACCOUNT_NAME, accountName); 294 return values; 295 } 296 297 private <T> T pickRandom(T[] from) { 298 return from[randInt(from.length)]; 299 } 300 301 private int randInt(int max) { 302 return Math.abs(mRandom.nextInt()) % max; 303 } 304} 305