package dentex.youtube.downloader.service;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.bugsense.trace.BugSenseHandler;
import android.app.DownloadManager;
import android.app.DownloadManager.Query;
import android.app.DownloadManager.Request;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
import dentex.youtube.downloader.R;
import dentex.youtube.downloader.ShareActivity;
import dentex.youtube.downloader.YTD;
import dentex.youtube.downloader.utils.Utils;
public class AutoUpgradeApkService extends Service {
private String currentVersion;
private String apkFilename;
private static final String DEBUG_TAG = "AutoUpgradeApkService";
private DownloadManager downloadManager;
File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
private static String webPage;
public long enqueue;
private Uri fileUri;
private AsyncUpdate asyncAutoUpdate;
public String onlineVersion;
public String onlineChangelog;
public static String matchedVersion;
public static String matchedChangeLog;
public String matchedMd5;
boolean isAsyncTaskRunning = false;
private String compRes = "init";
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
Utils.logger("d", "service created", DEBUG_TAG);
BugSenseHandler.initAndStartSession(this, YTD.BAK);
registerReceiver(apkReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
try {
currentVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
Utils.logger("d", "current version: " + currentVersion, DEBUG_TAG);
} catch (NameNotFoundException e) {
Log.e(DEBUG_TAG, "version not read: " + e.getMessage());
currentVersion = "100";
}
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected() && matchedVersion != "n.a.") {
try {
//init version and changelog
matchedChangeLog = null;
matchedVersion = null;
asyncAutoUpdate = new AsyncUpdate();
webPage = "http://sourceforge.net/projects/ytdownloader/files/";
asyncAutoUpdate.execute(webPage);
} catch (NullPointerException e) {
Log.e(DEBUG_TAG, "unable to retrieve update data.");
}
} else {
Log.e(DEBUG_TAG, getString(R.string.no_net));
}
}
@Override
public void onDestroy() {
Utils.logger("d", "service destroyed", DEBUG_TAG);
unregisterReceiver(apkReceiver);
}
private class AsyncUpdate extends AsyncTask<String, Void, Integer> {
protected void onPreExecute() {
isAsyncTaskRunning = true;
}
protected Integer doInBackground(String... urls) {
// params comes from the execute() call: params[0] is the url.
try {
Utils.logger("d", "doInBackground...", DEBUG_TAG);
return downloadUrl(urls[0]);
} catch (IOException e) {
Log.e(DEBUG_TAG, "doInBackground: " + e.getMessage());
matchedVersion = "n.a.";
return 1;
}
}
private int downloadUrl(String myurl) throws IOException {
InputStream is = null;
int len = 100000;
Utils.logger("d", "The link is: " + myurl, DEBUG_TAG);
try {
URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("User-Agent","<em>" + ShareActivity.USER_AGENT_FIREFOX + "</em>");
conn.setReadTimeout(20000 /* milliseconds */);
conn.setConnectTimeout(30000 /* milliseconds */);
conn.setInstanceFollowRedirects(false);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.connect();
int response = conn.getResponseCode();
Utils.logger("d", "The response is: " + response, DEBUG_TAG);
is = conn.getInputStream();
if (!asyncAutoUpdate.isCancelled()) {
return readIt(is, len);
} else {
Utils.logger("d", "asyncUpdate cancelled @ 'return readIt'", DEBUG_TAG);
return 3;
}
} finally {
if (is != null) {
is.close();
}
}
}
public int readIt(InputStream stream, int len) throws IOException, UnsupportedEncodingException {
Reader reader = null;
reader = new InputStreamReader(stream, "UTF-8");
char[] buffer = new char[len];
reader.read(buffer);
String content = new String(buffer);
return OnlineUpdateCheck(content);
}
@Override
protected void onPostExecute(Integer result) {
/*if (matchedVersion.contentEquals("n.a.")) {
}*/
if (compRes.contentEquals(">")) {
Utils.logger("d", "version comparison: downloading latest version...", DEBUG_TAG);
NotificationCompat.Builder builder = new NotificationCompat.Builder(AutoUpgradeApkService.this);
builder.setSmallIcon(R.drawable.icon_nb)
.setContentTitle(getString(R.string.title_activity_share))
.setContentText("v" + matchedVersion + " " + getString(R.string.new_v_download));
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(2, builder.build());
callDownloadApk(matchedVersion);
} else if (compRes.contentEquals("==")) {
//PopUps.showPopUp(getString(R.string.information), getString(R.string.upgrade_latest_installed), "info", AutoUpgradeApk.this);
Utils.logger("d", "version comparison: latest version is already installed!", DEBUG_TAG);
stopSelf();
} else if (compRes.contentEquals("<")) {
// No need for a popup...
Utils.logger("d", "version comparison: installed higher than the one online? ...this should not happen...", DEBUG_TAG);
stopSelf();
} else if (compRes.contentEquals("init")) {
Utils.logger("d", "version comparison not tested", DEBUG_TAG);
stopSelf();
}
}
}
private int OnlineUpdateCheck(String content) {
Utils.logger("d", "OnlineUpdateCheck", DEBUG_TAG);
int res = 3;
if (asyncAutoUpdate.isCancelled()) {
Utils.logger("d", "asyncUpdate cancelled @ 'OnlineUpdateCheck' begin", DEBUG_TAG);
return 3;
}
// match version name
Pattern v_pattern = Pattern.compile("versionName=\\\"(.*)\\\"");
Matcher v_matcher = v_pattern.matcher(content);
if (v_matcher.find() && !asyncAutoUpdate.isCancelled()) {
matchedVersion = v_matcher.group(1);
Utils.logger("i", "_on-line version: " + matchedVersion, DEBUG_TAG);
res = res - 1;
} else {
matchedVersion = "not_found";
Log.e(DEBUG_TAG, "_online version: not found!");
}
// match changelog
Pattern cl_pattern = Pattern.compile("<pre><code> v(.*?)</code></pre>", Pattern.DOTALL);
Matcher cl_matcher = cl_pattern.matcher(content);
if (cl_matcher.find() && !asyncAutoUpdate.isCancelled()) {
matchedChangeLog = " v" + cl_matcher.group(1);
Utils.logger("i", "_online changelog...", DEBUG_TAG);
res = res - 1;
} else {
matchedChangeLog = "not_found";
Log.e(DEBUG_TAG, "_online changelog not found!");
}
// match md5
// checksum: <code>d7ef1e4668b24517fb54231571b4a74f</code> dentex.youtube.downloader_v1.4
Pattern md5_pattern = Pattern.compile("checksum: <code>(.{32})</code> dentex.youtube.downloader_v");
Matcher md5_matcher = md5_pattern.matcher(content);
if (md5_matcher.find() && !asyncAutoUpdate.isCancelled()) {
matchedMd5 = md5_matcher.group(1);
Utils.logger("i", "_online md5sum: " + matchedMd5, DEBUG_TAG);
res = res - 1;
} else {
matchedMd5 = "not_found";
Log.e(DEBUG_TAG, "_online md5sum not found!");
}
compRes = Utils.VersionComparator.compare(matchedVersion, currentVersion);
Utils.logger("d", "version comparison: " + matchedVersion + " " + compRes + " " + currentVersion, DEBUG_TAG);
return res;
}
void callDownloadApk(String ver) {
String apklink = "http://sourceforge.net/projects/ytdownloader/files/dentex.youtube.downloader_v" + ver + ".apk/download";
apkFilename = "dentex.youtube.downloader_v" + ver + ".apk";
Request request = new Request(Uri.parse(apklink));
fileUri = Uri.parse(dir.toURI() + apkFilename);
request.setDestinationUri(fileUri);
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
request.setTitle("YouTube Downloader v" + ver);
downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
enqueue = downloadManager.enqueue(request);
}
BroadcastReceiver apkReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -2);
if (enqueue != -1 && id != -2 && id == enqueue) {
Query query = new Query();
query.setFilterById(id);
DownloadManager dm = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
Cursor c = dm.query(query);
if (c.moveToFirst()) {
int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
int status = c.getInt(columnIndex);
if (status == DownloadManager.STATUS_SUCCESSFUL) {
if (Utils.checkMD5(matchedMd5, new File(dir, apkFilename))) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setSmallIcon(R.drawable.icon_nb)
.setContentTitle(getString(R.string.title_activity_share))
.setContentText("v" + matchedVersion + " " + getString(R.string.new_v_install));
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent1 = new Intent();
intent1.setAction(android.content.Intent.ACTION_VIEW);
intent1.setDataAndType(fileUri, "application/vnd.android.package-archive");
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent1, 0);
builder.setContentIntent(contentIntent);
notificationManager.notify(2, builder.build());
} else {
deleteBadDownload(context, intent);
}
}
}
}
stopSelf();
}
public void deleteBadDownload(final Context context, final Intent intent) {
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -2);
downloadManager.remove(id);
Toast.makeText(context, "YTD: " + getString(R.string.failed_download), Toast.LENGTH_LONG).show();
}
};
}