package com.dotcool.reader;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import android.app.Activity;
import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.AsyncTask.Status;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;
import com.dotcool.reader.activity.DownloadListActivity;
import com.dotcool.reader.callback.ICallbackNotifier;
import com.dotcool.reader.dao.NovelsDao;
import com.dotcool.reader.model.DownloadModel;
import com.dotcool.reader.service.UpdateService;
import com.speakit.tts.foc.instance.FOCApplication;
/*
* http://www.devahead.com/blog/2011/06/extending-the-android-application-class-and-dealing-with-singleton/
*/
public class LNReaderApplication extends FOCApplication {
private static final String TAG = LNReaderApplication.class.toString();
private static NovelsDao novelsDao = null;
private static DownloadListActivity downloadListActivity = null;
private static UpdateService service = null;
private static LNReaderApplication instance;
private static Hashtable<String, AsyncTask<?, ?, ?>> runningTasks;
private static ArrayList<DownloadModel> downloadList;
private static Object lock = new Object();
public void onCreate() {
super.onCreate();
initSingletons();
instance = this;
doBindService();
Log.d(TAG, "Application created.");
}
public static LNReaderApplication getInstance() {
return instance;
}
protected void initSingletons() {
if (novelsDao == null)
novelsDao = NovelsDao.getInstance(this);
if (downloadListActivity == null)
downloadListActivity = DownloadListActivity.getInstance();
if (runningTasks == null)
runningTasks = new Hashtable<String, AsyncTask<?, ?, ?>>();
if (downloadList == null)
downloadList = new ArrayList<DownloadModel>();
}
/*
* AsyncTask listing method
*/
public static Hashtable<String, AsyncTask<?, ?, ?>> getTaskList() {
return runningTasks;
}
public AsyncTask<?, ?, ?> getTask(String key) {
return runningTasks.get(key);
}
public boolean addTask(String key, AsyncTask<?, ?, ?> task) {
synchronized (lock) {
if (runningTasks.containsKey(key)) {
AsyncTask<?, ?, ?> tempTask = runningTasks.get(key);
if (tempTask != null && tempTask.getStatus() != Status.FINISHED)
return false;
}
runningTasks.put(key, task);
return true;
}
}
public boolean removeTask(String key) {
synchronized (lock) {
if (!runningTasks.containsKey(key))
return false;
runningTasks.remove(key);
return true;
}
}
public boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
}
return false;
}
/*
* DownloadActivity method
*/
public int addDownload(String id, String name) {
synchronized (lock) {
downloadList.add(new DownloadModel(id, name, 0));
if (DownloadListActivity.getInstance() != null)
DownloadListActivity.getInstance().updateContent();
return downloadList.size();
}
}
public void removeDownload(String id) {
synchronized (lock) {
for (int i = 0; i < downloadList.size(); i++) {
if (downloadList.get(i).getDownloadId() == id) {
downloadList.remove(i);
break;
}
}
}
if (DownloadListActivity.getInstance() != null)
DownloadListActivity.getInstance().updateContent();
}
public String getDownloadDescription(String id) {
String name = "";
for (int i = 0; i < downloadList.size(); i++) {
if (downloadList.get(i).getDownloadId() == id) {
name = downloadList.get(i).getDownloadName();
break;
}
}
return name;
}
public boolean checkIfDownloadExists(String name) {
synchronized (lock) {
boolean exists = false;
for (int i = 0; i < downloadList.size(); i++) {
if (downloadList.get(i).getDownloadName().equals(name)) {
exists = true;
}
}
return exists;
}
}
public ArrayList<DownloadModel> getDownloadList() {
return downloadList;
}
public void updateDownload(String id, Integer progress, String message) {
/*
* Although this may seem an attempt at a fake incremental download bar
* its actually a progressbar smoother.
*/
int index = 0;
Integer oldProgress;
final Integer Increment;
int smoothTime = 1000;
int tickTime = 25;
int tempIncrease = 0;
for (int i = 0; i < downloadList.size(); i++) {
if (downloadList.get(i).getDownloadId() == id) {
index = i;
}
}
final int idx = index;
// Download status message
if (downloadList.get(idx) != null) {
downloadList.get(idx).setDownloadMessage(message);
}
if (DownloadListActivity.getInstance() != null) {
DownloadListActivity.getInstance().updateContent();
}
oldProgress = downloadList.get(index).getDownloadProgress();
tempIncrease = (progress - oldProgress);
if (tempIncrease < smoothTime / tickTime) {
smoothTime = tickTime * tempIncrease;
tempIncrease = 1;
} else
tempIncrease /= (smoothTime / tickTime);
Increment = tempIncrease;
new CountDownTimer(smoothTime, tickTime) {
@Override
public void onTick(long millisUntilFinished) {
if (downloadList.size() > idx) {
DownloadModel temp = downloadList.get(idx);
if (temp != null) {
temp.setDownloadProgress(temp.getDownloadProgress() + Increment);
}
}
if (DownloadListActivity.getInstance() != null) {
DownloadListActivity.getInstance().updateContent();
}
}
@Override
public void onFinish() {
}
}.start();
}
/*
* UpdateService method
*/
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
service = ((UpdateService.MyBinder) binder).getService();
Log.d(UpdateService.TAG, "onServiceConnected");
Toast.makeText(getApplicationContext(), "Connected", Toast.LENGTH_SHORT).show();
}
public void onServiceDisconnected(ComponentName className) {
service = null;
Log.d(UpdateService.TAG, "onServiceDisconnected");
}
};
private void doBindService() {
bindService(new Intent(this, UpdateService.class), mConnection, Context.BIND_AUTO_CREATE);
Log.d(UpdateService.TAG, "doBindService");
}
public void setUpdateServiceListener(ICallbackNotifier notifier) {
if (service != null) {
service.notifier = notifier;
}
}
public void runUpdateService(boolean force, ICallbackNotifier notifier) {
if (service == null) {
doBindService();
service.force = force;
service.notifier = notifier;
} else
service.force = force;
service.notifier = notifier;
service.onStartCommand(null, BIND_AUTO_CREATE, (int) (new Date().getTime() / 1000));
}
@Override
public void onLowMemory() {
/*
* java.lang.IllegalArgumentException
* in android.app.LoadedApk.forgetServiceDispatcher
*
* probable crash: service is not checked if it exists after onLowMemory.
* Technically fixed. needs checking.
*/
if (mConnection != null) {
Log.w(TAG, "Low Memory, Trying to unbind service...");
try {
unbindService(mConnection);
Log.i(TAG, "Unbind service done.");
} catch (Exception ex) {
Log.e(TAG, "Failed to unbind.", ex);
}
}
super.onLowMemory();
}
/*
* CSS caching method.
* Also used for caching javascript.
*/
private Hashtable<Integer, String> cssCache = null;
public String ReadCss(int styleId) {
if (cssCache == null)
cssCache = new Hashtable<Integer, String>();
if (!cssCache.containsKey(styleId)) {
cssCache.put(styleId, UIHelper.readRawStringResources(getApplicationContext(), styleId));
}
return cssCache.get(styleId);
}
public void resetFirstRun() {
SharedPreferences.Editor edit = PreferenceManager.getDefaultSharedPreferences(this).edit();
edit.remove(Constants.PREF_FIRST_RUN);
edit.commit();
}
public void restartApplication() {
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
}