public void actionNextTimerTask() {
   if (isSlideshowRunning) {
     userCreatedTouchEvent = false;
     gallery.setUserCreatedTouchEvent(false);
     slideshowTimerTask = new SlideshowTimerTask();
     slideshowTimerTask.execute();
   }
 }
  public void actionToggleTitle() {
    Analytics.trackEvent(getApplicationContext(), "actions", "slideshow", "tittle-toggle");
    Log.d(LOG_PREFIX, "action Toggle Title");
    // we need the adapter to change the display title setting
    CustomGallery gallery = (CustomGallery) findViewById(R.id.gallery);
    View selectedView = gallery.getSelectedView();
    ImageAdapter adapter = null;
    if (gallery == null
        || selectedView == null
        || gallery.getAdapter() instanceof ImageAdapter == false) {
      Log.w(
          LOG_PREFIX,
          "Gallery view is not found in actionNextPhoto or adapter is of wrong instance! Let's make sure this doesn't crash the app");
      return;
    }
    adapter = (ImageAdapter) gallery.getAdapter();

    TextView slideshowTitle = (TextView) selectedView.findViewById(R.id.slideshow_title);
    if (slideshowTitle == null) {
      Log.w(LOG_PREFIX, "slideshowTitle is null. Cannot change visibility");
      return;
    }
    int currentVisibility = slideshowTitle.getVisibility();
    int newVisibility = 0;
    if (currentVisibility == View.INVISIBLE) {
      newVisibility = View.VISIBLE;
      setVisibilityOfSlideshowText(selectedView, newVisibility);
      adapter.setDoDisplayPhotoTitle(true);
    } else {
      newVisibility = View.INVISIBLE;
      setVisibilityOfSlideshowText(selectedView, newVisibility);
      adapter.setDoDisplayPhotoTitle(false);
    }

    // trick to get cached views to update themselves
    // adapter.notifyDataSetChanged();
    // let's extend the time untill the photo changes
    userCreatedTouchEvent = true;

    // View nextView = gallery.getChildAt(gallery.getSelectedItemPosition()+1);
    // setVisibilityOfSlideshowText(nextView, newVisibility);
  }
  /** Scroll to the next photo. If we reach the end, let's start over */
  public void actionNextPhoto() {
    CustomGallery gallery = (CustomGallery) findViewById(R.id.gallery);
    if (gallery == null) {
      Log.w(
          LOG_PREFIX,
          "Gallery view is not found in actionNextPhoto! Let's make sure this doesn't crash the app");
      return;
    }

    if (userCreatedTouchEvent || gallery.hasUserCreatedTouchEvent()) {
      Log.i(
          LOG_PREFIX,
          "User created a touch even since time task started. Will not skip to next photo yet");
      return;
    }

    // Log.i(LOG_PREFIX, "Selected position is " + gallery.getSelectedItemPosition()+ " out of "+
    // gallery.getCount());

    // TODO: Evaluate if we should add all queued photos if we are almost at the end

    if (gallery.getSelectedItemPosition() + 1 == gallery.getCount()) {
      Log.i(LOG_PREFIX, "At the end of the slideshow. Starting on the first photo again");
      Analytics.trackEvent(getApplicationContext(), "actions", "slideshow", "cycles-free");
      gallery.setSelection(0);
    } else { // skip to next photo
      gallery.onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, new KeyEvent(0, 0));
    }
  }
  @Override
  public void onDownloadCompleted(DownloadableObject downloadableObject) {
    // unsafe cast, but we have control
    SlideshowPhoto slideshowPhoto = (SlideshowPhoto) downloadableObject;
    if (queuedSlideshowPhotos == null) {
      queuedSlideshowPhotos = new ArrayList<SlideshowPhoto>(20);
    }
    queuedSlideshowPhotos.add(slideshowPhoto);

    // we want to add the slideshow photos as seldom as possible, as it creates a refresh of views
    if (gallery.getCount() <= 5 && queuedSlideshowPhotos.size() >= 5) {
      addSlideshowPhoto(queuedSlideshowPhotos);
      queuedSlideshowPhotos = null;
    } else if (gallery.getCount() - gallery.getSelectedItemPosition() <= 3
        && queuedSlideshowPhotos.size() >= 10) {
      addSlideshowPhoto(queuedSlideshowPhotos);
      queuedSlideshowPhotos = null;
    } else if (queuedSlideshowPhotos.size() >= 50) {
      addSlideshowPhoto(queuedSlideshowPhotos);
      queuedSlideshowPhotos = null;
    }
  }
  @Override
  public boolean onMenuItemSelected(int featureId, MenuItem item) {
    switch (item.getItemId()) {
      case R.id.menuSetAs:
        SlideshowPhoto currentPhoto1 = imageAdapter.getItem(gallery.getSelectedItemPosition());
        Analytics.trackPageView(getApplicationContext(), "/setas");
        Analytics.trackEvent(getApplicationContext(), "actions", "setas", currentPhoto1.getTitle());
        actionSetAsWallpaper(currentPhoto1);

        return true;
      case R.id.menuPreferences:
        Analytics.trackPageView(getApplicationContext(), "/preferences");
        Intent iPreferences = new Intent(this, SlideshowPreferences.class);
        startActivity(iPreferences);
        return true;
      case R.id.menuShare:
        SlideshowPhoto currentPhoto2 = imageAdapter.getItem(gallery.getSelectedItemPosition());
        Analytics.trackPageView(getApplicationContext(), "/share");
        Analytics.trackEvent(getApplicationContext(), "actions", "share", currentPhoto2.getTitle());
        actionSharePhoto(currentPhoto2);

        return true;
      case R.id.menuTitle:
        actionToggleTitle();

        return true;
      case R.id.menuPause:
        actionPauseSlideshow();

        return true;
      case R.id.menuPlay:
        actionResumeSlideshow();

        return true;

      default:
        return super.onMenuItemSelected(featureId, item);
    }
  }
  /* (non-Javadoc)
   * @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)
   */
  @Override
  public boolean onKeyDown(int keyCode, KeyEvent event) {
    Log.d(LOG_PREFIX, "Keyevent in activity" + keyCode);
    // Basically some key-aliases for GoogleTV buttons
    switch (keyCode) {
        // hardcoded some keyevents in order to support 2.1
        // case KeyEvent.KEYCODE_MEDIA_STOP:
        // case KeyEvent.KEYCODE_MEDIA_PAUSE:
      case 86:
      case 127:
        actionPauseSlideshow();

        return true;
        // case KeyEvent.KEYCODE_MEDIA_PLAY:
      case 126:
        actionResumeSlideshow();

        return true;

      case KeyEvent.KEYCODE_MEDIA_NEXT:
      case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
        userCreatedTouchEvent = true;
        gallery.onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, new KeyEvent(0, 0));
        return true;
      case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
      case KeyEvent.KEYCODE_MEDIA_REWIND:
        userCreatedTouchEvent = true;
        gallery.onKeyDown(KeyEvent.KEYCODE_DPAD_LEFT, new KeyEvent(0, 0));
        return true;

      default:
        Log.d(LOG_PREFIX, "Unhandled keyevent " + keyCode);
        break;
    }

    return super.onKeyDown(keyCode, event);
  }
  @Override
  public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    if (SlideshowPreferences.KEY_DO_DELETE_CACHE.equals(key)) {
      // reset photos
      notifyUser(getString(R.string.msg_cachedphotos_slideshow));
      Intent intent = new Intent(Intent.ACTION_MAIN);
      intent.addCategory(Intent.CATEGORY_HOME);
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      startActivity(intent);

      cachedPhotosDeleted = true;

      /*ArrayList<SlideshowPhoto> cachedDrawables = new ArrayList<SlideshowPhoto>(10);
            SlideshowPhoto initialPhoto = new SlideshowPhotoDrawable(this,"title", "description",R.drawable.trey3);
            cachedDrawables.add(initialPhoto);

            //TODO: Find better way for the rootFile to be passed around
            imageAdapter=null;
            imageAdapter=new ImageAdapter(this,0,cachedDrawables,rootFileDirectory);
            gallery.setAdapter(imageAdapter);
            gallery.setSelection(0);
      new PhotoUrlsTask().execute();*/
    } else if (SlideshowPreferences.KEY_TRANSITION_TYPE.equals(key)) {
      boolean doCustomTransition = SlideshowPreferences.doCustomTransition(getApplicationContext());
      // if doTransition, we should normally check which transition and set the corresponding
      // in and out animations on the gallery. Currently we have only one, so we skip it
      gallery.setDoCustomTransition(doCustomTransition);
    } else if (SlideshowPreferences.KEY_DISPLAY_TITLE.equals(key)) {
      boolean doDisplayPhotoTitle =
          SlideshowPreferences.doDisplayPhotoTitle(getApplicationContext());
      imageAdapter.setDoDisplayPhotoTitle(doDisplayPhotoTitle);
    } else if (SlideshowPreferences.KEY_DO_DOWNLOAD_ON_3G.equals(key)) {
      // attempt to download photos again
      new PhotoUrlsTask().execute();
    }
  }
  @Override
  public void onCreate(Bundle savedInstanceState) {
    // make full screen for pre-honeycomb devices
    if (AndroidUtils.isAndroid30()) {
      // 9 == Window.FEATURE_ACTION_BAR_OVERLAY. Done in order to avoid having to use reflection as
      // value is not present in 2.2
      getWindow().requestFeature(9);
    } else { // all pre-3.0 version
      requestWindowFeature(Window.FEATURE_NO_TITLE);
      getWindow()
          .setFlags(
              WindowManager.LayoutParams.FLAG_FULLSCREEN,
              WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }

    Analytics.trackPageView(getApplicationContext(), "/start");

    String rootPath =
        Environment.getExternalStorageDirectory() + SlideshowPreferences.CACHE_DIRECTORY;
    rootFileDirectory = new File(rootPath);

    asyncReadQueue = new AsyncReadQueue<Drawable>(getApplicationContext(), this);

    // register listener so we can handle if the cached photos are deleted
    SharedPreferences settings =
        getSharedPreferences(SlideshowPreferences.PREFS_NAME, MODE_WORLD_READABLE);
    settings.registerOnSharedPreferenceChangeListener(this);

    super.onCreate(savedInstanceState);

    Display display = getWindowManager().getDefaultDisplay();
    screenWidthPx = display.getWidth();
    screenHeightPx = display.getHeight();
    // notifyUser("Resolution discovered "+screenWidthPx + "x"+screenHeightPx);

    setContentView(R.layout.gallery_1);

    // Reference the Gallery view
    gallery = (CustomGallery) findViewById(R.id.gallery);
    // lights out mode for the activity
    // Reflection call similar to gallery.setSystemUiVisibility(View.STATUS_BAR_HIDDEN);
    // Needed since android 2.2 doesn't have method
    onCreateReflectionCalls(gallery, this);

    //// transition time in millis
    gallery.setAnimationDuration(5500);
    // disable annoying click sound on next photo
    gallery.setSoundEffectsEnabled(false);
    // disable sleep
    gallery.setKeepScreenOn(true);
    boolean doCustomTransition = SlideshowPreferences.doCustomTransition(getApplicationContext());
    gallery.setDoCustomTransition(doCustomTransition);

    // Add some hardcoded photos that will be displayed untill we have download the others
    ArrayList<SlideshowPhoto> cachedDrawables = new ArrayList<SlideshowPhoto>(10);
    // FYI the url is only used during share photo
    cachedDrawables.add(
        new SlideshowPhotoDrawable(
            this,
            "Father",
            "Graffiti art captured in Bergen, Norway",
            R.drawable.photo_father,
            "http://dl.dropbox.com/u/4379928/Slideshow/father.JPG"));
    cachedDrawables.add(
        new SlideshowPhotoDrawable(
            this,
            "Handstand",
            "The lightning was just perfect this day, so why not use it for something productively",
            R.drawable.photo_handstand,
            "http://dl.dropbox.com/u/4379928/Slideshow/handstand.jpg"));
    cachedDrawables.add(
        new SlideshowPhotoDrawable(
            this,
            "Lexus",
            "A showcase photo of the Lexus IS series",
            R.drawable.photo_lexus,
            "http://dl.dropbox.com/u/4379928/Slideshow/lexus_is%2Cjpg.jpg"));

    // lets randomize the three hardcoded photos
    long seed = System.nanoTime();
    Collections.shuffle(cachedDrawables, new Random(seed));

    // cachedDrawables.add(new SlideshowPhotoDrawable(this,"test", "test",R.drawable.logo));

    boolean doDisplayPhotoTitle = SlideshowPreferences.doDisplayPhotoTitle(getApplicationContext());
    // create the adapter holding the slideshow photos
    imageAdapter =
        new ImageAdapter(this, 0, cachedDrawables, rootFileDirectory, doDisplayPhotoTitle);
    gallery.setAdapter(imageAdapter);

    // Set a item click listener, and just Toast the clicked position
    // gallery.setOnItemClickListener(new OnItemClickListener() {
    //    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
    //        Toast.makeText(SlideshowActivity.this, "Photo in position " + position + " clicked",
    // Toast.LENGTH_SHORT).show();
    //    }
    // });

    // We also want to show context menu for longpressed items in the gallery
    registerForContextMenu(gallery);

    // The SlideshowTimerTask task is started by onResume (which is called soon after onCreate
    // slideshowTimerTask=  new SlideshowTimerTask();
    // slideshowTimerTask.execute();

    // Canvas test = new Canvas();
    // Log.i(LOG_PREFIX, " Canvas max " +
    // test.getMaximumBitmapHeight()+","+test.getMaximumBitmapHeight());

    new PhotoUrlsTask().execute();
  }