Android Open Source - Muzei Featured Art Source






From Project

Back to project page Muzei.

License

The source code is released under:

Apache License

If you think the Android project Muzei listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright 2014 Google Inc.//  w  w w.  j  a  va  2 s .com
 *
 * 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.apps.muzei.featuredart;

import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.widget.Toast;

import com.google.android.apps.muzei.api.Artwork;
import com.google.android.apps.muzei.api.RemoteMuzeiArtSource;
import com.google.android.apps.muzei.api.UserCommand;
import com.google.android.apps.muzei.util.IOUtil;
import com.google.android.apps.muzei.util.LogUtil;

import net.nurik.roman.muzei.BuildConfig;
import net.nurik.roman.muzei.R;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.TimeZone;

import static com.google.android.apps.muzei.util.LogUtil.LOGD;
import static com.google.android.apps.muzei.util.LogUtil.LOGE;
import static com.google.android.apps.muzei.util.LogUtil.LOGW;

public class FeaturedArtSource extends RemoteMuzeiArtSource {
    private static final String TAG = LogUtil.makeLogTag(FeaturedArtSource.class);
    private static final String SOURCE_NAME = "FeaturedArt";

    private static final String QUERY_URL = "http://muzeiapi.appspot.com/featured?cachebust=1";
    private static final Uri ARCHIVE_URI = Uri.parse("http://muzei.co/archive");

    private static final int COMMAND_ID_SHARE = 1;
    private static final int COMMAND_ID_VIEW_ARCHIVE = 2;
    private static final int COMMAND_ID_DEBUG_INFO = 51;

    private static final int MAX_JITTER_MILLIS = 20 * 60 * 1000;

    private static Random sRandom = new Random();

    private static final SimpleDateFormat sDateFormatTZ
            = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
    private static final SimpleDateFormat sDateFormatLocal
            = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    static {
        sDateFormatTZ.setTimeZone(TimeZone.getTimeZone("UTC"));
    }

    public FeaturedArtSource() {
        super(SOURCE_NAME);
    }

    @Override
    protected void onUpdate(int reason) {
        List<UserCommand> commands = new ArrayList<UserCommand>();
        if (reason == UPDATE_REASON_INITIAL) {
            // Show initial photo (starry night)
            publishArtwork(new Artwork.Builder()
                    .imageUri(Uri.parse("file:///android_asset/starrynight.jpg"))
                    .title("The Starry Night")
                    .token("initial")
                    .byline("Vincent van Gogh, 1889.\nMuzei shows a new painting every day.")
                    .viewIntent(new Intent(Intent.ACTION_VIEW,
                            Uri.parse("http://www.wikipaintings.org/en/vincent-van-gogh/the-starry-night-1889")))
                    .build());
            commands.add(new UserCommand(BUILTIN_COMMAND_ID_NEXT_ARTWORK));
            // show the latest photo in 15 minutes
            scheduleUpdate(System.currentTimeMillis() + 15 * 60 * 1000);

        } else {
            // For everything but the initial update, defer to RemoteMuzeiArtSource
            super.onUpdate(reason);
        }

        commands.add(new UserCommand(COMMAND_ID_SHARE, getString(R.string.action_share_artwork)));
        commands.add(new UserCommand(COMMAND_ID_VIEW_ARCHIVE,
                getString(R.string.featuredart_source_action_view_archive)));
        if (BuildConfig.DEBUG) {
            commands.add(new UserCommand(COMMAND_ID_DEBUG_INFO, "Debug info"));
        }
        setUserCommands(commands);
    }

    @Override
    protected void onSubscriberAdded(ComponentName subscriber) {
        super.onSubscriberAdded(subscriber);
        Artwork currentArtwork = getCurrentArtwork();
        if (currentArtwork != null && !"initial".equals(currentArtwork.getToken())) {
            // TODO: is this really necessary?
            // When a subscriber is added, manually try a fetch, unless this is the
            // first update
            onUpdate(UPDATE_REASON_OTHER);
        }
    }

