/*
* Copyright (C) 2013 Fairphone Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fairphone.updater;
import android.app.DownloadManager;
import android.app.DownloadManager.Request;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.app.TaskStackBuilder;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.BitmapFactory;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.Environment;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class UpdaterService extends Service {
private static final String TAG = UpdaterService.class.getSimpleName();
private static final String PREFERENCE_DATE_LAST_TIME_CHECKED = "LastTimeUpdateChecked";
private DownloadManager mDownloadManager;
private DownloadBroadCastReceiver mDownloadBroadCastReceiver;
private long mLatestFileDownloadId;
private SharedPreferences mSharedPreferences;
private SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault());
final static long DAY_IN_MILLIS = 1000 * 60 * 60 * 24;
private static final int MAX_DAYS_BEFORE_CHECKING = 8;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mSharedPreferences = getApplicationContext().getSharedPreferences(FairphoneUpdater.FAIRPHONE_UPDATER_PREFERENCES, MODE_PRIVATE);
if(hasInternetConnection() ){
// remove the old file if its still there for some reason
removeLatestFile(getApplicationContext());
setupDownloadManager();
// start the download of the latest file
startDownloadLatest();
}
return Service.START_NOT_STICKY;
}
private void removeLatestFile(Context context) {
VersionParserHelper.removeFiles(context);
updateLastChecked("2013.01.01 00:00:00");
}
private boolean isFileStillValid() {
Date lastTimeChecked = getLastTimeCheckedDate();
int diffInDays = (int) ((System.currentTimeMillis() - lastTimeChecked.getTime())/ DAY_IN_MILLIS );
return diffInDays < MAX_DAYS_BEFORE_CHECKING;
}
private Date getLastTimeCheckedDate() {
String lastTimeDatePreference = mSharedPreferences.getString(PREFERENCE_DATE_LAST_TIME_CHECKED, "2013.01.01 00:00:00");
Date lastTimeDate = null;
try {
lastTimeDate = mDateFormat.parse(lastTimeDatePreference);
} catch (ParseException e) {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.YEAR, -1);
lastTimeDate = cal.getTime();
}
return lastTimeDate;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
public void startDownloadLatest() {
if(hasConnection()){
Resources resources = getApplicationContext().getResources();
// set the download for the latest version on the download manager
Request request = createDownloadRequest(resources.getString(R.string.downloadUrl), resources.getString(R.string.versionFilename) + resources.getString(R.string.versionFilename_zip));
mLatestFileDownloadId = mDownloadManager.enqueue(request);
}
}
private boolean hasConnection() {
return isWiFiEnabled();
}
private boolean isWiFiEnabled() {
ConnectivityManager manager = (ConnectivityManager) getApplicationContext()
.getSystemService(Context.CONNECTIVITY_SERVICE);
boolean isWifi = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
.isConnectedOrConnecting();
return isWifi;
}
private void setNotification() {
Context context = getApplicationContext();
NotificationManager manager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(
context)
.setSmallIcon(R.drawable.fairphone_updater_tray_icon_small)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.fairphone_updater_tray_icon))
.setContentTitle(
context.getResources().getString(R.string.app_name))
.setContentText(getResources().getString(R.string.fairphoneUpdateMessage));
Intent resultIntent = new Intent(context, FairphoneUpdater.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(FairphoneUpdater.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(resultPendingIntent);
Notification notificationWhileRunnig = builder.build();
// Add notification
manager.notify(0, notificationWhileRunnig);
//to update the activity
Intent updateIntent = new Intent(FairphoneUpdater.FAIRPHONE_UPDATER_NEW_VERSION_RECEIVED);
sendBroadcast(updateIntent);
}
private Request createDownloadRequest(String url, String fileName) {
Request request = new Request(Uri.parse(url));
Environment.getExternalStoragePublicDirectory(
Environment.getExternalStorageDirectory()
+ VersionParserHelper.UPDATER_FOLDER).mkdirs();
request.setDestinationInExternalPublicDir(
VersionParserHelper.UPDATER_FOLDER, fileName);
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
request.setAllowedOverRoaming(false);
Resources resources = getApplicationContext().getResources();
request.setTitle(resources.getString(R.string.downloadUpdateTitle));
return request;
}
private boolean hasInternetConnection() {
ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
boolean is3g = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE)
.isConnectedOrConnecting();
boolean isWifi = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
.isConnectedOrConnecting();
return isWifi || is3g;
}
private void setupDownloadManager() {
mDownloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
mDownloadBroadCastReceiver = new DownloadBroadCastReceiver();
getApplicationContext().registerReceiver(mDownloadBroadCastReceiver,
new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
private void removeBroadcastReceiver() {
getApplicationContext().unregisterReceiver(mDownloadBroadCastReceiver);
}
private void checkVersionValidation(Context context){
Version latestVersion = VersionParserHelper
.getLastestVersion(getApplicationContext());
Version currentVersion = VersionParserHelper
.getDeviceVersion(getApplicationContext());
if(latestVersion != null){
String versionName = null;
String versionNumber = null;
String versionUrl = null;
String versionMd5 = null;
String versionAndroid = null;
if(latestVersion.isNewerVersionThan(currentVersion)){
// save the version in the share preferences
versionName = latestVersion.getName();
versionNumber = latestVersion.getNumber();
versionUrl = latestVersion.getDownloadLink();
versionMd5 = latestVersion.getMd5Sum();
versionAndroid = latestVersion.getAndroid();
setNotification();
} else {
VersionParserHelper.removeLatestVersionFile(getApplicationContext());
}
Editor editor = mSharedPreferences.edit();
editor.putString(FairphoneUpdater.PREFERENCE_NEW_VERSION_NAME, versionName);
editor.putString(FairphoneUpdater.PREFERENCE_NEW_VERSION_NUMBER, versionNumber);
editor.putString(FairphoneUpdater.PREFERENCE_NEW_VERSION_MD5_SUM, versionMd5);
editor.putString(FairphoneUpdater.PREFERENCE_NEW_VERSION_URL, versionUrl);
editor.putString(FairphoneUpdater.PREFERENCE_NEW_VERSION_ANDROID, versionAndroid);
editor.commit();
removeLatestFileDownload(context);
}
}
private void removeLatestFileDownload(Context context) {
if(mLatestFileDownloadId != 0){
mDownloadManager.remove(mLatestFileDownloadId);
mLatestFileDownloadId = 0;
}
VersionParserHelper.removeFiles(context);
}
private float parseVersion(String number) {
String finalNumber = number.replaceAll("\\.", "");
return Float.parseFloat(finalNumber);
}
private void updateLastChecked(String date) {
Editor editor = mSharedPreferences.edit();
editor.putString(PREFERENCE_DATE_LAST_TIME_CHECKED, date);
editor.commit();
}
private class DownloadBroadCastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(mLatestFileDownloadId);
Cursor cursor = mDownloadManager.query(query);
if (cursor.moveToFirst()) {
int columnIndex = cursor
.getColumnIndex(DownloadManager.COLUMN_STATUS);
int status = cursor.getInt(columnIndex);
if (status == DownloadManager.STATUS_SUCCESSFUL) {
String filePath = mDownloadManager.getUriForDownloadedFile(
mLatestFileDownloadId).getPath();
String targetPath = Environment.getExternalStorageDirectory()
+ VersionParserHelper.UPDATER_FOLDER;
if(RSAUtils.checkFileSignature(context, filePath, targetPath)){
updateLastChecked(mDateFormat.format(Calendar.getInstance().getTime()));
checkVersionValidation(context);
}else{
//invalid file
removeLatestFileDownload(context);
}
}
}
cursor.close();
removeBroadcastReceiver();
}
}
}