├── .gitignore
├── default.properties
├── res
├── drawable-hdpi
│ └── icon.png
├── drawable-ldpi
│ └── icon.png
├── drawable-mdpi
│ └── icon.png
├── drawable-nodpi
│ ├── close.png
│ ├── share.gif
│ ├── widget_icon.png
│ ├── beautyclock_retry.jpg
│ └── beautyclock_widget_title.png
├── drawable-xhdpi
│ └── icon.png
├── drawable
│ └── beautyclock_widget_bg.9.png
├── xml
│ ├── livewallpaper.xml
│ ├── appwidget_info.xml
│ ├── app_share_widget_info.xml
│ ├── preferences.xml
│ └── preferences_secret.xml
├── xml-v11
│ └── appwidget_info.xml
├── values
│ ├── theme.xml
│ └── strings.xml
├── layout
│ ├── share_widget_layout3.xml
│ ├── share_widget_layout.xml
│ ├── share_layout.xml
│ └── widget_layout.xml
└── values-zh-rTW
│ └── strings.xml
├── src
└── com
│ └── corner23
│ └── android
│ └── beautyclocklivewallpaper
│ ├── BeautyClockBackupAgent.java
│ ├── BootReceiver.java
│ ├── widget
│ ├── WidgetProvider.java
│ ├── ShareWidgetProvider.java
│ └── WidgetService.java
│ ├── asynctasks
│ ├── PlayBellTask.java
│ ├── CacheCleanUpTask.java
│ └── FetchBeautyPictureTask.java
│ ├── SharePicture.java
│ ├── Settings.java
│ └── services
│ ├── UpdateService.java
│ ├── DeadWallpaper.java
│ └── LiveWallpaper.java
├── README
├── LICENSE
└── AndroidManifest.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | gen/*
2 | bin/*
3 | *.DS_Store
4 |
--------------------------------------------------------------------------------
/default.properties:
--------------------------------------------------------------------------------
1 | # Project target.
2 | target=android-14
3 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakalaca/BeautyClockLiveWallpaper/HEAD/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakalaca/BeautyClockLiveWallpaper/HEAD/res/drawable-ldpi/icon.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakalaca/BeautyClockLiveWallpaper/HEAD/res/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/res/drawable-nodpi/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakalaca/BeautyClockLiveWallpaper/HEAD/res/drawable-nodpi/close.png
--------------------------------------------------------------------------------
/res/drawable-nodpi/share.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakalaca/BeautyClockLiveWallpaper/HEAD/res/drawable-nodpi/share.gif
--------------------------------------------------------------------------------
/res/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakalaca/BeautyClockLiveWallpaper/HEAD/res/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/res/drawable-nodpi/widget_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakalaca/BeautyClockLiveWallpaper/HEAD/res/drawable-nodpi/widget_icon.png
--------------------------------------------------------------------------------
/res/drawable-nodpi/beautyclock_retry.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakalaca/BeautyClockLiveWallpaper/HEAD/res/drawable-nodpi/beautyclock_retry.jpg
--------------------------------------------------------------------------------
/res/drawable/beautyclock_widget_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakalaca/BeautyClockLiveWallpaper/HEAD/res/drawable/beautyclock_widget_bg.9.png
--------------------------------------------------------------------------------
/res/drawable-nodpi/beautyclock_widget_title.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakalaca/BeautyClockLiveWallpaper/HEAD/res/drawable-nodpi/beautyclock_widget_title.png
--------------------------------------------------------------------------------
/res/xml/livewallpaper.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/res/xml/appwidget_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/res/xml/app_share_widget_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/res/xml-v11/appwidget_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/res/values/theme.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/res/layout/share_widget_layout3.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
14 |
15 |
--------------------------------------------------------------------------------
/src/com/corner23/android/beautyclocklivewallpaper/BeautyClockBackupAgent.java:
--------------------------------------------------------------------------------
1 | package com.corner23.android.beautyclocklivewallpaper;
2 |
3 | import android.app.backup.BackupAgentHelper;
4 | import android.app.backup.SharedPreferencesBackupHelper;
5 |
6 | public class BeautyClockBackupAgent extends BackupAgentHelper {
7 | // A key to uniquely identify the set of backup data
8 | static final String PREFS_BACKUP_KEY = "prefs";
9 |
10 | // Allocate a helper and add it to the backup agent
11 | @Override
12 | public void onCreate() {
13 | SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, Settings.SHARED_PREFS_NAME);
14 | addHelper(PREFS_BACKUP_KEY, helper);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/res/layout/share_widget_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
14 |
23 |
24 |
--------------------------------------------------------------------------------
/src/com/corner23/android/beautyclocklivewallpaper/BootReceiver.java:
--------------------------------------------------------------------------------
1 | package com.corner23.android.beautyclocklivewallpaper;
2 |
3 | import com.corner23.android.beautyclocklivewallpaper.services.DeadWallpaper;
4 |
5 | import android.content.BroadcastReceiver;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.content.SharedPreferences;
9 |
10 | public class BootReceiver extends BroadcastReceiver {
11 |
12 | public void onReceive(Context context, Intent intent) {
13 | if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
14 | SharedPreferences prefs = context.getSharedPreferences(Settings.SHARED_PREFS_NAME, 0);
15 | if (prefs != null) {
16 | boolean enableDeadWallpaperService = prefs.getBoolean(Settings.PREF_ENABLE_DEADWALLPAPER, false);
17 | if (enableDeadWallpaperService) {
18 | context.startService(new Intent(context, DeadWallpaper.class));
19 | }
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/res/layout/share_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
14 |
22 |
33 |
34 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | Shows beauty tokei on your Android device, current supports:
2 |
3 | http://www.arthur.com.tw (Taiwan)
4 | http://www.clockm.com (Taiwan)
5 | http://www.bijint.com (Japan/HongKong/Korea)
6 |
7 | Just for fun, any questions feel free contact me :-)
8 |
9 | E-mail: shakalaca AT gmail dot com
10 |
11 | v2.5:
12 | * Support 早稲田
13 | * Support widget with picture and share button
14 |
15 | v2.4:
16 | * New share picture layout
17 | * Support wretch/新潟/鹿児島/名古屋/香川/岡山/福岡/金沢/京都/仙台/北海道
18 | * Add option for user to disable scrolling
19 | * Performance tuning
20 | * Fix binan & author picture source URL
21 | * Center picture in settings
22 |
23 | 2010-09-26 v2.3:
24 | * Add share picture widget
25 | * Change UpdateService to fetch only and more power efficient
26 | * Fix error saving pictures in sd card
27 | * Fix other bugs..
28 |
29 | 2010-07-29 v2.1:
30 | * Add Dead Wallpaper for devices don't support live wallpaper
31 | * Refine settings structure
32 |
33 | 2010-07-28 v2.0:
34 | * Rewrite the whole engine
35 | * Prefetch fix number of pictures and save them in cache area
36 |
37 | 2010-07-21 v1.5:
38 | * Use broadcast receiver instead of polling
39 |
40 | 2010-07-20 v1.4:
41 | * Support Lovely Time II
42 | * Verify bell
43 |
44 | 2010-07-17 v1.1:
45 | * Add an option for user to stop fetching picture when screen is off
46 | * Adjust the wallpaper to fit screen.
47 |
48 | 2010-07-17 v1.0:
49 | Initial version
50 |
--------------------------------------------------------------------------------
/src/com/corner23/android/beautyclocklivewallpaper/widget/WidgetProvider.java:
--------------------------------------------------------------------------------
1 | package com.corner23.android.beautyclocklivewallpaper.widget;
2 |
3 | import android.appwidget.AppWidgetManager;
4 | import android.appwidget.AppWidgetProvider;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.util.Log;
8 |
9 | public class WidgetProvider extends AppWidgetProvider {
10 |
11 | private static final String TAG = "WidgetProvider";
12 |
13 | @Override
14 | public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
15 | Log.d(TAG, "onUpdate");
16 | super.onUpdate(context, appWidgetManager, appWidgetIds);
17 |
18 | context.startService(new Intent(context, WidgetService.class));
19 | }
20 |
21 | @Override
22 | public void onReceive(Context context, Intent intent) {
23 | Log.d(TAG, "onReceive");
24 | final String action = intent.getAction();
25 | if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
26 | final int appWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
27 | if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
28 | this.onDeleted(context, new int[] { appWidgetId });
29 | }
30 | } else {
31 | super.onReceive(context, intent);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010, Shaka Huang
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5 |
6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8 | Neither the name of the BeautyClockLiveWallpaper nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10 |
11 |
--------------------------------------------------------------------------------
/res/layout/widget_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
19 |
25 |
26 |
31 |
40 |
41 |
--------------------------------------------------------------------------------
/src/com/corner23/android/beautyclocklivewallpaper/asynctasks/PlayBellTask.java:
--------------------------------------------------------------------------------
1 | package com.corner23.android.beautyclocklivewallpaper.asynctasks;
2 |
3 | import java.io.IOException;
4 |
5 | import android.content.Context;
6 | import android.media.AudioManager;
7 | import android.media.MediaPlayer;
8 | import android.os.AsyncTask;
9 | import android.os.Environment;
10 | import android.util.Log;
11 |
12 | public class PlayBellTask extends AsyncTask {
13 |
14 | private static final String TAG = "PlayBellTask";
15 |
16 | private static final String BELL_TO_PLAY = Environment.getExternalStorageDirectory().getPath() + "/BeautyClock/bell/bell%02d.mp3";
17 |
18 | private Context mContext = null;
19 |
20 | public PlayBellTask(Context context) {
21 | mContext = context;
22 | }
23 |
24 | @Override
25 | protected Void doInBackground(Integer... params) {
26 | int hour = params[0];
27 |
28 | // check phone settings first, if it's in silent or vibration mode, don't play bell!
29 | AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
30 | if (am != null && (am.getRingerMode() == AudioManager.RINGER_MODE_SILENT ||
31 | am.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE)) {
32 | Log.i(TAG, "Phone is in vibration mode or silent mode");
33 | return null;
34 | }
35 |
36 | try {
37 | MediaPlayer mp = new MediaPlayer();
38 | mp.setDataSource(String.format(BELL_TO_PLAY, hour));
39 | mp.prepare();
40 | mp.start();
41 | } catch (IllegalArgumentException e) {
42 | e.printStackTrace();
43 | } catch (IllegalStateException e) {
44 | e.printStackTrace();
45 | } catch (IOException e) {
46 | e.printStackTrace();
47 | }
48 | return null;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/com/corner23/android/beautyclocklivewallpaper/widget/ShareWidgetProvider.java:
--------------------------------------------------------------------------------
1 | package com.corner23.android.beautyclocklivewallpaper.widget;
2 |
3 | import com.corner23.android.beautyclocklivewallpaper.R;
4 | import com.corner23.android.beautyclocklivewallpaper.SharePicture;
5 |
6 | import android.app.PendingIntent;
7 | import android.appwidget.AppWidgetManager;
8 | import android.appwidget.AppWidgetProvider;
9 | import android.content.Context;
10 | import android.content.Intent;
11 | import android.widget.RemoteViews;
12 |
13 | public class ShareWidgetProvider extends AppWidgetProvider {
14 |
15 | @Override
16 | public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
17 | super.onUpdate(context, appWidgetManager, appWidgetIds);
18 |
19 | final int N = appWidgetIds.length;
20 |
21 | // Perform this loop procedure for each App Widget that belongs to this provider
22 | for (int i=0; i {
13 |
14 | private static final String TAG = "CacheCleanUpTask";
15 | private static final String CACHE_FILE_PATH = "%02d%02d.jpg";
16 | private int hour, minute, max_pic;
17 | private Context mContext = null;
18 | private boolean bForceCleanUp = false;
19 |
20 | public CacheCleanUpTask (Context context, boolean bForce) {
21 | mContext = context;
22 | bForceCleanUp = bForce;
23 | }
24 |
25 | private void moveCachedFiles(int h, int m, File _from_root, File _to_root) {
26 | for (int i = 0; i < max_pic; i++) {
27 | String _cache_fname = String.format(CACHE_FILE_PATH, h, m);
28 | File _from = new File(_from_root, _cache_fname);
29 | File _to = new File(_to_root, _cache_fname);
30 | if (_from != null && _to != null) {
31 | if (_from.exists()) {
32 | Log.d(TAG, "Found.." + _cache_fname);
33 | _from.renameTo(_to);
34 | }
35 | }
36 |
37 | if (m == 59) {
38 | h++;
39 | if (h == 24) {
40 | h = 0;
41 | }
42 | m = -1;
43 | }
44 | m++;
45 | }
46 | }
47 |
48 | private void deleteExpiredCacheFiles() {
49 | File[] files = mContext.getCacheDir().listFiles();
50 | for (int i = 0; i < files.length; i++) {
51 | Log.d(TAG, "deleting: " + files[i].getAbsolutePath());
52 | files[i].delete();
53 | }
54 | }
55 |
56 | @Override
57 | protected Void doInBackground(Integer... params) {
58 | hour = params[0];
59 | minute = params[1];
60 | max_pic = params[2];
61 |
62 | File cacheDir = mContext.getCacheDir();
63 | File tmpDir = mContext.getDir("bc_tmp", Context.MODE_PRIVATE);
64 |
65 | if (!bForceCleanUp) {
66 | moveCachedFiles(hour, minute, cacheDir, tmpDir);
67 | }
68 | deleteExpiredCacheFiles();
69 | if (!bForceCleanUp) {
70 | moveCachedFiles(hour, minute, tmpDir, cacheDir);
71 | }
72 |
73 | return null;
74 | }
75 |
76 | @Override
77 | protected void onPostExecute(Void result) {
78 | super.onPostExecute(result);
79 |
80 | Intent intent = new Intent(mContext, UpdateService.class);
81 | intent.putExtra("fetch_pictures", true);
82 | intent.putExtra("hour", hour);
83 | intent.putExtra("minute", minute);
84 | mContext.startService(intent);
85 | }
86 | }
--------------------------------------------------------------------------------
/res/values-zh-rTW/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 美人時計
4 | 美人時計桌布分享小工具
5 | 分享這張桌布
6 | 分享 !
7 | 圖片載入失敗.. 請再試一次.
8 | 我愛這張桌布 !
9 | 我愛這張桌布 !
10 | 我愛這張桌布 !
11 |
12 | 這是個桌面工具, \n\n使用方法: \n1. 在主畫面按 menu 鍵 \n2. 選擇新增 \n3. 選擇小工具 \n4. 選擇美人時計瀏覽器.\n\n設定方法:\n在這畫面按 menu 鍵或在主畫面點選本小工具.\n\n設定準點報時:\n1. 在設定中將這功能開啟.\n2. 在 SD 卡下建立 BeautyClock\\bell 目錄. \n3. 將檔案 bell00.mp3 ~ bell23.mp3 放到前述目錄底下.\n\n使用自訂的圖片來源:\n1. 在 SD 卡下建立 BeautyClock\\pic\\custom 這個目錄.\n2. 將 hhmm.jpg 放進去. (hh = 00 ~ 23 and mm = 00 ~ 59, 代表每分鐘的圖.)
13 | 美人時計設定
14 |
15 | 給那些沒有動態桌布的裝置
16 | 啟用擬動態桌布
17 | 模擬動態桌布, 如果你的裝置有支持動態桌布, 別用
18 |
19 | 一般設定
20 | 選擇圖片來源
21 |
22 | 使用大圖
23 | 如果網站有提供
24 |
25 | 適合螢幕
26 | 將圖片延展至全螢幕
27 |
28 | 取消捲動
29 | 只顯示圖片中間部分
30 |
31 | 新方式更新桌面工具
32 | 如果桌面工具一直無法顯示, 請試著開啟這選項
33 |
34 | 網路設定
35 | 背景抓圖頻率
36 | 設定網路連線間隔
37 |
38 | 螢幕關閉時仍連網抓圖
39 | 這會減低你的電池可用時間
40 |
41 | 進階設定
42 | 儲存圖片
43 | 留一份檔案在 SD 卡
44 |
45 | 整點報時
46 | 請確認 SD 卡中有報時鈴聲
47 |
48 |
--------------------------------------------------------------------------------
/res/xml/preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
11 |
18 |
19 |
23 |
24 |
28 |
29 |
33 |
34 |
38 |
39 |
40 |
41 |
42 |
50 |
51 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/com/corner23/android/beautyclocklivewallpaper/SharePicture.java:
--------------------------------------------------------------------------------
1 | package com.corner23.android.beautyclocklivewallpaper;
2 |
3 | import java.io.File;
4 |
5 | import android.app.Activity;
6 | import android.content.Intent;
7 | import android.content.SharedPreferences;
8 | import android.graphics.Bitmap;
9 | import android.graphics.BitmapFactory;
10 | import android.net.Uri;
11 | import android.os.Bundle;
12 | import android.text.format.Time;
13 | import android.view.View;
14 | import android.widget.ImageView;
15 | import android.widget.TextView;
16 | import android.widget.Toast;
17 |
18 | public class SharePicture extends Activity implements View.OnClickListener {
19 |
20 | private File PictureFile = null;
21 |
22 | private ImageView shareIV = null;
23 | private ImageView closeIV = null;
24 |
25 | private Bitmap LoadCurrentPicture() {
26 | Time mTime = new Time();
27 | mTime.setToNow();
28 |
29 | SharedPreferences mPrefs = getSharedPreferences(Settings.SHARED_PREFS_NAME, 0);
30 | String mStorePath = mPrefs.getString(Settings.PREF_INTERNAL_PICTURE_PATH, "");
31 |
32 | String sFilePath = String.format("%s/%02d%02d.jpg", mStorePath, mTime.hour, mTime.minute);
33 | PictureFile = new File(sFilePath);
34 | if (PictureFile.exists()) {
35 | return BitmapFactory.decodeFile(sFilePath);
36 | }
37 |
38 | sFilePath = String.format("%s/%02d%02d.jpg", getCacheDir().getAbsolutePath(), mTime.hour, mTime.minute);
39 | PictureFile = new File(sFilePath);
40 | if (PictureFile.exists()) {
41 | return BitmapFactory.decodeFile(sFilePath);
42 | }
43 |
44 | PictureFile = null;
45 |
46 | return null;
47 | }
48 |
49 | @Override
50 | protected void onCreate(Bundle savedInstanceState) {
51 | super.onCreate(savedInstanceState);
52 |
53 | setContentView(R.layout.share_layout);
54 |
55 | shareIV = (ImageView) findViewById(R.id.ShareImageView);
56 | Bitmap pic = LoadCurrentPicture();
57 | if (pic != null) {
58 | shareIV.setImageBitmap(pic);
59 | shareIV.setOnClickListener(this);
60 |
61 | TextView tv = (TextView) findViewById(R.id.ShareButton);
62 | tv.setOnClickListener(this);
63 |
64 | closeIV = (ImageView) findViewById(R.id.CloseImageView);
65 | closeIV.setOnClickListener(this);
66 | } else {
67 | Toast.makeText(this, R.string.share_picture_failed_text, Toast.LENGTH_SHORT).show();
68 | SharePicture.this.finish();
69 | }
70 | }
71 |
72 | @Override
73 | public void onClick(View v) {
74 | if (v != closeIV) {
75 | if (PictureFile != null) {
76 | Intent shareIntent = new Intent(Intent.ACTION_SEND);
77 | shareIntent.setType("image/jpeg");
78 | shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(PictureFile));
79 | shareIntent.putExtra(Intent.EXTRA_SUBJECT, getResources().getString(R.string.share_picture_subject_text));
80 | shareIntent.putExtra(Intent.EXTRA_TEXT, getResources().getString(R.string.share_picture_msg_text));
81 | shareIntent.putExtra(Intent.EXTRA_TITLE, getResources().getString(R.string.share_picture_title_text));
82 | startActivity(shareIntent);
83 | } else {
84 | Toast.makeText(SharePicture.this, R.string.share_picture_failed_text, Toast.LENGTH_SHORT).show();
85 | }
86 | }
87 |
88 | SharePicture.this.finish();
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/res/xml/preferences_secret.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
11 |
18 |
19 |
23 |
24 |
28 |
29 |
33 |
34 |
38 |
39 |
40 |
41 |
42 |
50 |
51 |
55 |
56 |
57 |
58 |
59 |
63 |
64 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/src/com/corner23/android/beautyclocklivewallpaper/Settings.java:
--------------------------------------------------------------------------------
1 | package com.corner23.android.beautyclocklivewallpaper;
2 |
3 | import java.io.File;
4 |
5 | import com.corner23.android.beautyclocklivewallpaper.services.DeadWallpaper;
6 |
7 | import android.content.Intent;
8 | import android.content.SharedPreferences;
9 | import android.os.Build;
10 | import android.os.Bundle;
11 | import android.os.Environment;
12 | import android.preference.PreferenceActivity;
13 | import android.preference.PreferenceCategory;
14 |
15 | public class Settings extends PreferenceActivity
16 | implements SharedPreferences.OnSharedPreferenceChangeListener {
17 |
18 | public static final String SHARED_PREFS_NAME = "bclw_settings";
19 |
20 | public static final String PREF_FETCH_WHEN_SCREEN_OFF = "fetch_screen_off";
21 | public static final String PREF_RING_HOURLY = "ring_hourly";
22 | public static final String PREF_SAVE_COPY = "save_copy";
23 | public static final String PREF_FIT_SCREEN = "fit_screen";
24 | public static final String PREF_NO_SCROLL = "no_scroll";
25 | public static final String PREF_FETCH_LARGER_PICTURE = "fetch_larger_picture";
26 | public static final String PREF_PICTURE_SOURCE = "picture_source";
27 | public static final String PREF_ENABLE_DEADWALLPAPER = "bcdw_enable";
28 | public static final String PREF_PICTURE_PER_FETCH = "picture_per_fetch";
29 | public static final String PREF_INTERNAL_PICTURE_PATH = "picture_path";
30 | public static final String PREF_ANOTHERWAY_UPDATE_WIDGET = "update_widget";
31 |
32 | public static final int ID_CUSTOM_TOKEI = 98;
33 |
34 | @Override
35 | protected void onCreate(Bundle icicle) {
36 | super.onCreate(icicle);
37 | getPreferenceManager().setSharedPreferencesName(SHARED_PREFS_NAME);
38 | File secretParadise = new File(Environment.getExternalStorageDirectory() + "/BeautyClock/givemepower");
39 | if (secretParadise.exists()) {
40 | addPreferencesFromResource(R.xml.preferences_secret);
41 | } else {
42 | addPreferencesFromResource(R.xml.preferences);
43 | }
44 |
45 | PreferenceCategory bcdw_section = (PreferenceCategory) findPreference("bcdw_section");
46 | if (bcdw_section != null) {
47 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
48 | getPreferenceScreen().removePreference(bcdw_section);
49 | }
50 | }
51 |
52 | getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
53 | }
54 |
55 | @Override
56 | protected void onResume() {
57 | super.onResume();
58 | }
59 |
60 | @Override
61 | protected void onDestroy() {
62 | getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
63 | super.onDestroy();
64 | }
65 |
66 | public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
67 | if (key == null) {
68 | return;
69 | }
70 |
71 | if (key.equals(PREF_ENABLE_DEADWALLPAPER)) {
72 | boolean enable = prefs.getBoolean(PREF_ENABLE_DEADWALLPAPER, false);
73 | Intent intent = new Intent(this, DeadWallpaper.class);
74 | if (enable) {
75 | startService(intent);
76 | } else {
77 | stopService(intent);
78 | }
79 | }
80 | }
81 | }
82 |
83 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
46 |
47 |
52 |
53 |
54 |
55 |
58 |
59 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Beauty Clock
4 | Beauty Clock Wallpaper Share Widget
5 | Share this wallpaper
6 | Share it !
7 | Error loading picture.. please try again.
8 | I love this wallpaper !
9 | I love this wallpaper !
10 | I love this wallpaper !
11 |
12 | This is a widget, \n\nTo use it: \n1. Press menu key in home screen \n2. Select Add \n3. Select widgets \n4. Choose Beauty Clock.\n\nTo setup widget:\npress menu key here.\n\nTo bell on every hour:\n1. Enable this feature in settings.\n2. Create BeautyClock\\bell directory in your sdcard. \n3. Put bell00.mp3 ~ bell23.mp3 in that directory.\n\nTo use your own tokei:\n1. Create BeautyClock\\pic\\custom directory in your sdcard.\n2. Put hhmm.jpg under that directory. (hh = 00 ~ 23 and mm = 00 ~ 59, which presents every minute.)
13 | Beauty Clock Settings
14 |
15 | For devices not supporting live wallpaper
16 | Enable Dead Wallpaper
17 | Imitated Live Wallpaper. DO NOT use if device supports live wallpaper
18 |
19 | General settings
20 | Choose image source
21 |
22 | Use larger picture
23 | If web site provides
24 |
25 | Fit the screen
26 | Scale the picture to full screen
27 |
28 | No scrolling
29 | Always show center part of the picture
30 |
31 | New way update widget
32 | If there\'s problem showing picture with the widget, try this option
33 |
34 | Network settings
35 | Background fetch frequency
36 | Interval between network connection
37 |
38 | Fetch picture when screen is off
39 | This will reduce your battery time
40 |
41 | Advance settings
42 | Save picture
43 | Save a copy in the SD card
44 |
45 | Ring on every hour
46 | Be sure you have the bells
47 |
48 |
49 | - Arthur
50 | - ClockM
51 | - Bijin-tokei (japan)
52 | - Bijin-tokei (韓国)
53 | - Bijin-tokei (香港)
54 | - Bijin-tokei (新潟)
55 | - Bijin-tokei (鹿児島)
56 | - Bijin-tokei (名古屋)
57 | - Bijin-tokei (香川)
58 | - Bijin-tokei (岡山)
59 | - Bijin-tokei (福岡)
60 | - Bijin-tokei (金沢)
61 | - Bijin-tokei (京都)
62 | - Bijin-tokei (仙台)
63 | - Bijin-tokei (北海道)
64 | - Bijin-tokei (早稲田)
65 | - Bijin-tokei (GAL)
66 | - Bijin-tokei (サーキット)
67 | - Binan-tokei
68 | - Lovely Time II
69 | - Wretch
70 | - Your own tokei
71 | - AV tokei
72 |
73 |
74 |
75 | - Arthur
76 | - ClockM
77 | - Bijin-tokei (japan)
78 | - Bijin-tokei (韓国)
79 | - Bijin-tokei (香港)
80 | - Bijin-tokei (新潟)
81 | - Bijin-tokei (鹿児島)
82 | - Bijin-tokei (名古屋)
83 | - Bijin-tokei (香川)
84 | - Bijin-tokei (岡山)
85 | - Bijin-tokei (福岡)
86 | - Bijin-tokei (金沢)
87 | - Bijin-tokei (京都)
88 | - Bijin-tokei (仙台)
89 | - Bijin-tokei (北海道)
90 | - Bijin-tokei (早稲田)
91 | - Bijin-tokei (GAL)
92 | - Bijin-tokei (サーキット)
93 | - Binan-tokei
94 | - Lovely Time II
95 | - Wretch
96 | - Your own tokei
97 |
98 |
99 |
100 | - Arthur
101 | - ClockM
102 | - Bijin-tokei (japan)
103 | - Bijin-tokei (korea)
104 | - Bijin-tokei (hk)
105 | - Bijin-tokei (niigata)
106 | - Bijin-tokei (kagoshima)
107 | - Bijin-tokei (nagoya)
108 | - Bijin-tokei (kagawa)
109 | - Bijin-tokei (okayama)
110 | - Bijin-tokei (fukuoka)
111 | - Bijin-tokei (kanazawa)
112 | - Bijin-tokei (kyoto)
113 | - Bijin-tokei (sendai)
114 | - Bijin-tokei (hokkaido)
115 | - Bijin-tokei (wasedastyle)
116 | - Bijin-tokei (GAL)
117 | - Bijin-tokei (circuit)
118 | - Binan-tokei
119 | - Lovely Time II
120 | - Wretch
121 | - Your own tokei
122 |
123 |
124 |
125 | - 0
126 | - 1
127 | - 2
128 | - 3
129 | - 4
130 | - 5
131 | - 6
132 | - 7
133 | - 8
134 | - 9
135 | - 10
136 | - 11
137 | - 12
138 | - 13
139 | - 14
140 | - 15
141 | - 16
142 | - 17
143 | - 18
144 | - 19
145 | - 20
146 | - 98
147 | - 99
148 |
149 |
150 |
151 | - 10 minutes
152 | - 20 minutes
153 | - 30 minutes
154 | - 40 minutes
155 | - 50 minutes
156 | - 1 hour
157 |
158 |
159 |
160 | - 15
161 | - 30
162 | - 45
163 | - 60
164 | - 75
165 | - 90
166 |
167 |
168 |
169 |
--------------------------------------------------------------------------------
/src/com/corner23/android/beautyclocklivewallpaper/services/UpdateService.java:
--------------------------------------------------------------------------------
1 | package com.corner23.android.beautyclocklivewallpaper.services;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.util.concurrent.RejectedExecutionException;
6 |
7 | import com.corner23.android.beautyclocklivewallpaper.Settings;
8 | import com.corner23.android.beautyclocklivewallpaper.asynctasks.CacheCleanUpTask;
9 | import com.corner23.android.beautyclocklivewallpaper.asynctasks.FetchBeautyPictureTask;
10 |
11 | import android.app.AlarmManager;
12 | import android.app.PendingIntent;
13 | import android.app.Service;
14 | import android.content.Context;
15 | import android.content.Intent;
16 | import android.content.SharedPreferences;
17 | import android.net.ConnectivityManager;
18 | import android.os.AsyncTask;
19 | import android.os.Environment;
20 | import android.os.Handler;
21 | import android.os.IBinder;
22 | import android.os.SystemClock;
23 | import android.text.format.Time;
24 | import android.util.Log;
25 |
26 | public class UpdateService extends Service {
27 |
28 | public static final String BROADCAST_WALLPAPER_UPDATE = UpdateService.class.getName() + ":UPDATE";
29 |
30 | private static final String TAG = "UpdateService";
31 |
32 | private static final int MAX_TIMEOUT_COUNT = 5;
33 |
34 | private int mHour = 0;
35 | private int mMinute = 0;
36 |
37 | private FetchBeautyPictureTask mFetchBeautyPictureTask = null;
38 | private CacheCleanUpTask mCacheCleanUpTask = null;
39 |
40 | // preferences
41 | private SharedPreferences mPrefs;
42 | private int mPictureSource = 0;
43 | private boolean mFetchWhenScreenOff = true;
44 | private boolean mFetchLargerPicture = true;
45 | private boolean mSaveCopy = false;
46 | private int mPicturesPerFetch = 30;
47 |
48 | // network
49 | private ConnectivityManager cm = null;
50 |
51 | // alarm
52 | private AlarmManager am = null;
53 |
54 | private boolean mStarted = false;
55 | private int mCurrentCount = 0;
56 | private int mTimeOutCount = 0;
57 |
58 | final Handler mHandler = new Handler();
59 |
60 | private void cancelFetchBeautyPictureTask() {
61 | if (mFetchBeautyPictureTask != null &&
62 | mFetchBeautyPictureTask.getStatus() == AsyncTask.Status.RUNNING) {
63 | mFetchBeautyPictureTask.cancel(true);
64 | }
65 | }
66 |
67 | private void startToFetchBeautyPictureTask() {
68 | Log.i(TAG, "startToFetchBeautyPictureTask");
69 | try {
70 | cancelFetchBeautyPictureTask();
71 | mFetchBeautyPictureTask = new FetchBeautyPictureTask(this, cm, mPictureSource, mFetchLargerPicture, mSaveCopy);
72 | if (mCurrentCount == 0) {
73 | mFetchBeautyPictureTask.saveSourcePath();
74 | }
75 | mFetchBeautyPictureTask.execute(mHour, mMinute);
76 | } catch (RejectedExecutionException e) {
77 | e.printStackTrace();
78 | }
79 | }
80 |
81 | private void cancelCleanUpCacheTask() {
82 | if (mCacheCleanUpTask != null &&
83 | mCacheCleanUpTask.getStatus() == AsyncTask.Status.RUNNING) {
84 | mCacheCleanUpTask.cancel(true);
85 | }
86 | }
87 |
88 | private void startToCleanUpCache(int hour, int minute) {
89 | try {
90 | mCacheCleanUpTask = new CacheCleanUpTask(getApplicationContext(), true);
91 | mCacheCleanUpTask.execute(hour, minute, mPicturesPerFetch);
92 | } catch(RejectedExecutionException e) {
93 | e.printStackTrace();
94 | }
95 | }
96 |
97 | private void broadcastUpdate() {
98 | Log.d(TAG, "Broadcast Wallpaper update !!");
99 | Intent i = new Intent(BROADCAST_WALLPAPER_UPDATE);
100 | sendBroadcast(i);
101 | }
102 |
103 | private void UpdatePictures() {
104 | mCurrentCount = 0;
105 |
106 | Log.d(TAG, "mPictureSource: " + mPictureSource);
107 | // don't update on custom files..
108 | if (mPictureSource != Settings.ID_CUSTOM_TOKEI) {
109 | Time mTime = new Time();
110 | mTime.setToNow();
111 |
112 | cancelFetchBeautyPictureTask();
113 | cancelCleanUpCacheTask();
114 | startToCleanUpCache(mTime.hour, mTime.minute);
115 | }
116 |
117 | broadcastUpdate();
118 | }
119 |
120 | private void readDefaultPrefs(SharedPreferences prefs) {
121 | if (prefs == null) {
122 | return;
123 | }
124 |
125 | mFetchWhenScreenOff = prefs.getBoolean(Settings.PREF_FETCH_WHEN_SCREEN_OFF, true);
126 | mSaveCopy = prefs.getBoolean(Settings.PREF_SAVE_COPY, false);
127 | mFetchLargerPicture = prefs.getBoolean(Settings.PREF_FETCH_LARGER_PICTURE, true);
128 | mPictureSource = Integer.parseInt(prefs.getString(Settings.PREF_PICTURE_SOURCE, "0"));
129 | mPicturesPerFetch = Integer.parseInt(prefs.getString(Settings.PREF_PICTURE_PER_FETCH, "30"));
130 | }
131 |
132 | private Runnable fetchTask = new Runnable() {
133 | public void run() {
134 | startToFetchBeautyPictureTask();
135 | }
136 | };
137 |
138 | @Override
139 | public void onStart(Intent intent, int startId) {
140 | onStartCommand(intent, 0, startId);
141 | }
142 |
143 | @Override
144 | public int onStartCommand(Intent intent, int flags, int startId) {
145 | Log.i(TAG, "onStartCommand");
146 |
147 | if (!mStarted) {
148 | mStarted = true;
149 |
150 | readDefaultPrefs(mPrefs);
151 |
152 | PendingIntent pi = PendingIntent.getService(this, 0, new Intent(UpdateService.this, UpdateService.class), 0);
153 | am.cancel(pi);
154 | }
155 |
156 | if (intent != null) {
157 | // from CacheCleanUpTask
158 | if (intent.hasExtra("fetch_pictures")) {
159 | Log.d(TAG, "Finish clean up, fetch pictures..");
160 | // get exact start time
161 | mHour = intent.getIntExtra("hour", 0);
162 | mMinute = intent.getIntExtra("minute", 0);
163 |
164 | readDefaultPrefs(mPrefs);
165 |
166 | if (mPictureSource != Settings.ID_CUSTOM_TOKEI) {
167 | startToFetchBeautyPictureTask();
168 | }
169 | // from FetchBeautyPictureTask
170 | } else if (intent.hasExtra("fetch_pictures_ret")) {
171 | boolean timeout = intent.getBooleanExtra("timeout", false);
172 | boolean success = intent.getBooleanExtra("fetch_success", false);
173 |
174 | Log.d(TAG, "Count:" + mCurrentCount);
175 | if (timeout && mTimeOutCount++ < MAX_TIMEOUT_COUNT) {
176 | Log.i(TAG, "timeout, startToFetchBeautyPicture again");
177 | } else {
178 | if (!success) {
179 | Log.e(TAG, "failed !!");
180 | } else {
181 | if (mCurrentCount == 0) {
182 | broadcastUpdate();
183 | }
184 | }
185 | mTimeOutCount = 0;
186 |
187 | if (mMinute == 59) {
188 | mHour++;
189 | if (mHour == 24) {
190 | mHour = 0;
191 | }
192 | mMinute = -1;
193 | }
194 | mMinute++;
195 | mCurrentCount++;
196 | }
197 |
198 | if (mCurrentCount < mPicturesPerFetch) {
199 | mHandler.postDelayed(fetchTask, 2000);
200 | } else {
201 | mCurrentCount = 0;
202 |
203 | if (mFetchWhenScreenOff) {
204 | Log.d(TAG, "Setting alarm ..");
205 | PendingIntent pi = PendingIntent.getService(this, 0, new Intent(UpdateService.this, UpdateService.class), 0);
206 | long RoundTime = (long)(mPicturesPerFetch * 0.6 * 60 * 1000);
207 |
208 | am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME,
209 | SystemClock.elapsedRealtime() + RoundTime,
210 | RoundTime, pi);
211 | }
212 |
213 | this.stopSelf();
214 | }
215 | // do a full refresh
216 | } else {
217 | Log.d(TAG, "full refresh");
218 | readDefaultPrefs(mPrefs);
219 | UpdatePictures();
220 | }
221 | }
222 |
223 | return START_STICKY;
224 | }
225 |
226 | @Override
227 | public void onCreate() {
228 | super.onCreate();
229 |
230 | // get connection manager for checking network status
231 | cm = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
232 | am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
233 |
234 | mPrefs = getSharedPreferences(Settings.SHARED_PREFS_NAME, 0);
235 |
236 | // create .nomedia to prevent scanning of this folder
237 | try {
238 | File mFile = new File(Environment.getExternalStorageDirectory().getPath() + "/BeautyClock/pic/.nomedia");
239 | if (mFile != null && !mFile.exists()) {
240 | mFile.mkdirs();
241 | mFile.createNewFile();
242 | }
243 | } catch (IOException e) {
244 | }
245 | }
246 |
247 | @Override
248 | public void onDestroy() {
249 | super.onDestroy();
250 |
251 | mHandler.removeCallbacks(fetchTask);
252 | cancelCleanUpCacheTask();
253 | cancelFetchBeautyPictureTask();
254 | }
255 |
256 | @Override
257 | public IBinder onBind(Intent intent) {
258 | return null;
259 | }
260 | }
261 |
--------------------------------------------------------------------------------
/src/com/corner23/android/beautyclocklivewallpaper/widget/WidgetService.java:
--------------------------------------------------------------------------------
1 | package com.corner23.android.beautyclocklivewallpaper.widget;
2 |
3 | import java.io.File;
4 | import java.util.TimeZone;
5 |
6 | import com.corner23.android.beautyclocklivewallpaper.R;
7 | import com.corner23.android.beautyclocklivewallpaper.Settings;
8 | import com.corner23.android.beautyclocklivewallpaper.services.UpdateService;
9 |
10 | import android.app.PendingIntent;
11 | import android.app.Service;
12 | import android.appwidget.AppWidgetManager;
13 | import android.content.BroadcastReceiver;
14 | import android.content.ComponentName;
15 | import android.content.Context;
16 | import android.content.Intent;
17 | import android.content.IntentFilter;
18 | import android.content.SharedPreferences;
19 | import android.graphics.Bitmap;
20 | import android.graphics.BitmapFactory;
21 | import android.net.Uri;
22 | import android.os.IBinder;
23 | import android.text.format.Time;
24 | import android.util.Log;
25 | import android.view.View;
26 | import android.widget.RemoteViews;
27 |
28 | public class WidgetService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener {
29 |
30 | private static final String TAG = "WidgetService";
31 | private static final String DISPLAYTIME_FORMAT = "%02d:%02d";
32 |
33 | private Time mTime = new Time();
34 |
35 | private int mScreenHeight = 0;
36 | private int mScreenWidth = 0;
37 |
38 | private SharedPreferences mPrefs;
39 | private boolean mAnotherWayUpdatWidget = false;
40 |
41 | private boolean mRegScreenBR = false;
42 | private boolean mRegTimeBR = false;
43 | private boolean mRegUpdateBR = false;
44 |
45 | private boolean mFirstTimeUpdate = true;
46 |
47 | private final BroadcastReceiver mWallpaperUpdateBroadcastReceiver = new BroadcastReceiver() {
48 |
49 | @Override
50 | public void onReceive(Context context, Intent intent) {
51 | Log.i(TAG, "mWallpaperUpdateBroadcastReceiver:onReceive");
52 | updateWidget(context);
53 | }
54 | };
55 |
56 | private final BroadcastReceiver mScreenBroadcastReceiver = new BroadcastReceiver() {
57 | @Override
58 | public void onReceive(Context context, Intent intent) {
59 | Log.i(TAG, "mScreenBroadcastReceiver:onReceive");
60 | if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
61 | // Log.i(TAG, "Intent.ACTION_SCREEN_ON");
62 | registerTimeBroadcastReceiver();
63 | registerWallpaperUpdateBroadcastReceiver();
64 |
65 | updateWidget(context);
66 | } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
67 | // Log.i(TAG, "Intent.ACTION_SCREEN_OFF");
68 | unregisterWallpaperUpdateBroadcastReceiver();
69 | unregisterTimeBroadcastReceiver();
70 | }
71 | }
72 | };
73 |
74 | private final BroadcastReceiver mTimeBroadcastReceiver = new BroadcastReceiver() {
75 | @Override
76 | public void onReceive(Context context, Intent intent) {
77 | Log.i(TAG, "mTimeBroadcastReceiver:onReceive");
78 |
79 | if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
80 | String tz = intent.getStringExtra("time-zone");
81 | mTime = new Time(TimeZone.getTimeZone(tz).getID());
82 |
83 | startService(new Intent(context, UpdateService.class));
84 | } else if (intent.getAction().equals(Intent.ACTION_TIME_CHANGED)) {
85 | startService(new Intent(context, UpdateService.class));
86 | } else {
87 | // normal tick, get time
88 | mTime.setToNow();
89 |
90 | updateWidget(context);
91 | }
92 | }
93 | };
94 |
95 | private void registerWallpaperUpdateBroadcastReceiver() {
96 | if (!mRegUpdateBR) {
97 | IntentFilter filter = new IntentFilter();
98 | filter.addAction(UpdateService.BROADCAST_WALLPAPER_UPDATE);
99 | registerReceiver(mWallpaperUpdateBroadcastReceiver, filter);
100 | mRegUpdateBR = true;
101 | }
102 | }
103 |
104 | private void unregisterWallpaperUpdateBroadcastReceiver() {
105 | if (mRegUpdateBR) {
106 | this.unregisterReceiver(mWallpaperUpdateBroadcastReceiver);
107 | mRegUpdateBR = false;
108 | }
109 | }
110 |
111 | private void registerScreenBroadcastReceiver() {
112 | if (!mRegScreenBR) {
113 | IntentFilter filter = new IntentFilter();
114 | filter.addAction(Intent.ACTION_SCREEN_ON);
115 | filter.addAction(Intent.ACTION_SCREEN_OFF);
116 | this.registerReceiver(mScreenBroadcastReceiver, filter);
117 | mRegScreenBR = true;
118 | }
119 | }
120 |
121 | private void unregisterScreenBroadcastReceiver() {
122 | if (mRegScreenBR) {
123 | this.unregisterReceiver(mScreenBroadcastReceiver);
124 | mRegScreenBR = false;
125 | }
126 | }
127 |
128 | private void registerTimeBroadcastReceiver() {
129 | if (!mRegTimeBR) {
130 | IntentFilter filter = new IntentFilter();
131 | filter.addAction(Intent.ACTION_TIME_TICK);
132 | filter.addAction(Intent.ACTION_TIME_CHANGED);
133 | filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
134 | this.registerReceiver(mTimeBroadcastReceiver, filter);
135 | mRegTimeBR = true;
136 | }
137 | }
138 |
139 | private void unregisterTimeBroadcastReceiver() {
140 | if (mRegTimeBR) {
141 | this.unregisterReceiver(mTimeBroadcastReceiver);
142 | mRegTimeBR = false;
143 | }
144 | }
145 |
146 | private String getPicturePath() {
147 | mTime.setToNow();
148 | int hour = mTime.hour;
149 | int minute = mTime.minute;
150 |
151 | String storePath = mPrefs.getString(Settings.PREF_INTERNAL_PICTURE_PATH, "");
152 | int source = Integer.parseInt(mPrefs.getString(Settings.PREF_PICTURE_SOURCE, "0"));
153 |
154 | // check SD card first
155 | String fname = String.format("%s/%02d%02d.jpg", storePath, hour, minute);
156 | File _f_sdcard = new File(fname);
157 | if (!_f_sdcard.exists()) {
158 | fname = String.format("%s/%02d%02d.jpg", getCacheDir().getAbsolutePath(), hour, minute);
159 | File _f_cache = new File(fname);
160 | if (!_f_cache.exists() && source != Settings.ID_CUSTOM_TOKEI) {
161 | Intent intent = new Intent(this, UpdateService.class);
162 | intent.putExtra("fetch_pictures", true);
163 | intent.putExtra("hour", hour);
164 | intent.putExtra("minute", minute);
165 | startService(intent);
166 |
167 | return null;
168 | }
169 | }
170 |
171 | Log.d(TAG, fname);
172 | return fname;
173 | }
174 |
175 | private Bitmap ResizeBitmap(Bitmap bitmap) {
176 | if (bitmap == null) {
177 | Log.d(TAG, "NULL Bitmap !");
178 | return null;
179 | }
180 |
181 | int width = bitmap.getWidth();
182 | int height = bitmap.getHeight();
183 | if (width == 0 || height == 0) {
184 | Log.d(TAG, "Bitmap format error !");
185 | return null;
186 | }
187 |
188 | if (width < mScreenWidth && height < mScreenHeight) {
189 | return null;
190 | }
191 |
192 | if (height > width) {
193 | double ratio = (double) mScreenHeight / height;
194 | height = mScreenHeight;
195 | width = (int) (width * ratio);
196 | } else {
197 | double ratio = (double) mScreenWidth / width;
198 | width = mScreenWidth;
199 | height = (int) (height * ratio);
200 | }
201 |
202 | return Bitmap.createScaledBitmap(bitmap, width, height, true);
203 | }
204 |
205 | private void updateWidget(Context context) {
206 | Log.i(TAG, "updateWidget");
207 |
208 | AppWidgetManager awm = AppWidgetManager.getInstance(context);
209 | ComponentName remoteWidget = new ComponentName(context, WidgetProvider.class);
210 | RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
211 |
212 | if (awm != null && remoteWidget != null && remoteViews != null) {
213 | mTime.setToNow();
214 |
215 | Intent intent = new Intent(context, Settings.class);
216 | PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
217 |
218 | remoteViews.setTextViewText(R.id.TimeTextView, String.format(DISPLAYTIME_FORMAT, mTime.hour, mTime.minute));
219 | remoteViews.setOnClickPendingIntent(R.id.BeautyClockImageView, pendingIntent);
220 | remoteViews.setImageViewResource(R.id.BeautyClockImageView, R.drawable.beautyclock_retry);
221 | remoteViews.setViewVisibility(R.id.ShareIt, View.GONE);
222 |
223 | if (mFirstTimeUpdate) {
224 | mFirstTimeUpdate = false;
225 | } else {
226 | String fname = getPicturePath();
227 | if (fname != null) {
228 | Uri pictureUri = Uri.fromFile(new File(fname));
229 | if (mAnotherWayUpdatWidget) {
230 | remoteViews.setImageViewUri(R.id.BeautyClockImageView, pictureUri);
231 | } else {
232 | Bitmap bitmap = BitmapFactory.decodeFile(fname);
233 | Bitmap bitmap_scaled = ResizeBitmap(bitmap);
234 | if (bitmap_scaled != null) {
235 | Log.d(TAG, "scaled");
236 | remoteViews.setImageViewBitmap(R.id.BeautyClockImageView, bitmap_scaled);
237 | } else {
238 | Log.d(TAG, "original");
239 | remoteViews.setImageViewBitmap(R.id.BeautyClockImageView, bitmap);
240 | }
241 | }
242 |
243 | Intent shareIntent = new Intent(Intent.ACTION_SEND);
244 | shareIntent.setType("image/jpeg");
245 | shareIntent.putExtra(Intent.EXTRA_STREAM, pictureUri);
246 | shareIntent.putExtra(Intent.EXTRA_SUBJECT, context.getResources().getString(R.string.share_picture_subject_text));
247 | shareIntent.putExtra(Intent.EXTRA_TEXT, context.getResources().getString(R.string.share_picture_msg_text));
248 | shareIntent.putExtra(Intent.EXTRA_TITLE, context.getResources().getString(R.string.share_picture_title_text));
249 | PendingIntent pi_share = PendingIntent.getActivity(context, 0, shareIntent, 0);
250 |
251 | remoteViews.setOnClickPendingIntent(R.id.ShareIt, pi_share);
252 | remoteViews.setViewVisibility(R.id.ShareIt, View.VISIBLE);
253 | }
254 | }
255 |
256 | awm.updateAppWidget(remoteWidget, remoteViews);
257 | }
258 | }
259 |
260 | @Override
261 | public void onCreate() {
262 | super.onCreate();
263 |
264 | this.getCacheDir().mkdirs();
265 |
266 | // register notification
267 | registerWallpaperUpdateBroadcastReceiver();
268 | registerTimeBroadcastReceiver();
269 | registerScreenBroadcastReceiver();
270 |
271 | mPrefs = getSharedPreferences(Settings.SHARED_PREFS_NAME, 0);
272 | mPrefs.registerOnSharedPreferenceChangeListener(this);
273 | onSharedPreferenceChanged(mPrefs, null);
274 |
275 | int max_size = 4 * 74 - 2; // refer to http://developer.android.com/guide/topics/appwidgets/index.html
276 | mScreenHeight = (int) (max_size * getResources().getDisplayMetrics().density);
277 | mScreenWidth = (int) (max_size * getResources().getDisplayMetrics().density);
278 |
279 | startService(new Intent(this, UpdateService.class));
280 | }
281 |
282 | @Override
283 | public void onDestroy() {
284 | unregisterWallpaperUpdateBroadcastReceiver();
285 | unregisterTimeBroadcastReceiver();
286 | unregisterScreenBroadcastReceiver();
287 |
288 | stopService(new Intent(this, UpdateService.class));
289 |
290 | super.onDestroy();
291 | }
292 |
293 | @Override
294 | public void onStart(Intent intent, int startId) {
295 | onStartCommand(intent, 0, startId);
296 | }
297 |
298 | @Override
299 | public int onStartCommand(Intent intent, int flags, int startId) {
300 | Log.i(TAG, "onStartCommand");
301 |
302 | updateWidget(this);
303 |
304 | return START_STICKY;
305 | }
306 |
307 | @Override
308 | public IBinder onBind(Intent intent) {
309 | return null;
310 | }
311 |
312 | public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
313 | if (prefs == null) {
314 | return;
315 | }
316 |
317 | if (key == null) {
318 | return;
319 | }
320 |
321 | if (key.equals(Settings.PREF_SAVE_COPY) ||
322 | key.equals(Settings.PREF_FETCH_LARGER_PICTURE) ||
323 | key.equals(Settings.PREF_PICTURE_SOURCE) ||
324 | key.equals(Settings.PREF_PICTURE_PER_FETCH)) {
325 | mFirstTimeUpdate = true;
326 | startService(new Intent(this, UpdateService.class));
327 | } else if (key.equals(Settings.PREF_ANOTHERWAY_UPDATE_WIDGET)) {
328 | mAnotherWayUpdatWidget = prefs.getBoolean(Settings.PREF_ANOTHERWAY_UPDATE_WIDGET, false);
329 | updateWidget(this);
330 | }
331 | }
332 | }
333 |
--------------------------------------------------------------------------------
/src/com/corner23/android/beautyclocklivewallpaper/services/DeadWallpaper.java:
--------------------------------------------------------------------------------
1 | package com.corner23.android.beautyclocklivewallpaper.services;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.util.TimeZone;
6 | import java.util.concurrent.RejectedExecutionException;
7 |
8 | import com.corner23.android.beautyclocklivewallpaper.Settings;
9 | import com.corner23.android.beautyclocklivewallpaper.asynctasks.PlayBellTask;
10 |
11 | import android.app.Service;
12 | import android.app.WallpaperManager;
13 | import android.content.BroadcastReceiver;
14 | import android.content.Context;
15 | import android.content.Intent;
16 | import android.content.IntentFilter;
17 | import android.content.SharedPreferences;
18 | import android.graphics.Bitmap;
19 | import android.graphics.BitmapFactory;
20 | import android.os.AsyncTask;
21 | import android.os.IBinder;
22 | import android.text.format.Time;
23 | import android.util.Log;
24 |
25 | public class DeadWallpaper extends Service implements SharedPreferences.OnSharedPreferenceChangeListener {
26 |
27 | private static final String TAG = "DeadWallpaper";
28 |
29 | private Time mTime = new Time();
30 |
31 | // preferences
32 | private boolean mFitScreen = false;
33 | private String mStorePath = null;
34 | private boolean mBellHourly = false;
35 | private boolean mNoScroll = false;
36 |
37 | private int mScreenHeight = 0;
38 | private int mScreenWidth = 0;
39 | private SharedPreferences mPrefs;
40 | private WallpaperManager wm = null;
41 | private int OrigWallpaperWidth = 0;
42 | private int OrigWallpaperHeight = 0;
43 |
44 | private Bitmap mBeautyBitmap = null;
45 | private int mBitmapHeight = 0;
46 | private int mBitmapWidth = 0;
47 |
48 | private boolean mRegScreenBR = false;
49 | private boolean mRegTimeBR = false;
50 | private boolean mRegUpdateBR = false;
51 |
52 | private PlayBellTask mPlayBellTask = null;
53 |
54 | private final BroadcastReceiver mWallpaperUpdateBroadcastReceiver = new BroadcastReceiver() {
55 |
56 | @Override
57 | public void onReceive(Context context, Intent intent) {
58 | Log.i(TAG, "mWallpaperUpdateBroadcastReceiver:onReceive");
59 | updateBeautyBitmap();
60 | setWallpaper();
61 | }
62 | };
63 |
64 | private final BroadcastReceiver mScreenBroadcastReceiver = new BroadcastReceiver() {
65 | @Override
66 | public void onReceive(Context context, Intent intent) {
67 | Log.i(TAG, "mScreenBroadcastReceiver:onReceive");
68 | if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
69 | // Log.i(TAG, "Intent.ACTION_SCREEN_ON");
70 | registerTimeBroadcastReceiver();
71 | registerWallpaperUpdateBroadcastReceiver();
72 |
73 | updateBeautyBitmap();
74 | setWallpaper();
75 | } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
76 | // Log.i(TAG, "Intent.ACTION_SCREEN_OFF");
77 | unregisterWallpaperUpdateBroadcastReceiver();
78 | unregisterTimeBroadcastReceiver();
79 | }
80 | }
81 | };
82 |
83 | private final BroadcastReceiver mTimeBroadcastReceiver = new BroadcastReceiver() {
84 | @Override
85 | public void onReceive(Context context, Intent intent) {
86 | Log.i(TAG, "mTimeBroadcastReceiver:onReceive");
87 |
88 | if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
89 | String tz = intent.getStringExtra("time-zone");
90 | mTime = new Time(TimeZone.getTimeZone(tz).getID());
91 |
92 | startService(new Intent(context, UpdateService.class));
93 | } else if (intent.getAction().equals(Intent.ACTION_TIME_CHANGED)) {
94 | startService(new Intent(context, UpdateService.class));
95 | } else {
96 | // normal tick, get time
97 | mTime.setToNow();
98 |
99 | if (mTime.minute == 0 && mBellHourly) {
100 | cancelPlayBellTask();
101 | startToPlayBell(mTime.hour);
102 | }
103 |
104 | updateBeautyBitmap();
105 | setWallpaper();
106 | }
107 | }
108 | };
109 |
110 | private void registerWallpaperUpdateBroadcastReceiver() {
111 | if (!mRegUpdateBR) {
112 | IntentFilter filter = new IntentFilter();
113 | filter.addAction(UpdateService.BROADCAST_WALLPAPER_UPDATE);
114 | registerReceiver(mWallpaperUpdateBroadcastReceiver, filter);
115 | mRegUpdateBR = true;
116 | }
117 | }
118 |
119 | private void unregisterWallpaperUpdateBroadcastReceiver() {
120 | if (mRegUpdateBR) {
121 | this.unregisterReceiver(mWallpaperUpdateBroadcastReceiver);
122 | mRegUpdateBR = false;
123 | }
124 | }
125 |
126 | private void registerScreenBroadcastReceiver() {
127 | if (!mRegScreenBR) {
128 | IntentFilter filter = new IntentFilter();
129 | filter.addAction(Intent.ACTION_SCREEN_ON);
130 | filter.addAction(Intent.ACTION_SCREEN_OFF);
131 | this.registerReceiver(mScreenBroadcastReceiver, filter);
132 | mRegScreenBR = true;
133 | }
134 | }
135 |
136 | private void unregisterScreenBroadcastReceiver() {
137 | if (mRegScreenBR) {
138 | this.unregisterReceiver(mScreenBroadcastReceiver);
139 | mRegScreenBR = false;
140 | }
141 | }
142 |
143 | private void registerTimeBroadcastReceiver() {
144 | if (!mRegTimeBR) {
145 | IntentFilter filter = new IntentFilter();
146 | filter.addAction(Intent.ACTION_TIME_TICK);
147 | filter.addAction(Intent.ACTION_TIME_CHANGED);
148 | filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
149 | this.registerReceiver(mTimeBroadcastReceiver, filter);
150 | mRegTimeBR = true;
151 | }
152 | }
153 |
154 | private void unregisterTimeBroadcastReceiver() {
155 | if (mRegTimeBR) {
156 | this.unregisterReceiver(mTimeBroadcastReceiver);
157 | mRegTimeBR = false;
158 | }
159 | }
160 |
161 | private void cancelPlayBellTask() {
162 | if (mPlayBellTask != null &&
163 | mPlayBellTask.getStatus() == AsyncTask.Status.RUNNING) {
164 | mPlayBellTask.cancel(true);
165 | }
166 | }
167 |
168 | private void startToPlayBell(int hour) {
169 | try {
170 | mPlayBellTask = new PlayBellTask(this);
171 | mPlayBellTask.execute(hour);
172 | } catch(RejectedExecutionException e) {
173 | e.printStackTrace();
174 | }
175 | }
176 |
177 | private void updateBeautyBitmap() {
178 | mTime.setToNow();
179 | int hour = mTime.hour;
180 | int minute = mTime.minute;
181 |
182 | // check SD card first
183 | String fname = String.format("%s/%02d%02d.jpg", mStorePath, hour, minute);
184 | File _f_sdcard = new File(fname);
185 | if (!_f_sdcard.exists()) {
186 | fname = String.format("%s/%02d%02d.jpg", getCacheDir().getAbsolutePath(), hour, minute);
187 |
188 | File _f_cache = new File(fname);
189 | if (!_f_cache.exists()) {
190 | Intent intent = new Intent(this, UpdateService.class);
191 | intent.putExtra("fetch_pictures", true);
192 | intent.putExtra("hour", hour);
193 | intent.putExtra("minute", minute);
194 | startService(intent);
195 | return;
196 | }
197 | }
198 |
199 | if (mBeautyBitmap != null) {
200 | mBeautyBitmap.recycle();
201 | }
202 | mBeautyBitmap = BitmapFactory.decodeFile(fname);
203 | }
204 |
205 | private void CalculateRightSize(Bitmap bitmap) {
206 | if (bitmap == null) {
207 | return;
208 | }
209 |
210 | int width = bitmap.getWidth();
211 | int height = bitmap.getHeight();
212 | if (width == 0 || height == 0) {
213 | return;
214 | }
215 |
216 | if (mScreenWidth > mScreenHeight) {
217 | double ratio = (double) mScreenHeight / height;
218 | width = (int) (width * ratio);
219 | height = mScreenHeight;
220 | } else {
221 | if (height > width) {
222 | if (mFitScreen) {
223 | height = mScreenHeight;
224 | } else {
225 | double ratio = (double) mScreenWidth / width;
226 | height = (int) (height * ratio);
227 | }
228 | width = mScreenWidth;
229 | } else {
230 | if (mFitScreen) {
231 | height = mScreenHeight;
232 | } else {
233 | double ratio = (double) mScreenWidth*2 / width;
234 | height = (int) (height * ratio);
235 | }
236 | width = mScreenWidth*2;
237 | }
238 | }
239 |
240 | mBitmapHeight = height;
241 | mBitmapWidth = width;
242 |
243 |
244 | if (mNoScroll) {
245 | // Log.d(TAG, "w:" + width + ", h:" + height);
246 | // Log.d(TAG, "Sw:" + mScreenWidth + ", Sh:" + mScreenHeight);
247 | int Xpos = (width - mScreenWidth)/2;
248 | if (Xpos < 0) {
249 | Xpos = 0;
250 | }
251 | Bitmap tmpBitmap = Bitmap.createScaledBitmap(mBeautyBitmap, width, height, true);
252 | mBeautyBitmap.recycle();
253 | mBeautyBitmap = Bitmap.createBitmap(tmpBitmap, Xpos, 0, mScreenWidth, height);
254 | mBitmapHeight = mScreenHeight;
255 | mBitmapWidth = mScreenWidth;
256 | }
257 | }
258 |
259 | private void setWallpaper() {
260 | try {
261 | if (mBeautyBitmap != null) {
262 | CalculateRightSize(mBeautyBitmap);
263 |
264 | wm.setBitmap(mBeautyBitmap);
265 |
266 | if (mBitmapWidth != 0 && mBitmapHeight != 0) {
267 | wm.suggestDesiredDimensions(mBitmapWidth, mBitmapHeight);
268 | } else {
269 | if (mBitmapWidth == 0) {
270 | Log.e(TAG, "Width is zero !");
271 | }
272 |
273 | if (mBitmapHeight == 0) {
274 | Log.e(TAG, "Height is zero !");
275 | }
276 | }
277 | }
278 | } catch (IOException e) {
279 | Log.e(TAG, "Error setting wallpaper ! :" + e.getMessage());
280 | }
281 | }
282 |
283 | @Override
284 | public void onCreate() {
285 | super.onCreate();
286 |
287 | this.getCacheDir().mkdirs();
288 |
289 | // register notification
290 | registerWallpaperUpdateBroadcastReceiver();
291 | registerTimeBroadcastReceiver();
292 | registerScreenBroadcastReceiver();
293 |
294 | mScreenHeight = getResources().getDisplayMetrics().heightPixels;
295 | mScreenWidth = getResources().getDisplayMetrics().widthPixels;
296 |
297 | mPrefs = getSharedPreferences(Settings.SHARED_PREFS_NAME, 0);
298 | mPrefs.registerOnSharedPreferenceChangeListener(this);
299 | onSharedPreferenceChanged(mPrefs, null);
300 |
301 | wm = WallpaperManager.getInstance(this);
302 | OrigWallpaperWidth = wm.getDesiredMinimumWidth();
303 | OrigWallpaperHeight = wm.getDesiredMinimumHeight();
304 | Log.d(TAG, OrigWallpaperWidth + "x" + OrigWallpaperHeight);
305 |
306 | startService(new Intent(DeadWallpaper.this, UpdateService.class));
307 | }
308 |
309 | public void onDestroy() {
310 | cancelPlayBellTask();
311 |
312 | unregisterWallpaperUpdateBroadcastReceiver();
313 | unregisterTimeBroadcastReceiver();
314 | unregisterScreenBroadcastReceiver();
315 |
316 | stopService(new Intent(DeadWallpaper.this, UpdateService.class));
317 |
318 | try {
319 | wm.suggestDesiredDimensions(OrigWallpaperWidth, OrigWallpaperHeight);
320 | wm.clear();
321 | Log.d(TAG, OrigWallpaperWidth + "x" + OrigWallpaperHeight);
322 | } catch (IOException e) {
323 | e.printStackTrace();
324 | }
325 |
326 | super.onDestroy();
327 | }
328 |
329 | @Override
330 | public void onStart(Intent intent, int startId) {
331 | onStartCommand(intent, 0, startId);
332 | }
333 |
334 | @Override
335 | public int onStartCommand(Intent intent, int flags, int startId) {
336 | Log.i(TAG, "onStartCommand");
337 |
338 | updateBeautyBitmap();
339 | setWallpaper();
340 |
341 | return START_STICKY;
342 | }
343 |
344 | @Override
345 | public IBinder onBind(Intent intent) {
346 | return null;
347 | }
348 |
349 | public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
350 | if (prefs == null) {
351 | return;
352 | }
353 |
354 | if (key == null) {
355 | mFitScreen = prefs.getBoolean(Settings.PREF_FIT_SCREEN, false);
356 | mStorePath = prefs.getString(Settings.PREF_INTERNAL_PICTURE_PATH, "");
357 | mBellHourly = prefs.getBoolean(Settings.PREF_RING_HOURLY, false);
358 | mNoScroll = prefs.getBoolean(Settings.PREF_NO_SCROLL, false);
359 |
360 | return;
361 | }
362 |
363 | if (key.equals(Settings.PREF_FIT_SCREEN)) {
364 | mFitScreen = prefs.getBoolean(Settings.PREF_FIT_SCREEN, false);
365 | setWallpaper();
366 | } else if (key.equals(Settings.PREF_INTERNAL_PICTURE_PATH)) {
367 | mStorePath = prefs.getString(Settings.PREF_INTERNAL_PICTURE_PATH, "");
368 | } else if (key.equals(Settings.PREF_RING_HOURLY)) {
369 | mBellHourly = prefs.getBoolean(Settings.PREF_RING_HOURLY, false);
370 | } else if (key.equals(Settings.PREF_SAVE_COPY) ||
371 | key.equals(Settings.PREF_FETCH_LARGER_PICTURE) ||
372 | key.equals(Settings.PREF_PICTURE_SOURCE) ||
373 | key.equals(Settings.PREF_PICTURE_PER_FETCH)) {
374 | startService(new Intent(this, UpdateService.class));
375 | } else if (key.equals(Settings.PREF_NO_SCROLL)) {
376 | mNoScroll = prefs.getBoolean(Settings.PREF_NO_SCROLL, false);
377 | setWallpaper();
378 | }
379 | }
380 | }
381 |
--------------------------------------------------------------------------------
/src/com/corner23/android/beautyclocklivewallpaper/services/LiveWallpaper.java:
--------------------------------------------------------------------------------
1 | package com.corner23.android.beautyclocklivewallpaper.services;
2 |
3 | import java.io.File;
4 | import java.util.TimeZone;
5 | import java.util.concurrent.RejectedExecutionException;
6 |
7 | import com.corner23.android.beautyclocklivewallpaper.Settings;
8 | import com.corner23.android.beautyclocklivewallpaper.asynctasks.PlayBellTask;
9 |
10 | import android.content.BroadcastReceiver;
11 | import android.content.Context;
12 | import android.content.Intent;
13 | import android.content.IntentFilter;
14 | import android.content.SharedPreferences;
15 | import android.graphics.Bitmap;
16 | import android.graphics.BitmapFactory;
17 | import android.graphics.Canvas;
18 | import android.graphics.Color;
19 | import android.graphics.Paint;
20 | import android.os.AsyncTask;
21 | import android.service.wallpaper.WallpaperService;
22 | import android.text.format.Time;
23 | import android.util.Log;
24 | import android.view.SurfaceHolder;
25 |
26 | public class LiveWallpaper extends WallpaperService {
27 |
28 | @Override
29 | public void onCreate() {
30 | super.onCreate();
31 |
32 | this.getCacheDir().mkdirs();
33 |
34 | startService(new Intent(LiveWallpaper.this, UpdateService.class));
35 | }
36 |
37 | @Override
38 | public void onDestroy() {
39 | super.onDestroy();
40 |
41 | stopService(new Intent(LiveWallpaper.this, UpdateService.class));
42 | }
43 |
44 | @Override
45 | public Engine onCreateEngine() {
46 | return new BeautyClockEngine();
47 | }
48 |
49 | class BeautyClockEngine extends Engine implements SharedPreferences.OnSharedPreferenceChangeListener {
50 |
51 | private static final String TAG = "LiveWallpaper";
52 | private static final int STATUS_BAR_HEIGHT = 38;
53 |
54 | private Time mTime = new Time();
55 | private int mHour = 0;
56 | private int mMinute = 0;
57 |
58 | // preferences
59 | private boolean mFitScreen = false;
60 | private String mStorePath = null;
61 | private boolean mBellHourly = false;
62 | private boolean mNoScroll = false;
63 |
64 | private boolean mRegTimeBR = false;
65 | private boolean mRegScreenBR = false;
66 | private boolean mRegUpdateBR = false;
67 | private boolean mIsEngineVisible = false;
68 | private boolean bIsLarge = false;
69 |
70 | private int mScreenHeight = 0;
71 | private int mScreenWidth = 0;
72 | private int nXOffset = 0;
73 | private SharedPreferences mPrefs;
74 |
75 | private Bitmap mBeautyBitmap = null;
76 |
77 | private PlayBellTask mPlayBellTask = null;
78 |
79 | private boolean bUpdateStarted = false;
80 | private int mFailedCount = 0;
81 |
82 | private final BroadcastReceiver mWallpaperUpdateBroadcastReceiver = new BroadcastReceiver() {
83 |
84 | @Override
85 | public void onReceive(Context context, Intent intent) {
86 | Log.w(TAG, "mWallpaperUpdateBroadcastReceiver:onReceive");
87 | bUpdateStarted = true;
88 | updateBeautyBitmap();
89 | draw();
90 | }
91 | };
92 |
93 | private final BroadcastReceiver mScreenBroadcastReceiver = new BroadcastReceiver() {
94 | @Override
95 | public void onReceive(Context context, Intent intent) {
96 | Log.w(TAG, "mScreenBroadcastReceiver:onReceive");
97 | if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
98 | // Log.v(TAG, "Intent.ACTION_SCREEN_ON");
99 | if (mIsEngineVisible) {
100 | registerTimeBroadcastReceiver();
101 | registerWallpaperUpdateBroadcastReceiver();
102 | updateBeautyBitmap();
103 | draw();
104 | }
105 | } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
106 | // Log.v(TAG, "Intent.ACTION_SCREEN_OFF");
107 | unregisterWallpaperUpdateBroadcastReceiver();
108 | unregisterTimeBroadcastReceiver();
109 | }
110 | }
111 | };
112 |
113 | private final BroadcastReceiver mTimeBroadcastReceiver = new BroadcastReceiver() {
114 | @Override
115 | public void onReceive(Context context, Intent intent) {
116 | Log.i(TAG, "mTimeBroadcastReceiver:onReceive");
117 | if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
118 | String tz = intent.getStringExtra("time-zone");
119 | mTime = new Time(TimeZone.getTimeZone(tz).getID());
120 |
121 | startUpdateService();
122 | } else if (intent.getAction().equals(Intent.ACTION_TIME_CHANGED)) {
123 | startUpdateService();
124 | } else {
125 | updateTime();
126 |
127 | if (mMinute == 0 && mBellHourly) {
128 | cancelPlayBellTask();
129 | startToPlayBell(mHour);
130 | }
131 |
132 | if (!bUpdateStarted) {
133 | mFailedCount++;
134 | if (mFailedCount == 3) {
135 | bUpdateStarted = true;
136 | }
137 | }
138 |
139 | updateBeautyBitmap();
140 | draw();
141 | }
142 | }
143 | };
144 |
145 | private void registerWallpaperUpdateBroadcastReceiver() {
146 | if (!mRegUpdateBR) {
147 | IntentFilter filter = new IntentFilter();
148 | filter.addAction(UpdateService.BROADCAST_WALLPAPER_UPDATE);
149 | registerReceiver(mWallpaperUpdateBroadcastReceiver, filter);
150 | mRegUpdateBR = true;
151 | }
152 | }
153 |
154 | private void unregisterWallpaperUpdateBroadcastReceiver() {
155 | if (mRegUpdateBR) {
156 | unregisterReceiver(mWallpaperUpdateBroadcastReceiver);
157 | mRegUpdateBR = false;
158 | }
159 | }
160 |
161 | private void registerScreenBroadcastReceiver() {
162 | if (!mRegScreenBR) {
163 | IntentFilter filter = new IntentFilter();
164 | filter.addAction(Intent.ACTION_SCREEN_ON);
165 | filter.addAction(Intent.ACTION_SCREEN_OFF);
166 | registerReceiver(mScreenBroadcastReceiver, filter);
167 | mRegScreenBR = true;
168 | }
169 | }
170 |
171 | private void unregisterScreenBroadcastReceiver() {
172 | if (mRegScreenBR) {
173 | unregisterReceiver(mScreenBroadcastReceiver);
174 | mRegScreenBR = false;
175 | }
176 | }
177 |
178 | private void registerTimeBroadcastReceiver() {
179 | if (!mRegTimeBR) {
180 | IntentFilter filter = new IntentFilter();
181 | filter.addAction(Intent.ACTION_TIME_TICK);
182 | filter.addAction(Intent.ACTION_TIME_CHANGED);
183 | filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
184 | registerReceiver(mTimeBroadcastReceiver, filter);
185 | mRegTimeBR = true;
186 | }
187 | }
188 |
189 | private void unregisterTimeBroadcastReceiver() {
190 | if (mRegTimeBR) {
191 | unregisterReceiver(mTimeBroadcastReceiver);
192 | mRegTimeBR = false;
193 | }
194 | }
195 |
196 | private void cancelPlayBellTask() {
197 | if (mPlayBellTask != null &&
198 | mPlayBellTask.getStatus() == AsyncTask.Status.RUNNING) {
199 | mPlayBellTask.cancel(true);
200 | }
201 | }
202 |
203 | private void startToPlayBell(int hour) {
204 | try {
205 | mPlayBellTask = new PlayBellTask(LiveWallpaper.this);
206 | mPlayBellTask.execute(hour);
207 | } catch(RejectedExecutionException e) {
208 | e.printStackTrace();
209 | }
210 | }
211 |
212 | BeautyClockEngine() {
213 | mScreenHeight = getResources().getDisplayMetrics().heightPixels;
214 | mScreenWidth = getResources().getDisplayMetrics().widthPixels;
215 |
216 | mPrefs = getSharedPreferences(Settings.SHARED_PREFS_NAME, 0);
217 | mPrefs.registerOnSharedPreferenceChangeListener(this);
218 | onSharedPreferenceChanged(mPrefs, null);
219 | }
220 |
221 | private void startUpdateService() {
222 | Intent intent = new Intent(LiveWallpaper.this, UpdateService.class);
223 | startService(intent);
224 | }
225 |
226 | private void startUpdateServiceWithTime() {
227 | if (bUpdateStarted) {
228 | Intent intent = new Intent(LiveWallpaper.this, UpdateService.class);
229 | intent.putExtra("fetch_pictures", true);
230 | intent.putExtra("hour", mHour);
231 | intent.putExtra("minute", mMinute);
232 | startService(intent);
233 | }
234 | }
235 |
236 | private void updateTime() {
237 | mTime.setToNow();
238 | mHour = mTime.hour;
239 | mMinute = mTime.minute;
240 | }
241 |
242 | private void updateBeautyBitmap() {
243 | updateTime();
244 |
245 | // check SD card first
246 | String fname = String.format("%s/%02d%02d.jpg", mStorePath, mHour, mMinute);
247 | File _f_sdcard = new File(fname);
248 | Log.d(TAG, "check SD:" + fname);
249 | if (!_f_sdcard.exists()) {
250 | fname = String.format("%s/%02d%02d.jpg", getCacheDir().getAbsolutePath(), mHour, mMinute);
251 | Log.d(TAG, "check cache:" + fname);
252 |
253 | File _f_cache = new File(fname);
254 | if (!_f_cache.exists()) {
255 | startUpdateServiceWithTime();
256 | return;
257 | }
258 | }
259 |
260 | Bitmap bitmap = BitmapFactory.decodeFile(fname);
261 | if (bitmap != null) {
262 | if (mBeautyBitmap != null) {
263 | mBeautyBitmap.recycle();
264 | }
265 | mBeautyBitmap = ResizeBitmap(bitmap);
266 | }
267 | }
268 |
269 | private Bitmap ResizeBitmap(Bitmap bitmap) {
270 | if (bitmap == null) {
271 | return null;
272 | }
273 |
274 | int width = bitmap.getWidth();
275 | int height = bitmap.getHeight();
276 | if (width == 0 || height == 0) {
277 | return null;
278 | }
279 |
280 | if (mScreenWidth > mScreenHeight) {
281 | double ratio = (float) (mScreenHeight - STATUS_BAR_HEIGHT) / height;
282 | width = (int) (width * ratio);
283 | height = mScreenHeight - STATUS_BAR_HEIGHT;
284 | } else {
285 | if (height > width) {
286 | if (mFitScreen) {
287 | height = mScreenHeight - STATUS_BAR_HEIGHT;
288 | } else {
289 | double ratio = (float) mScreenWidth / width;
290 | height = (int) (height * ratio);
291 | }
292 | width = mScreenWidth;
293 | /*
294 | double ratio = (float) (mScreenHeight - 60) / height;
295 | height = mScreenHeight - 60;
296 | width = (int) (width * ratio);
297 | */
298 | } else {
299 | if (mFitScreen) {
300 | height = mScreenHeight - STATUS_BAR_HEIGHT;
301 | } else {
302 | double ratio = (float) mScreenWidth*2 / width;
303 | height = (int) (height * ratio);
304 | }
305 | width = mScreenWidth*2;
306 | }
307 | }
308 |
309 | if (isPreview()) {
310 | height = mScreenHeight - STATUS_BAR_HEIGHT * 3;
311 | }
312 |
313 | // Log.w(TAG, "bitmap:"+ bitmap.getWidth() + "x" + bitmap.getHeight() + ":"+ bitmap.getDensity());
314 | // Log.w(TAG, "bitmap:"+ bitmap.getWidth()*bitmap.getHeight());
315 | Bitmap bitmapNew = Bitmap.createScaledBitmap(bitmap, width, height, true);
316 | // Log.w(TAG,"scaled !!!!!!!!!!");
317 | // Log.w(TAG,"bitmap:"+ bitmap.getWidth() + "x" + bitmap.getHeight() + ":"+ bitmap.getDensity());
318 | // Log.w(TAG,"bitmap:"+ bitmap.getWidth()*bitmap.getHeight());
319 | return bitmapNew;
320 | }
321 |
322 | private void drawBeautyClock(Canvas c, Bitmap bitmap_src) {
323 | if (c == null || bitmap_src == null) {
324 | return;
325 | }
326 |
327 | Bitmap bitmap_resized = bitmap_src; //ResizeBitmap(bitmap_src);
328 | int width = bitmap_resized.getWidth();
329 | int height = bitmap_resized.getHeight();
330 | int Xpos = 0, Ypos = STATUS_BAR_HEIGHT;
331 |
332 | // picture across virtual desktop, set scrolling
333 | if (width > height) {
334 | Xpos = nXOffset;
335 | bIsLarge = true;
336 | } else {
337 | bIsLarge = false;
338 | }
339 |
340 | if (isPreview() || mNoScroll) {
341 | Xpos = -(width - mScreenWidth) / 2;
342 | Ypos = STATUS_BAR_HEIGHT;
343 | } else {
344 | if (mScreenWidth > mScreenHeight) {
345 | int offset = (int) (mScreenWidth * (bIsLarge ? 1.2 : 1) - width) / 2;
346 | if (offset > 0) {
347 | Xpos += offset;
348 | }
349 | } else {
350 | if (!mFitScreen) {
351 | int offset = (mScreenHeight - STATUS_BAR_HEIGHT - height) / 2;
352 | if (offset > 0) {
353 | Ypos += offset;
354 | }
355 | }
356 | }
357 | }
358 |
359 | // clean before drawing
360 | c.drawColor(Color.BLACK);
361 | c.drawBitmap(bitmap_resized, Xpos, Ypos, null);
362 | }
363 |
364 | private void drawErrorScreen(Canvas c) {
365 | updateTime();
366 |
367 | // setup paint for drawing digitl clock
368 | Paint paint = new Paint();
369 | paint.setColor(Color.YELLOW);
370 | paint.setAntiAlias(true);
371 | paint.setStrokeCap(Paint.Cap.ROUND);
372 | paint.setStyle(Paint.Style.STROKE);
373 | paint.setStrokeWidth(5);
374 | paint.setTextSize(120);
375 |
376 | String time = String.format("%02d:%02d", mHour, mMinute);
377 | c.drawColor(Color.BLACK);
378 | c.drawText(time, mScreenWidth/2-150, mScreenHeight/2-30, paint);
379 |
380 | /*
381 | Paint paint = new Paint();
382 | paint.setColor(Color.BLACK);
383 | paint.setAntiAlias(true);
384 | paint.setStrokeCap(Paint.Cap.ROUND);
385 | paint.setStyle(Paint.Style.STROKE);
386 | paint.setStrokeWidth(5);
387 | paint.setTextSize(120);
388 |
389 | if (mErrorBitmap == null) {
390 | Drawable dw = getResources().getDrawable(R.drawable.beautyclock_retry);
391 | mErrorBitmap = ResizeBitmap(((BitmapDrawable)dw).getBitmap());
392 | }
393 | c.drawBitmap(mErrorBitmap, 0, 15, paint);
394 | String time = String.format("%02d:%02d", mHour, mMinute);
395 | /c.drawText(time, mScreenWidth/2-150, 140, paint);
396 | */
397 | }
398 |
399 | private void draw() {
400 | final SurfaceHolder holder = getSurfaceHolder();
401 | Canvas c = null;
402 | try {
403 | c = holder.lockCanvas();
404 | if (c != null) {
405 | if (mBeautyBitmap != null) {
406 | drawBeautyClock(c, mBeautyBitmap);
407 | } else {
408 | drawErrorScreen(c);
409 | }
410 | }
411 | } finally {
412 | if (c != null) {
413 | holder.unlockCanvasAndPost(c);
414 | }
415 | }
416 | }
417 |
418 | /*
419 | @Override
420 | public void onSurfaceCreated(SurfaceHolder holder) {
421 | Log.d(TAG, "onSurfaceCreated");
422 | super.onSurfaceCreated(holder);
423 | }
424 |
425 | @Override
426 | public int getDesiredMinimumHeight() {
427 | Log.d(TAG, "getDesiredMinimumHeight");
428 | return super.getDesiredMinimumHeight();
429 | }
430 |
431 | @Override
432 | public int getDesiredMinimumWidth() {
433 | Log.d(TAG, "getDesiredMinimumWidth");
434 | return super.getDesiredMinimumWidth();
435 | }
436 |
437 | @Override
438 | public SurfaceHolder getSurfaceHolder() {
439 | Log.d(TAG, "getSurfaceHolder");
440 | return super.getSurfaceHolder();
441 | }
442 |
443 | @Override
444 | public boolean isPreview() {
445 | Log.d(TAG, "isPreview");
446 | return super.isPreview();
447 | }
448 |
449 | @Override
450 | public boolean isVisible() {
451 | Log.d(TAG, "isVisible");
452 | return super.isVisible();
453 | }
454 |
455 | @Override
456 | public Bundle onCommand(String action, int x, int y, int z,
457 | Bundle extras, boolean resultRequested) {
458 | Log.d(TAG, "onCommand");
459 | return super.onCommand(action, x, y, z, extras, resultRequested);
460 | }
461 |
462 | @Override
463 | public void onTouchEvent(MotionEvent event) {
464 | Log.d(TAG, "onTouchEvent");
465 | super.onTouchEvent(event);
466 | }
467 |
468 | @Override
469 | public void setTouchEventsEnabled(boolean enabled) {
470 | Log.d(TAG, "setTouchEventsEnabled:" + enabled);
471 | super.setTouchEventsEnabled(enabled);
472 | }
473 |
474 |
475 | @Override
476 | public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) {
477 | Log.d(TAG, "onDesiredSizeChanged");
478 | super.onDesiredSizeChanged(desiredWidth, desiredHeight);
479 | }
480 |
481 | @Override
482 | public void onSurfaceDestroyed(SurfaceHolder holder) {
483 | Log.d(TAG, "onSurfaceDestroyed");
484 | super.onSurfaceDestroyed(holder);
485 | }
486 | */
487 | @Override
488 | public void onCreate(SurfaceHolder surfaceHolder) {
489 | // Log.d(TAG, "onCreate (engine)");
490 | super.onCreate(surfaceHolder);
491 |
492 | // setTouchEventsEnabled(false);
493 |
494 | // register notification
495 | registerTimeBroadcastReceiver();
496 | registerWallpaperUpdateBroadcastReceiver();
497 | registerScreenBroadcastReceiver();
498 | }
499 |
500 | @Override
501 | public void onDestroy() {
502 | // Log.d(TAG, "onDestroy (engine)");
503 | super.onDestroy();
504 |
505 | cancelPlayBellTask();
506 |
507 | unregisterTimeBroadcastReceiver();
508 | unregisterWallpaperUpdateBroadcastReceiver();
509 | unregisterScreenBroadcastReceiver();
510 | }
511 |
512 | @Override
513 | public void onOffsetsChanged(float xOffset, float yOffset,
514 | float xOffsetStep, float yOffsetStep, int xPixelOffset,
515 | int yPixelOffset) {
516 | // Log.d(TAG, "onOffsetsChanged");
517 | // Log.d(TAG, "x:" + xPixelOffset + ", y:" + yPixelOffset);
518 | nXOffset = xPixelOffset;
519 | if (bIsLarge) {
520 | draw();
521 | }
522 | }
523 |
524 | @Override
525 | public void onSurfaceChanged(SurfaceHolder holder, int format,
526 | int width, int height) {
527 | // Log.d(TAG, "onSurfaceChanged:" + width + "," + height);
528 |
529 | mScreenHeight = height;
530 | mScreenWidth = width;
531 | updateBeautyBitmap();
532 | draw();
533 | }
534 |
535 | @Override
536 | public void onVisibilityChanged(boolean visible) {
537 | Log.d(TAG, "onVisibilityChanged:" + visible);
538 | if (visible) {
539 | updateBeautyBitmap();
540 | draw();
541 | mIsEngineVisible = true;
542 | registerWallpaperUpdateBroadcastReceiver();
543 | } else {
544 | mIsEngineVisible = false;
545 | unregisterWallpaperUpdateBroadcastReceiver();
546 | }
547 | }
548 |
549 | public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
550 | if (prefs == null) {
551 | return;
552 | }
553 |
554 | if (key == null) {
555 | mFitScreen = prefs.getBoolean(Settings.PREF_FIT_SCREEN, false);
556 | mStorePath = prefs.getString(Settings.PREF_INTERNAL_PICTURE_PATH, "");
557 | mBellHourly = prefs.getBoolean(Settings.PREF_RING_HOURLY, false);
558 | mNoScroll = prefs.getBoolean(Settings.PREF_NO_SCROLL, false);
559 |
560 | return;
561 | }
562 |
563 | if (key.equals(Settings.PREF_FIT_SCREEN)) {
564 | mFitScreen = prefs.getBoolean(Settings.PREF_FIT_SCREEN, false);
565 | updateBeautyBitmap();
566 | draw();
567 | } else if (key.equals(Settings.PREF_INTERNAL_PICTURE_PATH)) {
568 | mStorePath = prefs.getString(Settings.PREF_INTERNAL_PICTURE_PATH, "");
569 | } else if (key.equals(Settings.PREF_RING_HOURLY)) {
570 | mBellHourly = prefs.getBoolean(Settings.PREF_RING_HOURLY, false);
571 | } else if (key.equals(Settings.PREF_SAVE_COPY) ||
572 | key.equals(Settings.PREF_FETCH_LARGER_PICTURE) ||
573 | key.equals(Settings.PREF_PICTURE_SOURCE) ||
574 | key.equals(Settings.PREF_PICTURE_PER_FETCH)) {
575 | startUpdateService();
576 | } else if (key.equals(Settings.PREF_NO_SCROLL)) {
577 | mNoScroll = prefs.getBoolean(Settings.PREF_NO_SCROLL, false);
578 | draw();
579 | }
580 | }
581 | }
582 | }
583 |
--------------------------------------------------------------------------------
/src/com/corner23/android/beautyclocklivewallpaper/asynctasks/FetchBeautyPictureTask.java:
--------------------------------------------------------------------------------
1 | package com.corner23.android.beautyclocklivewallpaper.asynctasks;
2 |
3 | import java.io.BufferedInputStream;
4 | import java.io.BufferedOutputStream;
5 | import java.io.ByteArrayOutputStream;
6 | import java.io.Closeable;
7 | import java.io.File;
8 | import java.io.FileNotFoundException;
9 | import java.io.FileOutputStream;
10 | import java.io.IOException;
11 | import java.io.InputStream;
12 | import java.io.OutputStream;
13 | import java.net.InetSocketAddress;
14 | import java.net.Proxy;
15 | import java.net.SocketAddress;
16 | import java.net.SocketTimeoutException;
17 | import java.net.URL;
18 | import java.net.URLConnection;
19 |
20 | import com.corner23.android.beautyclocklivewallpaper.Settings;
21 | import com.corner23.android.beautyclocklivewallpaper.services.UpdateService;
22 |
23 | import android.content.Context;
24 | import android.content.Intent;
25 | import android.content.SharedPreferences.Editor;
26 | import android.net.ConnectivityManager;
27 | import android.net.NetworkInfo;
28 | import android.os.AsyncTask;
29 | import android.os.Environment;
30 | import android.util.Log;
31 |
32 | public class FetchBeautyPictureTask extends AsyncTask {
33 |
34 | private static final int IO_BUFFER_SIZE = 4096;
35 |
36 | private static final int BCLW_FETCH_STATE_OTHER_FAILED = -1;
37 | private static final int BCLW_FETCH_STATE_SUCCESS = 0;
38 | private static final int BCLW_FETCH_STATE_FILE_NOT_FOUND = 1;
39 | private static final int BCLW_FETCH_STATE_TIMEOUT = 2;
40 | private static final int BCLW_FETCH_STATE_IO_ERROR = 3;
41 |
42 | private static final String TAG = "FetchBeautyPictureTask";
43 |
44 | private static final String ARTHUR_PICTURE_URL = "http://www.arthur.com.tw/photo/images/400/%02d%02d.JPG";
45 | private static final String CLOCKM_PICTURE_URL = "http://www.clockm.com/tw/img/clk/hour/%02d%02d.jpg";
46 | private static final String BIJIN_PICTURE_URL_L = "http://www.bijint.com/assets/pict/bijin/590x450/%02d%02d.jpg";
47 | private static final String BIJIN_PICTURE_URL = "http://www.bijint.com/assets/pict/bijin/240x320/%02d%02d.jpg";
48 | private static final String BIJIN_KOREA_PICTURE_URL_L = "http://www.bijint.com/assets/pict/kr/590x450/%02d%02d.jpg";
49 | private static final String BIJIN_KOREA_PICTURE_URL = "http://www.bijint.com/assets/pict/kr/240x320/%02d%02d.jpg";
50 | private static final String BIJIN_GAL_PICTURE_URL_L = "http://gal.bijint.com/assets/pict/gal/590x450/%02d%02d.jpg";
51 | private static final String BIJIN_GAL_PICTURE_URL = "http://gal.bijint.com/assets/pict/gal/240x320/%02d%02d.jpg";
52 | private static final String BIJIN_CC_PICTURE_URL = "http://www.bijint.com/assets/pict/cc/590x450/%02d%02d.jpg";
53 | private static final String BINAN_PICTURE_URL_L = "http://www.bijint.com/assets/pict/binan/590x450/%02d%02d.jpg";
54 | private static final String BINAN_PICTURE_URL = "http://www.bijint.com/assets/pict/binan/240x320/%02d%02d.jpg";
55 | private static final String BIJIN_HK_PICTURE_URL_L = "http://www.bijint.com/assets/pict/hk/590x450/%02d%02d.jpg";
56 | private static final String BIJIN_HK_PICTURE_URL = "http://www.bijint.com/assets/pict/hk/240x320/%02d%02d.jpg";
57 |
58 | private static final String BIJIN_NIIGATA_PICTURE_URL = "http://www.bijint.com/niigata/tokei_images/%02d%02d.jpg";
59 | private static final String BIJIN_KAGOSHIMA_PICTURE_URL = "http://www.bijint.com/kagoshima/tokei_images/%02d%02d.jpg";
60 | private static final String BIJIN_NAGOYA_PICTURE_URL = "http://www.bijint.com/nagoya/tokei_images/%02d%02d.jpg";
61 | private static final String BIJIN_KAGAWA_PICTURE_URL = "http://www.bijint.com/kagawa/tokei_images/%02d%02d.jpg";
62 | private static final String BIJIN_OKAYMA_PICTURE_URL = "http://www.bijint.com/okayama/tokei_images/%02d%02d.jpg";
63 | private static final String BIJIN_FUKUOKA_PICTURE_URL = "http://www.bijint.com/fukuoka/tokei_images/%02d%02d.jpg";
64 | private static final String BIJIN_KANAZAWA_PICTURE_URL = "http://www.bijint.com/kanazawa/tokei_images/%02d%02d.jpg";
65 | private static final String BIJIN_KYOTO_PICTURE_URL = "http://www.bijint.com/kyoto/tokei_images/%02d%02d.jpg";
66 | private static final String BIJIN_SENDAI_PICTURE_URL = "http://www.bijint.com/sendai/tokei_images/%02d%02d.jpg";
67 | private static final String BIJIN_HOKKAIDO_PICTURE_URL = "http://www.bijint.com/hokkaido/tokei_images/%02d%02d.jpg";
68 | private static final String BIJIN_WASEDASTYLE_PICTURE_URL = "http://www.bijint.com/wasedastyle/tokei_images/%02d%02d.jpg";
69 |
70 | private static final String LOVELY_TIME_PICTURE_URL = "http://gameflier.lovelytime.com.tw/photo/%02d%02d.JPG";
71 | private static final String WRETCH_PICTURE_URL = "http://tw.yimg.com/i/tw/wretch/beautyclockweb/%02d%02d.jpg";
72 | private static final String WRETCH_PICTURE_URL_L = "http://l.yimg.com/f/i/tw/wretch/beautyclock/%02d%02d.jpg";
73 | private static final String AVTOKEI_PICTURE_URL = "http://www.avtokei.jp/images/clocks/%02d/%02d%02d.jpg";
74 |
75 | private static final String SDCARD_BASE_PATH = Environment.getExternalStorageDirectory().getPath() + "/BeautyClock/pic/%s/%02d%02d.jpg";
76 | private static final String ARTHUR_PICTURE = "arthur";
77 | private static final String CLOCKM_PICTURE = "clockm";
78 | private static final String BIJIN_PICTURE = "bijin";
79 | private static final String BIJIN_PICTURE_L = "bijin_l";
80 | private static final String BIJIN_KOREA_PICTURE = "bijin-kr";
81 | private static final String BIJIN_KOREA_PICTURE_L = "bijin-kr_l";
82 | private static final String BIJIN_GAL_PICTURE = "bijin-gal";
83 | private static final String BIJIN_GAL_PICTURE_L = "bijin-gal_l";
84 | private static final String BIJIN_CC_PICTURE = "bijin-cc";
85 | private static final String BINAN_PICTURE = "binan";
86 | private static final String BINAN_PICTURE_L = "binan_l";
87 | private static final String BIJIN_HK_PICTURE = "bijin-hk";
88 | private static final String BIJIN_HK_PICTURE_L = "bijin-hk_l";
89 |
90 | private static final String BIJIN_NIIGATA_PICTURE = "niigata";
91 | private static final String BIJIN_KAGOSHIMA_PICTURE = "kagoshima";
92 | private static final String BIJIN_NAGOYA_PICTURE = "nagoya";
93 | private static final String BIJIN_KAGAWA_PICTURE = "kagawa";
94 | private static final String BIJIN_OKAYMA_PICTURE = "okayama";
95 | private static final String BIJIN_FUKUOKA_PICTURE = "fukuoka";
96 | private static final String BIJIN_KANAZAWA_PICTURE = "kanazawa";
97 | private static final String BIJIN_KYOTO_PICTURE = "kyoto";
98 | private static final String BIJIN_SENDAI_PICTURE = "sendai";
99 | private static final String BIJIN_HOKKAIDO_PICTURE = "hokkaido";
100 | private static final String BIJIN_WASEDASTYLE_PICTURE = "wasedastyle";
101 |
102 | private static final String LOVELY_TIME_PICTURE = "lovely";
103 | private static final String WRETCH_PICTURE = "wretch";
104 | private static final String WRETCH_PICTURE_L = "wretch_l";
105 | private static final String AVTOKEI_PICTURE = "av";
106 | private static final String CUSTOM_PICTURE = "custom";
107 |
108 | private static final String CACHE_FILE_PATH = "%02d%02d.jpg";
109 |
110 | private int mHour, mMinute;
111 | private int mPictureSource;
112 | private boolean mFetchLargerPicture;
113 | private boolean mSaveCopy;
114 | private Context mContext = null;
115 | private ConnectivityManager cm = null;
116 | private boolean bCancel = false;
117 |
118 | public void saveSourcePath() {
119 | String path = (new File(getPATH())).getParent();
120 |
121 | Editor editor = mContext.getSharedPreferences(Settings.SHARED_PREFS_NAME, 0).edit();
122 | editor.putString(Settings.PREF_INTERNAL_PICTURE_PATH, path);
123 | editor.commit();
124 |
125 | Log.d(TAG, "saving path .." + path);
126 | }
127 |
128 | public FetchBeautyPictureTask(Context context, ConnectivityManager connmgr, int source, boolean getlarge, boolean savecopy) {
129 | mContext = context;
130 | cm = connmgr;
131 | mPictureSource = source;
132 | mFetchLargerPicture = getlarge;
133 | mSaveCopy = savecopy;
134 | }
135 |
136 | private String getPATH() {
137 | String URLstr = null;
138 | switch (mPictureSource) {
139 | default:
140 | case 0: URLstr = String.format(SDCARD_BASE_PATH, ARTHUR_PICTURE, mHour, mMinute); break;
141 | case 1: URLstr = String.format(SDCARD_BASE_PATH, CLOCKM_PICTURE, mHour, mMinute); break;
142 | case 2: URLstr = String.format(SDCARD_BASE_PATH, mFetchLargerPicture ? BIJIN_PICTURE_L : BIJIN_PICTURE, mHour, mMinute); break;
143 | case 3: URLstr = String.format(SDCARD_BASE_PATH, mFetchLargerPicture ? BIJIN_KOREA_PICTURE_L : BIJIN_KOREA_PICTURE, mHour, mMinute); break;
144 | case 4: URLstr = String.format(SDCARD_BASE_PATH, mFetchLargerPicture ? BIJIN_HK_PICTURE_L : BIJIN_HK_PICTURE, mHour, mMinute); break;
145 | case 5: URLstr = String.format(SDCARD_BASE_PATH, BIJIN_NIIGATA_PICTURE, mHour, mMinute); break;
146 | case 6: URLstr = String.format(SDCARD_BASE_PATH, BIJIN_KAGOSHIMA_PICTURE, mHour, mMinute); break;
147 | case 7: URLstr = String.format(SDCARD_BASE_PATH, BIJIN_NAGOYA_PICTURE, mHour, mMinute); break;
148 | case 8: URLstr = String.format(SDCARD_BASE_PATH, BIJIN_KAGAWA_PICTURE, mHour, mMinute); break;
149 | case 9: URLstr = String.format(SDCARD_BASE_PATH, BIJIN_OKAYMA_PICTURE, mHour, mMinute); break;
150 | case 10: URLstr = String.format(SDCARD_BASE_PATH, BIJIN_FUKUOKA_PICTURE, mHour, mMinute); break;
151 | case 11: URLstr = String.format(SDCARD_BASE_PATH, BIJIN_KANAZAWA_PICTURE, mHour, mMinute); break;
152 | case 12: URLstr = String.format(SDCARD_BASE_PATH, BIJIN_KYOTO_PICTURE, mHour, mMinute); break;
153 | case 13: URLstr = String.format(SDCARD_BASE_PATH, BIJIN_SENDAI_PICTURE, mHour, mMinute); break;
154 | case 14: URLstr = String.format(SDCARD_BASE_PATH, BIJIN_HOKKAIDO_PICTURE, mHour, mMinute); break;
155 | case 15: URLstr = String.format(SDCARD_BASE_PATH, BIJIN_WASEDASTYLE_PICTURE, mHour, mMinute); break;
156 | case 16: URLstr = String.format(SDCARD_BASE_PATH, mFetchLargerPicture ? BIJIN_GAL_PICTURE_L : BIJIN_GAL_PICTURE, mHour, mMinute); break;
157 | case 17: URLstr = String.format(SDCARD_BASE_PATH, BIJIN_CC_PICTURE, mHour, mMinute); break;
158 | case 18: URLstr = String.format(SDCARD_BASE_PATH, mFetchLargerPicture ? BINAN_PICTURE_L : BINAN_PICTURE, mHour, mMinute); break;
159 | case 19: URLstr = String.format(SDCARD_BASE_PATH, LOVELY_TIME_PICTURE, mHour, mMinute); break;
160 | case 20: URLstr = String.format(SDCARD_BASE_PATH, mFetchLargerPicture ? WRETCH_PICTURE_L : WRETCH_PICTURE, mHour, mMinute); break;
161 | case 98: URLstr = String.format(SDCARD_BASE_PATH, CUSTOM_PICTURE, mHour, mMinute); break;
162 | case 99: URLstr = String.format(SDCARD_BASE_PATH, AVTOKEI_PICTURE, mHour, mMinute); break;
163 | }
164 |
165 | return URLstr;
166 | }
167 |
168 | private String getURL() {
169 | String URLstr = null;
170 | switch (mPictureSource) {
171 | default:
172 | case 0: URLstr = String.format(ARTHUR_PICTURE_URL, mHour, mMinute); break;
173 | case 1: URLstr = String.format(CLOCKM_PICTURE_URL, mHour, mMinute); break;
174 | case 2: URLstr = String.format(mFetchLargerPicture ? BIJIN_PICTURE_URL_L : BIJIN_PICTURE_URL, mHour, mMinute); break;
175 | case 3: URLstr = String.format(mFetchLargerPicture ? BIJIN_KOREA_PICTURE_URL_L : BIJIN_KOREA_PICTURE_URL, mHour, mMinute); break;
176 | case 4: URLstr = String.format(mFetchLargerPicture ? BIJIN_HK_PICTURE_URL_L : BIJIN_HK_PICTURE_URL, mHour, mMinute); break;
177 | case 5: URLstr = String.format(BIJIN_NIIGATA_PICTURE_URL, mHour, mMinute); break;
178 | case 6: URLstr = String.format(BIJIN_KAGOSHIMA_PICTURE_URL, mHour, mMinute); break;
179 | case 7: URLstr = String.format(BIJIN_NAGOYA_PICTURE_URL, mHour, mMinute); break;
180 | case 8: URLstr = String.format(BIJIN_KAGAWA_PICTURE_URL, mHour, mMinute); break;
181 | case 9: URLstr = String.format(BIJIN_OKAYMA_PICTURE_URL, mHour, mMinute); break;
182 | case 10: URLstr = String.format(BIJIN_FUKUOKA_PICTURE_URL, mHour, mMinute); break;
183 | case 11: URLstr = String.format(BIJIN_KANAZAWA_PICTURE_URL, mHour, mMinute); break;
184 | case 12: URLstr = String.format(BIJIN_KYOTO_PICTURE_URL, mHour, mMinute); break;
185 | case 13: URLstr = String.format(BIJIN_SENDAI_PICTURE_URL, mHour, mMinute); break;
186 | case 14: URLstr = String.format(BIJIN_HOKKAIDO_PICTURE_URL, mHour, mMinute); break;
187 | case 15: URLstr = String.format(BIJIN_WASEDASTYLE_PICTURE_URL, mHour, mMinute); break;
188 | case 16: URLstr = String.format(mFetchLargerPicture ? BIJIN_GAL_PICTURE_URL_L : BIJIN_GAL_PICTURE_URL, mHour, mMinute); break;
189 | case 17: URLstr = String.format(BIJIN_CC_PICTURE_URL, mHour, mMinute); break;
190 | case 18: URLstr = String.format(mFetchLargerPicture ? BINAN_PICTURE_URL_L : BINAN_PICTURE_URL, mHour, mMinute); break;
191 | case 19: URLstr = String.format(LOVELY_TIME_PICTURE_URL, mHour, mMinute); break;
192 | case 20: URLstr = String.format(mFetchLargerPicture ? WRETCH_PICTURE_URL_L : WRETCH_PICTURE_URL, mHour, mMinute); break;
193 | case 99: URLstr = String.format(AVTOKEI_PICTURE_URL, mHour, mHour, mMinute); break;
194 | }
195 |
196 | return URLstr;
197 | }
198 |
199 | private String getReferer() {
200 | String referer = null;
201 | switch (mPictureSource) {
202 | case 2: referer = "http://www.bijint.com/jp/"; break;
203 | case 3: referer = "http://www.bijint.com/kr/"; break;
204 | case 4: referer = "http://www.bijint.com/hk/"; break;
205 | case 5: referer = "http://www.bijint.com/niigata/"; break;
206 | case 6: referer = "http://www.bijint.com/kagoshima/"; break;
207 | case 7: referer = "http://www.bijint.com/nagoya/"; break;
208 | case 8: referer = "http://www.bijint.com/kagawa/"; break;
209 | case 9: referer = "http://www.bijint.com/okayama/"; break;
210 | case 10: referer = "http://www.bijint.com/fukuoka/"; break;
211 | case 11: referer = "http://www.bijint.com/kanazawa/"; break;
212 | case 12: referer = "http://www.bijint.com/kyoto/"; break;
213 | case 13: referer = "http://www.bijint.com/sendai/"; break;
214 | case 14: referer = "http://www.bijint.com/hokkaido/"; break;
215 | case 15: referer = "http://www.bijint.com/wasedastyle/"; break;
216 | case 16: referer = "http://gal.bijint.com/"; break;
217 | case 17: referer = "http://www.bijint.com/cc/"; break;
218 | case 18: referer = "http://www.bijint.com/binan/"; break;
219 | case 99: referer = "http://www.avtokei.jp/index.html"; break;
220 | }
221 |
222 | return referer;
223 | }
224 |
225 | private boolean saveBitmapToFile(byte[] bitmap, File new_file) {
226 | if (bitmap == null || new_file == null) {
227 | Log.e(TAG, "Null parameters in saveBitmapToFile");
228 | return false;
229 | }
230 |
231 | try {
232 | if (!new_file.getParentFile().exists()) {
233 | new_file.mkdirs();
234 | }
235 | FileOutputStream out = new FileOutputStream(new_file);
236 | out.write(bitmap, 0, bitmap.length);
237 | out.flush();
238 | out.close();
239 | } catch (Exception e) {
240 | Log.e(TAG, "Error saving bitmap to file: " + e.getMessage());
241 | return false;
242 | }
243 |
244 | return true;
245 | }
246 |
247 | private byte[] fetchBeautyPictureBitmapFromURL(URL url, String referer) throws IOException {
248 | byte[] bitmap = null;
249 | InputStream in = null;
250 | OutputStream out = null;
251 | URLConnection urlc = null;
252 | Proxy httpProxy = Proxy.NO_PROXY;
253 |
254 | try {
255 | if (cm != null) {
256 | // network is turned off by user
257 | if (!cm.getBackgroundDataSetting()) {
258 | Log.i(TAG, "background transfer disabled..");
259 | return null;
260 | }
261 |
262 | // network is not connected
263 | NetworkInfo ni = cm.getActiveNetworkInfo();
264 | if (ni != null && ni.getState() != NetworkInfo.State.CONNECTED) {
265 | Log.i(TAG, "network down");
266 | return null;
267 | }
268 |
269 | // if we're using WIFI, then there's no proxy from APN
270 | if (ni != null && ni.getType() == ConnectivityManager.TYPE_WIFI) {
271 | httpProxy = Proxy.NO_PROXY;
272 | } else {
273 | String httpProxyHost = android.net.Proxy.getDefaultHost();
274 | Integer httpProxyPort = android.net.Proxy.getDefaultPort();
275 | if (httpProxyHost != null && httpProxyPort != null) {
276 | SocketAddress proxyAddress = new InetSocketAddress(httpProxyHost, httpProxyPort);
277 | httpProxy = new Proxy(Proxy.Type.HTTP, proxyAddress);
278 | } else {
279 | httpProxy = Proxy.NO_PROXY;
280 | }
281 | }
282 | }
283 | } catch (Exception e) {
284 | Log.e(TAG, "Error setting network env: " + e.getMessage());
285 | }
286 |
287 | try {
288 | urlc = url.openConnection(httpProxy);
289 | urlc.setRequestProperty("User-Agent", "Mozilla/5.0");
290 | if (referer != null) {
291 | urlc.setRequestProperty("Referer", referer);
292 | }
293 | urlc.setReadTimeout(10000);
294 | urlc.setConnectTimeout(10000);
295 |
296 | in = new BufferedInputStream(urlc.getInputStream(), IO_BUFFER_SIZE);
297 |
298 | ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
299 | out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);
300 | copy(in, out);
301 | out.flush();
302 |
303 | bitmap = dataStream.toByteArray();
304 | // bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
305 | } finally {
306 | closeStream(in);
307 | closeStream(out);
308 | }
309 |
310 | return bitmap;
311 | }
312 |
313 | private int copy(InputStream in, OutputStream out) throws IOException, SocketTimeoutException {
314 | byte[] b = new byte[IO_BUFFER_SIZE];
315 | int read, size = 0;
316 | while ((read = in.read(b)) != -1) {
317 | out.write(b, 0, read);
318 | size += read;
319 | }
320 | return size;
321 | }
322 |
323 | private void closeStream(Closeable stream) {
324 | if (stream != null) {
325 | try {
326 | stream.close();
327 | } catch (IOException e) {
328 | e.printStackTrace();
329 | }
330 | }
331 | }
332 |
333 | @Override
334 | protected Integer doInBackground(Integer... params) {
335 | Log.i(TAG, "doInBackground:FetchBeautyPictureTask");
336 | int ret = BCLW_FETCH_STATE_OTHER_FAILED;
337 |
338 | mHour = params[0];
339 | mMinute = params[1];
340 |
341 | try {
342 | // check file in sd card first
343 | String _path_sdcard = getPATH();
344 | File _file_sdcard = new File(_path_sdcard);
345 | if (_file_sdcard.exists()) {
346 | Log.d(TAG, "File in SD card:" + _path_sdcard);
347 | return BCLW_FETCH_STATE_SUCCESS;
348 | }
349 |
350 | // check application cache data
351 | String _path_cache = String.format(CACHE_FILE_PATH, mHour, mMinute);
352 | File _file_cache = new File(mContext.getCacheDir(), _path_cache);
353 | if (_file_cache.exists()) {
354 | Log.d(TAG, "File in cache");
355 | return BCLW_FETCH_STATE_SUCCESS;
356 | }
357 |
358 | URL mURL = new URL(getURL());
359 | byte[] bitmap = fetchBeautyPictureBitmapFromURL(mURL, getReferer());
360 | if (bitmap != null) {
361 | Log.d(TAG, "saving..");
362 | Log.d(TAG, mURL.toString());
363 | if (mSaveCopy) {
364 | Log.d(TAG, "saving.. to sd");
365 | saveBitmapToFile(bitmap, _file_sdcard);
366 | } else {
367 | saveBitmapToFile(bitmap, _file_cache);
368 | _file_cache.setReadable(true, false);
369 | }
370 |
371 | ret = BCLW_FETCH_STATE_SUCCESS;
372 | }
373 | } catch (FileNotFoundException e) {
374 | e.printStackTrace();
375 | return BCLW_FETCH_STATE_FILE_NOT_FOUND;
376 | } catch (IOException e) {
377 | e.printStackTrace();
378 | ret = BCLW_FETCH_STATE_IO_ERROR;
379 | if (cm != null) {
380 | NetworkInfo ni = cm.getActiveNetworkInfo();
381 | if (ni != null && ni.isConnected()) {
382 | ret = BCLW_FETCH_STATE_TIMEOUT;
383 | }
384 | }
385 | }
386 | return ret;
387 | }
388 |
389 | protected void onPostExecute(Integer ret) {
390 | Log.i(TAG, "onPostExecute:FetchBeautyPictureTask");
391 | if (bCancel) {
392 | Log.i(TAG, "Canceled.. ");
393 | return;
394 | }
395 | Intent intent = new Intent(mContext, UpdateService.class);
396 | intent.putExtra("fetch_pictures_ret", true);
397 |
398 | if (ret == BCLW_FETCH_STATE_TIMEOUT) {
399 | Log.i(TAG, "timeout, startToFetchBeautyPicture again");
400 | intent.putExtra("timeout", true);
401 | } else if (ret == BCLW_FETCH_STATE_SUCCESS) {
402 | intent.putExtra("fetch_success", true);
403 | } else {
404 | intent.putExtra("fetch_success", false);
405 | }
406 |
407 | mContext.startService(intent);
408 | }
409 |
410 | @Override
411 | protected void onCancelled() {
412 | super.onCancelled();
413 | bCancel = true;
414 | }
415 |
416 | @Override
417 | protected void onPreExecute() {
418 | super.onPreExecute();
419 |
420 | if (mPictureSource == Settings.ID_CUSTOM_TOKEI) {
421 | this.cancel(true);
422 | }
423 | }
424 | }
425 |
--------------------------------------------------------------------------------