    @Override
    protected void onCustomCommand(int id) {
        super.onCustomCommand(id);
        if (COMMAND_ID_SHARE == id) {
            Artwork currentArtwork = getCurrentArtwork();
            if (currentArtwork == null) {
                LOGW(TAG, "No current artwork, can't share.");
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(FeaturedArtSource.this,
                                R.string.featuredart_source_error_no_artwork_to_share,
                                Toast.LENGTH_SHORT).show();
                    }
                });
                return;
            }

            String detailUrl = ("initial".equals(currentArtwork.getToken()))
                    ? "http://www.wikipaintings.org/en/vincent-van-gogh/the-starry-night-1889"
                    : currentArtwork.getViewIntent().getDataString();
            String artist = currentArtwork.getByline()
                    .replaceFirst("\\.\\s*($|\\n).*", "").trim();

            Intent shareIntent = new Intent(Intent.ACTION_SEND);
            shareIntent.setType("text/plain");
            shareIntent.putExtra(Intent.EXTRA_TEXT, "My Android wallpaper today is '"
                    + currentArtwork.getTitle().trim()
                    + "' by " + artist
                    + ". #MuzeiFeaturedArt\n\n"
                    + detailUrl);
            shareIntent = Intent.createChooser(shareIntent, "Share artwork");
            shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(shareIntent);

        } else if (COMMAND_ID_VIEW_ARCHIVE == id) {
            Intent viewArchiveIntent = new Intent(Intent.ACTION_VIEW, ARCHIVE_URI);
            viewArchiveIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            try {
                startActivity(viewArchiveIntent);
            } catch (ActivityNotFoundException ignored) {
            }

        } else if (COMMAND_ID_DEBUG_INFO == id) {
            long nextUpdateTimeMillis = getSharedPreferences()
                    .getLong("scheduled_update_time_millis", 0);
            final String nextUpdateTime;
            if (nextUpdateTimeMillis > 0) {
                Date d = new Date(nextUpdateTimeMillis);
                nextUpdateTime = SimpleDateFormat.getDateTimeInstance().format(d);
            } else {
                nextUpdateTime = "None";
            }

            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(FeaturedArtSource.this,
                            "Next update time: " + nextUpdateTime,
                            Toast.LENGTH_LONG).show();
                }
            });
        }
    }

    @Override
    protected void onTryUpdate(int reason) throws RetryException {
        Artwork currentArtwork = getCurrentArtwork();
        Artwork artwork;
        JSONObject jsonObject;
        try {
            jsonObject = IOUtil.fetchJsonObject(QUERY_URL);
            artwork = Artwork.fromJson(jsonObject);
        } catch (JSONException e) {
            LOGE(TAG, "Error reading JSON", e);
            throw new RetryException(e);
        } catch (IOException e) {
            LOGE(TAG, "Error reading JSON", e);
            throw new RetryException(e);
        }

        if (artwork != null && currentArtwork != null && artwork.getImageUri() != null &&
                artwork.getImageUri().equals(currentArtwork.getImageUri())) {
            LOGD(TAG, "Skipping update of same artwork.");
        } else {
            LOGD(TAG, "Publishing artwork update: " + artwork);
            if (artwork != null && jsonObject != null) {
                publishArtwork(artwork);
            }
        }

        Date nextTime = null;
        String nextTimeStr = jsonObject.optString("nextTime");
        if (!TextUtils.isEmpty(nextTimeStr)) {
            int len = nextTimeStr.length();
            if (len > 4 && nextTimeStr.charAt(len - 3) == ':') {
                nextTimeStr = nextTimeStr.substring(0, len - 3) + nextTimeStr.substring(len - 2);
            }
            try {
                nextTime = sDateFormatTZ.parse(nextTimeStr);
            } catch (ParseException ignored) {
                try {
                    sDateFormatLocal.setTimeZone(TimeZone.getDefault());
                    nextTime = sDateFormatLocal.parse(nextTimeStr);
                } catch (ParseException e) {
                    LOGE(TAG, "Can't schedule update; "
                            + "invalid date format '" + nextTimeStr + "'", e);
                }
            }
        }

        boolean scheduleFallback = true;
        if (nextTime != null) {
            // jitter by up to N milliseconds
            scheduleUpdate(nextTime.getTime() + sRandom.nextInt(MAX_JITTER_MILLIS));
            scheduleFallback = false;
        }

        if (scheduleFallback) {
            // No next time, default to checking in 12 hours
            scheduleUpdate(System.currentTimeMillis() + 12 * 60 * 60 * 1000);
        }
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        if (BuildConfig.DEBUG && intent != null && "demoartwork".equals(intent.getAction())) {
            publishArtwork(new Artwork.Builder()
                    .imageUri(Uri.parse(intent.getStringExtra("image")))
                    .title(intent.getStringExtra("title"))
                    .token(intent.getStringExtra("image"))
                    .byline(intent.getStringExtra("byline"))
                    .viewIntent(new Intent(Intent.ACTION_VIEW,
                            Uri.parse(intent.getStringExtra("details"))))
                    .build());
            removeAllUserCommands();
        }

        super.onHandleIntent(intent);
    }
}




