我使用 muzei 代码(开源 - https://github.com/romannurik/muzei/)开发了一个壁纸,但是在更新壁纸时遇到了一个尴尬的问题。
我在主机中使用本地源而不是 api 或 db。所以我像这样更改了 FeautedArtSource.java;
package com.google.android.apps.muzei.featuredart;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.telephony.SmsManager;
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 com.xxx.xxx.BuildConfig;
import com.xxx.xxx.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.Calendar;
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 String QUERY_URL = "file:///android_asset/starrynight.jpg";
private static Uri ARCHIVE_URI = Uri.parse("file:///android_asset/starrynight.jpg");
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 = 1 * 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);
}
public void urls()
{
Calendar calendar=Calendar.getInstance();
if(calendar.get(Calendar.DATE)==1)
{
QUERY_URL="file:///android_asset/image1.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image1.jpg");
}
if(calendar.get(Calendar.DATE)==2)
{
QUERY_URL="file:///android_asset/image2.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image2.jpg");
}
if(calendar.get(Calendar.DATE)==3)
{
QUERY_URL="file:///android_asset/image3.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image3.jpg");
}
if(calendar.get(Calendar.DATE)==4)
{
QUERY_URL="file:///android_asset/image4.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image4.jpg");
}
if(calendar.get(Calendar.DATE)==5)
{
QUERY_URL="file:///android_asset/image5.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image5.jpg");
}
if(calendar.get(Calendar.DATE)==6)
{
QUERY_URL="file:///android_asset/image6.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image6.jpg");
}
if(calendar.get(Calendar.DATE)==7)
{
QUERY_URL="file:///android_asset/image7.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image7.jpg");
}
if(calendar.get(Calendar.DATE)==8)
{
QUERY_URL="file:///android_asset/image8.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image8.jpg");
}
if(calendar.get(Calendar.DATE)==9)
{
QUERY_URL="file:///android_asset/image9.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image9.jpg");
}
if(calendar.get(Calendar.DATE)==10)
{
QUERY_URL="file:///android_asset/image10.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image10.jpg");
}
if(calendar.get(Calendar.DATE)==11)
{
QUERY_URL="file:///android_asset/image11.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image11.jpg");
}
if(calendar.get(Calendar.DATE)==12)
{
QUERY_URL="file:///android_asset/image12.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image12.jpg");
}
if(calendar.get(Calendar.DATE)==13)
{
QUERY_URL="file:///android_asset/image13.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image13.jpg");
}
if(calendar.get(Calendar.DATE)==14)
{
QUERY_URL="file:///android_asset/image14.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image14.jpg");
}
if(calendar.get(Calendar.DATE)==15)
{
QUERY_URL="file:///android_asset/image15.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image15.jpg");
}
if(calendar.get(Calendar.DATE)==16)
{
QUERY_URL="file:///android_asset/image16.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image16.jpg");
}
if(calendar.get(Calendar.DATE)==17)
{
QUERY_URL="file:///android_asset/image17.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image17.jpg");
}
if(calendar.get(Calendar.DATE)==18)
{
QUERY_URL="file:///android_asset/image18.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image18.jpg");
}
if(calendar.get(Calendar.DATE)==19)
{
QUERY_URL="file:///android_asset/image19.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image19.jpg");
}
if(calendar.get(Calendar.DATE)==20)
{
QUERY_URL="file:///android_asset/image20.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image20.jpg");
}
if(calendar.get(Calendar.DATE)==21)
{
QUERY_URL="file:///android_asset/image21.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image21.jpg");
}
if(calendar.get(Calendar.DATE)==22)
{
QUERY_URL="file:///android_asset/image22.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image22.jpg");
}
if(calendar.get(Calendar.DATE)==23)
{
QUERY_URL="file:///android_asset/image23.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image23.jpg");
}
if(calendar.get(Calendar.DATE)==24)
{
QUERY_URL="file:///android_asset/image24.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image24.jpg");
}
if(calendar.get(Calendar.DATE)==25)
{
QUERY_URL="file:///android_asset/image25.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image25.jpg");
}
if(calendar.get(Calendar.DATE)==26)
{
QUERY_URL="file:///android_asset/image26.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image26.jpg");
}
if(calendar.get(Calendar.DATE)==27)
{
QUERY_URL="file:///android_asset/image27.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image27.jpg");
}
if(calendar.get(Calendar.DATE)==28)
{
QUERY_URL="file:///android_asset/image28.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image28.jpg");
}
if(calendar.get(Calendar.DATE)==29)
{
QUERY_URL="file:///android_asset/image29.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image29.jpg");
}
if(calendar.get(Calendar.DATE)==30)
{
QUERY_URL="file:///android_asset/image30.jpg";
ARCHIVE_URI=Uri.parse("file:///android_asset/image30.jpg");
}
}
@Override
protected void onUpdate(int reason) {
urls();
List<UserCommand> commands = new ArrayList<>();
if (reason == UPDATE_REASON_INITIAL) {
// Show initial photo (starry night)
publishArtwork(new Artwork.Builder()
.imageUri(Uri.parse(QUERY_URL))
.title("xxx")
.token("xxx")
.byline("xxx")
.viewIntent(new Intent(Intent.ACTION_VIEW,
Uri.parse(QUERY_URL)))
.build());
commands.add(new UserCommand(BUILTIN_COMMAND_ID_NEXT_ARTWORK));
// show the latest photo in 15 minutes
scheduleUpdate(System.currentTimeMillis() + 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)));
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);
urls();
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()))
? QUERY_URL
: 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 | 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 e) {
try {
sDateFormatLocal.setTimeZone(TimeZone.getDefault());
nextTime = sDateFormatLocal.parse(nextTimeStr);
} catch (ParseException e2) {
LOGE(TAG, "Can't schedule update; "
+ "invalid date format '" + nextTimeStr + "'", e2);
}
}
}
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() + 1 * 60 * 1000);
}*/
urls();
publishArtwork(new Artwork.Builder()
.imageUri(Uri.parse(QUERY_URL))
.title("xxx")
.token("xxx")
.byline("xxx")
.viewIntent(new Intent(Intent.ACTION_VIEW,
Uri.parse(QUERY_URL)))
.build());
scheduleUpdate(System.currentTimeMillis()+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(QUERY_URL)))
.build());
removeAllUserCommands();
}
super.onHandleIntent(intent);
}
}
当我将它安装到设备上时,它会选择特定日期的正确壁纸(例如:9 月 23 日的图像 23),但问题是;它不会更新第二天的壁纸。
如果我从设备设置菜单中清除应用程序的数据,它会正确更新。
此外,如果我在将日期安装到设备后立即手动更改日期,它工作正常。
这是清单文件;
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.xxx.xxx">
<uses-feature android:name="android.software.live_wallpaper" android:required="true" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- android:maxSdkVersion="18" /> ... has issues on some devices -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Permissions required by the wearable app -->
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
<application android:name="com.google.android.apps.muzei.MuzeiApplication"
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:supportsRtl="true">
<activity
android:name="com.google.android.apps.muzei.MuzeiActivity"
android:theme="@style/Theme.MuzeiActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.google.android.apps.muzei.MuzeiWallpaperService"
android:permission="android.permission.BIND_WALLPAPER">
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
</intent-filter>
<meta-data
android:name="android.service.wallpaper"
android:resource="@xml/wallpaper" />
</service>
<service android:name="com.google.android.apps.muzei.SourceSubscriberService"
android:exported="true" />
<service android:name="com.google.android.apps.muzei.TaskQueueService" />
<activity android:name="com.google.android.apps.muzei.settings.SettingsActivity"
android:label="@string/settings_title"
android:theme="@style/Theme.Muzei.Settings"
android:exported="true"
android:parentActivityName="com.google.android.apps.muzei.MuzeiActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.NOTIFICATION_PREFERENCES" />
</intent-filter>
</activity>
<activity
android:name="com.google.android.apps.muzei.settings.AboutActivity"
android:label="@string/about_title"
android:theme="@style/Theme.Muzei.About"
android:parentActivityName="com.google.android.apps.muzei.settings.SettingsActivity" />
<receiver android:name="com.google.android.apps.muzei.NetworkChangeReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
<!-- Photo sources -->
<service android:name="com.google.android.apps.muzei.featuredart.FeaturedArtSource"
android:label="@string/featuredart_source_title"
android:description="@string/featuredart_source_description"
android:icon="@drawable/ic_source_featured">
<intent-filter>
<action android:name="com.google.android.apps.muzei.api.MuzeiArtSource" />
</intent-filter>
<meta-data android:name="color" android:value="#659fef" />
</service>
<service android:name="com.google.android.apps.muzei.gallery.GalleryArtSource"
android:label="@string/gallery_source_title"
android:description="@string/gallery_source_description"
android:icon="@drawable/ic_source_gallery">
<intent-filter>
<action android:name="com.google.android.apps.muzei.api.MuzeiArtSource" />
</intent-filter>
<meta-data android:name="settingsActivity"
android:value="com.google.android.apps.muzei.gallery.GallerySettingsActivity" />
<meta-data android:name="color" android:value="#4db6ac" />
</service>
<activity android:name="com.google.android.apps.muzei.gallery.GallerySettingsActivity"
android:label="@string/gallery_source_settings_title"
android:parentActivityName="com.google.android.apps.muzei.settings.SettingsActivity"
android:theme="@style/Theme.Muzei.GallerySettings"
android:exported="true" />
<!-- Target for "Set As" intent -->
<activity android:name="com.google.android.apps.muzei.PhotoSetAsTargetActivity"
android:theme="@android:style/Theme.NoDisplay">
<intent-filter android:label="@string/set_as_wallpaper_using_muzei">
<action android:name="android.intent.action.ATTACH_DATA" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
<!-- Watch for source package changes -->
<receiver android:name="com.google.android.apps.muzei.SourcePackageChangeReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_CHANGED" />
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
<!-- New wallpaper notification receiver -->
<receiver android:name="com.google.android.apps.muzei.NewWallpaperNotificationReceiver" />
<service android:name="com.google.android.apps.muzei.MuzeiWearableListenerService"
tools:ignore="ExportedService">
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
</application>
</manifest>
除了这些文件之外,其他文件几乎与原始 muzei 相同,除了图形、标签等。
对解决方案有任何想法吗?