|
Android example source code file (PhotostreamActivity.java)
The PhotostreamActivity.java Android example source code
/*
* Copyright (C) 2008 Google Inc.
*
* 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.google.android.photostream;
import android.app.Activity;
import android.app.NotificationManager;
import android.os.Bundle;
import android.content.Intent;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.view.animation.Animation;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.LayoutAnimationController;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.widget.ImageView;
import android.widget.ViewAnimator;
import java.util.Random;
import java.util.List;
/**
* Activity used to display a Flickr user's photostream. This activity shows a fixed
* number of photos at a time. The activity is invoked either by LoginActivity, when
* the application is launched normally, or by a Home shortcut, or by an Intent with
* the view action and a flickr://photos/nsid URI.
*/
public class PhotostreamActivity extends Activity implements
View.OnClickListener, Animation.AnimationListener {
static final String ACTION = "com.google.android.photostream.FLICKR_STREAM";
static final String EXTRA_NOTIFICATION = "com.google.android.photostream.extra_notify_id";
static final String EXTRA_NSID = "com.google.android.photostream.extra_nsid";
static final String EXTRA_USER = "com.google.android.photostream.extra_user";
private static final String STATE_USER = "com.google.android.photostream.state_user";
private static final String STATE_PAGE = "com.google.android.photostream.state_page";
private static final String STATE_PAGE_COUNT = "com.google.android.photostream.state_pagecount";
private static final int PHOTOS_COUNT_PER_PAGE = 6;
private Flickr.User mUser;
private int mCurrentPage = 1;
private int mPageCount = 0;
private LayoutInflater mInflater;
private ViewAnimator mSwitcher;
private View mMenuNext;
private View mMenuBack;
private View mMenuSeparator;
private GridLayout mGrid;
private LayoutAnimationController mNextAnimation;
private LayoutAnimationController mBackAnimation;
private UserTask<?, ?, ?> mTask;
private String mUsername;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
clearNotification();
// Try to find a user name in the saved instance state or the intent
// that launched the activity. If no valid user NSID can be found, we
// just close the activity.
if (!initialize(savedInstanceState)) {
finish();
return;
}
setContentView(R.layout.screen_photostream);
setupViews();
loadPhotos();
}
private void clearNotification() {
final int notification = getIntent().getIntExtra(EXTRA_NOTIFICATION, -1);
if (notification != -1) {
NotificationManager manager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancel(notification);
}
}
/**
* Starts the PhotostreamActivity for the specified user.
*
* @param context The application's environment.
* @param user The user whose photos to display with a PhotostreamActivity.
*/
static void show(Context context, Flickr.User user) {
final Intent intent = new Intent(ACTION);
intent.putExtra(EXTRA_USER, user);
context.startActivity(intent);
}
/**
* Restores a previously saved state or, if missing, finds the user's NSID
* from the intent used to start the activity.
*
* @param savedInstanceState The saved state, if any.
*
* @return true if a {@link com.google.android.photostream.Flickr.User} was
* found either in the saved state or the intent.
*/
private boolean initialize(Bundle savedInstanceState) {
Flickr.User user;
if (savedInstanceState != null) {
user = savedInstanceState.getParcelable(STATE_USER);
mCurrentPage = savedInstanceState.getInt(STATE_PAGE);
mPageCount = savedInstanceState.getInt(STATE_PAGE_COUNT);
} else {
user = getUser();
}
mUser = user;
return mUser != null || mUsername != null;
}
/**
* Creates a {@link com.google.android.photostream.Flickr.User} instance
* from the intent used to start this activity.
*
* @return The user whose photos will be displayed, or null if no
* user was found.
*/
private Flickr.User getUser() {
final Intent intent = getIntent();
final String action = intent.getAction();
Flickr.User user = null;
if (ACTION.equals(action)) {
final Bundle extras = intent.getExtras();
if (extras != null) {
user = extras.getParcelable(EXTRA_USER);
if (user == null) {
final String nsid = extras.getString(EXTRA_NSID);
if (nsid != null) {
user = Flickr.User.fromId(nsid);
}
}
}
} else if (Intent.ACTION_VIEW.equals(action)) {
final List<String> segments = intent.getData().getPathSegments();
if (segments.size() > 1) {
mUsername = segments.get(1);
}
}
return user;
}
private void setupViews() {
mInflater = LayoutInflater.from(PhotostreamActivity.this);
mNextAnimation = AnimationUtils.loadLayoutAnimation(this, R.anim.layout_slide_next);
mBackAnimation = AnimationUtils.loadLayoutAnimation(this, R.anim.layout_slide_back);
mSwitcher = (ViewAnimator) findViewById(R.id.switcher_menu);
mMenuNext = findViewById(R.id.menu_next);
mMenuBack = findViewById(R.id.menu_back);
mMenuSeparator = findViewById(R.id.menu_separator);
mGrid = (GridLayout) findViewById(R.id.grid_photos);
mMenuNext.setOnClickListener(this);
mMenuBack.setOnClickListener(this);
mMenuBack.setVisibility(View.GONE);
mMenuSeparator.setVisibility(View.GONE);
mGrid.setClipToPadding(false);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(STATE_USER, mUser);
outState.putInt(STATE_PAGE, mCurrentPage);
outState.putInt(STATE_PAGE_COUNT, mPageCount);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mTask != null && mTask.getStatus() == UserTask.Status.RUNNING) {
mTask.cancel(true);
}
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.menu_next:
onNext();
break;
case R.id.menu_back:
onBack();
break;
default:
onShowPhoto((Flickr.Photo) v.getTag());
break;
}
}
@Override
public Object onRetainNonConfigurationInstance() {
final GridLayout grid = mGrid;
final int count = grid.getChildCount();
final LoadedPhoto[] list = new LoadedPhoto[count];
for (int i = 0; i < count; i++) {
final ImageView v = (ImageView) grid.getChildAt(i);
list[i] = new LoadedPhoto(((BitmapDrawable) v.getDrawable()).getBitmap(),
(Flickr.Photo) v.getTag());
}
return list;
}
private void prepareMenu(int pageCount) {
final boolean backVisible = mCurrentPage > 1;
final boolean nextVisible = mCurrentPage < pageCount;
mMenuBack.setVisibility(backVisible ? View.VISIBLE : View.GONE);
mMenuNext.setVisibility(nextVisible ? View.VISIBLE : View.GONE);
mMenuSeparator.setVisibility(backVisible && nextVisible ? View.VISIBLE : View.GONE);
}
private void loadPhotos() {
final Object data = getLastNonConfigurationInstance();
if (data == null) {
mTask = new GetPhotoListTask().execute(mCurrentPage);
} else {
final LoadedPhoto[] photos = (LoadedPhoto[]) data;
for (LoadedPhoto photo : photos) {
addPhoto(photo);
}
prepareMenu(mPageCount);
mSwitcher.showNext();
}
}
private void showPhotos(Flickr.PhotoList photos) {
mTask = new LoadPhotosTask().execute(photos);
}
private void onShowPhoto(Flickr.Photo photo) {
ViewPhotoActivity.show(this, photo);
}
private void onNext() {
mCurrentPage++;
animateAndLoadPhotos(mNextAnimation);
}
private void onBack() {
mCurrentPage--;
animateAndLoadPhotos(mBackAnimation);
}
private void animateAndLoadPhotos(LayoutAnimationController animation) {
mSwitcher.showNext();
mGrid.setLayoutAnimationListener(this);
mGrid.setLayoutAnimation(animation);
mGrid.invalidate();
}
public void onAnimationEnd(Animation animation) {
mGrid.setLayoutAnimationListener(null);
mGrid.setLayoutAnimation(null);
mGrid.removeAllViews();
loadPhotos();
}
public void onAnimationStart(Animation animation) {
}
public void onAnimationRepeat(Animation animation) {
}
private static Animation createAnimationForChild(int childIndex) {
boolean firstColumn = (childIndex & 0x1) == 0;
Animation translate = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, firstColumn ? -1.1f : 1.1f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f);
translate.setInterpolator(new AccelerateDecelerateInterpolator());
translate.setFillAfter(false);
translate.setDuration(300);
return translate;
}
private void addPhoto(LoadedPhoto... value) {
ImageView image = (ImageView) mInflater.inflate(R.layout.grid_item_photo, mGrid, false);
image.setImageBitmap(value[0].mBitmap);
image.startAnimation(createAnimationForChild(mGrid.getChildCount()));
image.setTag(value[0].mPhoto);
image.setOnClickListener(PhotostreamActivity.this);
mGrid.addView(image);
}
/**
* Background task used to load each individual photo. The task loads each photo
* in order and publishes each loaded Bitmap as a progress unit. The tasks ends
* by hiding the progress bar and showing the menu.
*/
private class LoadPhotosTask extends UserTask<Flickr.PhotoList, LoadedPhoto, Flickr.PhotoList> {
private final Random mRandom;
private LoadPhotosTask() {
mRandom = new Random();
}
public Flickr.PhotoList doInBackground(Flickr.PhotoList... params) {
final Flickr.PhotoList list = params[0];
final int count = list.getCount();
for (int i = 0; i < count; i++) {
if (isCancelled()) break;
final Flickr.Photo photo = list.get(i);
Bitmap bitmap = photo.loadPhotoBitmap(Flickr.PhotoSize.THUMBNAIL);
if (!isCancelled()) {
if (bitmap == null) {
final boolean portrait = mRandom.nextFloat() >= 0.5f;
bitmap = BitmapFactory.decodeResource(getResources(), portrait ?
R.drawable.not_found_small_1 : R.drawable.not_found_small_2);
}
publishProgress(new LoadedPhoto(ImageUtilities.rotateAndFrame(bitmap), photo));
bitmap.recycle();
}
}
return list;
}
/**
* Whenever a photo's Bitmap is loaded from the background thread, it is
* displayed in this method by adding a new ImageView in the photos grid.
* Each ImageView's tag contains the {@link com.google.android.photostream.Flickr.Photo}
* it was loaded from.
*
* @param value The photo and its bitmap.
*/
@Override
public void onProgressUpdate(LoadedPhoto... value) {
addPhoto(value);
}
@Override
public void onPostExecute(Flickr.PhotoList result) {
mPageCount = result.getPageCount();
prepareMenu(mPageCount);
mSwitcher.showNext();
mTask = null;
}
}
/**
* Background task used to load the list of photos. The tasks queries Flickr for the
* list of photos to display and ends by starting the LoadPhotosTask.
*/
private class GetPhotoListTask extends UserTask<Integer, Void, Flickr.PhotoList> {
public Flickr.PhotoList doInBackground(Integer... params) {
if (mUsername != null) {
mUser = Flickr.get().findByUserName(mUsername);
mUsername = null;
}
return Flickr.get().getPublicPhotos(mUser, PHOTOS_COUNT_PER_PAGE, params[0]);
}
@Override
public void onPostExecute(Flickr.PhotoList photoList) {
showPhotos(photoList);
mTask = null;
}
}
/**
* A LoadedPhoto contains the Flickr photo and the Bitmap loaded for that photo.
*/
private static class LoadedPhoto {
Bitmap mBitmap;
Flickr.Photo mPhoto;
LoadedPhoto(Bitmap bitmap, Flickr.Photo photo) {
mBitmap = bitmap;
mPhoto = photo;
}
}
}
Other Android examples (source code examples)Here is a short list of links related to this Android PhotostreamActivity.java source code file: |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.