Java Source Code List

com.example.muzei.examplecontractwidget.ArtworkUpdateReceiver.java
com.example.muzei.examplecontractwidget.ArtworkUpdateService.java
com.example.muzei.examplecontractwidget.MuzeiAppWidgetProvider.java
com.example.muzei.examplesource500px.Config.java
com.example.muzei.examplesource500px.FiveHundredPxExampleArtSource.java
com.example.muzei.examplesource500px.FiveHundredPxService.java
com.example.muzei.watchface.ArtworkImageLoader.java
com.example.muzei.watchface.MuzeiExampleWatchface.java
com.example.muzei.watchface.WatchfaceArtworkImageLoader.java
com.google.android.apps.muzei.ActivateMuzeiIntentService.java
com.google.android.apps.muzei.ArtDetailViewport.java
com.google.android.apps.muzei.ArtworkCacheIntentService.java
com.google.android.apps.muzei.ArtworkCache.java
com.google.android.apps.muzei.FullScreenActivity.java
com.google.android.apps.muzei.LockScreenVisibleReceiver.java
com.google.android.apps.muzei.MuzeiActivity.java
com.google.android.apps.muzei.MuzeiApplication.java
com.google.android.apps.muzei.MuzeiWallpaperService.java
com.google.android.apps.muzei.MuzeiWatchFace.java
com.google.android.apps.muzei.MuzeiWearableListenerService.java
com.google.android.apps.muzei.MuzeiWearableListenerService.java
com.google.android.apps.muzei.NetworkChangeReceiver.java
com.google.android.apps.muzei.NewWallpaperNotificationReceiver.java
com.google.android.apps.muzei.PhotoSetAsTargetActivity.java
com.google.android.apps.muzei.SourceManager.java
com.google.android.apps.muzei.SourcePackageChangeReceiver.java
com.google.android.apps.muzei.SourceSubscriberService.java
com.google.android.apps.muzei.TaskQueueService.java
com.google.android.apps.muzei.WearableController.java
com.google.android.apps.muzei.api.Artwork.java
com.google.android.apps.muzei.api.MuzeiArtSource.java
com.google.android.apps.muzei.api.MuzeiContract.java
com.google.android.apps.muzei.api.RemoteMuzeiArtSource.java
com.google.android.apps.muzei.api.UserCommand.java
com.google.android.apps.muzei.api.internal.ProtocolConstants.java
com.google.android.apps.muzei.api.internal.SourceState.java
com.google.android.apps.muzei.event.ArtDetailOpenedClosedEvent.java
com.google.android.apps.muzei.event.ArtworkLoadingStateChangedEvent.java
com.google.android.apps.muzei.event.ArtworkSizeChangedEvent.java
com.google.android.apps.muzei.event.BlurAmountChangedEvent.java
com.google.android.apps.muzei.event.CurrentArtworkDownloadedEvent.java
com.google.android.apps.muzei.event.DimAmountChangedEvent.java
com.google.android.apps.muzei.event.GainedNetworkConnectivityEvent.java
com.google.android.apps.muzei.event.GalleryChosenUrisChangedEvent.java
com.google.android.apps.muzei.event.GreyAmountChangedEvent.java
com.google.android.apps.muzei.event.LockScreenVisibleChangedEvent.java
com.google.android.apps.muzei.event.SelectedSourceChangedEvent.java
com.google.android.apps.muzei.event.SelectedSourceStateChangedEvent.java
com.google.android.apps.muzei.event.SwitchingPhotosStateChangedEvent.java
com.google.android.apps.muzei.event.WallpaperActiveStateChangedEvent.java
com.google.android.apps.muzei.event.WallpaperSizeChangedEvent.java
com.google.android.apps.muzei.featuredart.FeaturedArtSource.java
com.google.android.apps.muzei.gallery.GalleryArtSource.java
com.google.android.apps.muzei.gallery.GalleryDatabase.java
com.google.android.apps.muzei.gallery.GalleryEmptyStateGraphicView.java
com.google.android.apps.muzei.gallery.GallerySettingsActivity.java
com.google.android.apps.muzei.gallery.GalleryStore.java
com.google.android.apps.muzei.provider.MuzeiProvider.java
com.google.android.apps.muzei.render.BitmapRegionLoader.java
com.google.android.apps.muzei.render.DemoRenderController.java
com.google.android.apps.muzei.render.GLColorOverlay.java
com.google.android.apps.muzei.render.GLPicture.java
com.google.android.apps.muzei.render.GLTextureView.java
com.google.android.apps.muzei.render.GLUtil.java
com.google.android.apps.muzei.render.ImageUtil.java
com.google.android.apps.muzei.render.MuzeiBlurRenderer.java
com.google.android.apps.muzei.render.MuzeiRendererFragment.java
com.google.android.apps.muzei.render.RealRenderController.java
com.google.android.apps.muzei.render.RenderController.java
com.google.android.apps.muzei.settings.AboutActivity.java
com.google.android.apps.muzei.settings.Prefs.java
com.google.android.apps.muzei.settings.SettingsActivity.java
com.google.android.apps.muzei.settings.SettingsAdvancedFragment.java
com.google.android.apps.muzei.settings.SettingsChooseSourceFragment.java
com.google.android.apps.muzei.util.AnimatedMuzeiLoadingSpinnerView.java
com.google.android.apps.muzei.util.AnimatedMuzeiLogoFragment.java
com.google.android.apps.muzei.util.AnimatedMuzeiLogoView.java
com.google.android.apps.muzei.util.CheatSheet.java
com.google.android.apps.muzei.util.DrawInsetsFrameLayout.java
com.google.android.apps.muzei.util.IOUtil.java
com.google.android.apps.muzei.util.ImageBlurrer.java
com.google.android.apps.muzei.util.LogUtil.java
com.google.android.apps.muzei.util.LogoPaths.java
com.google.android.apps.muzei.util.MathUtil.java
com.google.android.apps.muzei.util.MultiSelectionController.java
com.google.android.apps.muzei.util.ObservableHorizontalScrollView.java
com.google.android.apps.muzei.util.PanScaleProxyView.java
com.google.android.apps.muzei.util.PanView.java
com.google.android.apps.muzei.util.ScrimUtil.java
com.google.android.apps.muzei.util.Scrollbar.java
com.google.android.apps.muzei.util.SelectionBuilder.java
com.google.android.apps.muzei.util.ShadowDipsTextView.java
com.google.android.apps.muzei.util.SvgPathParser.java
com.google.android.apps.muzei.util.TickingFloatAnimator.java
com.google.android.apps.muzei.util.TypefaceUtil.java
com.google.android.apps.muzei.util.Zoomer.java
net.rbgrn.android.glwallpaperservice.BaseConfigChooser.java
net.rbgrn.android.glwallpaperservice.GLWallpaperService.java