Implementation of a Receiver and Service to provide for the capability
to accept control from other Android applications. Allows for changing both Account-level and global settings. Account-level settings can be applied to a single Account or to all Accounts. The file class file derived from src/com/fsck/k9/K9RemoteControl.java will be bundled into a JAR file for use by external applications. This facility will be used for: Issue 215 Issue 730 Issue 864 Issue 884
This commit is contained in:
parent
752b5c59f1
commit
6c22507dfb
5 changed files with 360 additions and 1 deletions
|
@ -25,6 +25,12 @@
|
|||
android:label="@string/read_attachment_label"
|
||||
android:description="@string/read_attachment_desc"/>
|
||||
<uses-permission android:name="com.fsck.k9.permission.READ_ATTACHMENT"/>
|
||||
<permission android:name="com.fsck.k9.permission.REMOTE_CONTROL"
|
||||
android:permissionGroup="android.permission-group.MESSAGES"
|
||||
android:protectionLevel="dangerous"
|
||||
android:label="@string/remote_control_label"
|
||||
android:description="@string/remote_control_desc"/>
|
||||
<uses-permission android:name="com.fsck.k9.permission.REMOTE_CONTROL"/>
|
||||
<application android:icon="@drawable/icon" android:label="@string/app_name" android:name="K9"
|
||||
>
|
||||
<meta-data android:name="android.app.default_searchable"
|
||||
|
@ -219,6 +225,19 @@
|
|||
<action android:name="com.fsck.k9.service.BroadcastReceiver.scheduleIntent"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver android:name="com.fsck.k9.service.RemoteControlReceiver"
|
||||
android:enabled="true"
|
||||
android:permission="com.fsck.k9.permission.REMOTE_CONTROL"
|
||||
>
|
||||
<intent-filter>
|
||||
<action android:name="com.fsck.k9.K9RemoteControl.set"/>
|
||||
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.fsck.k9.K9RemoteControl.requestAccounts"/>
|
||||
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver android:name="com.fsck.k9.service.CoreReceiver"
|
||||
android:enabled="true"
|
||||
>
|
||||
|
@ -241,6 +260,12 @@
|
|||
android:enabled="true"
|
||||
>
|
||||
</service>
|
||||
<service
|
||||
android:name="com.fsck.k9.service.RemoteControlService"
|
||||
android:enabled="true"
|
||||
android:permission="com.fsck.k9.permission.REMOTE_CONTROL"
|
||||
>
|
||||
</service>
|
||||
<service
|
||||
android:name="com.fsck.k9.service.SleepService"
|
||||
android:enabled="true"
|
||||
|
|
|
@ -637,5 +637,7 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin
|
|||
|
||||
<string name="animations_title">Animation</string>
|
||||
<string name="animations_summary">Use gaudy visual effects</string>
|
||||
|
||||
|
||||
<string name="remote_control_label">K-9 Mail remote control</string>
|
||||
<string name="remote_control_desc">Allows this application to control K-9 Mail activities and settings.</string>
|
||||
</resources>
|
||||
|
|
108
src/com/fsck/k9/K9RemoteControl.java
Normal file
108
src/com/fsck/k9/K9RemoteControl.java
Normal file
|
@ -0,0 +1,108 @@
|
|||
package com.fsck.k9;
|
||||
/**
|
||||
* Utillity definitions for Android applications to control the behavior of K-9 Mail. All such applications must declare the following permission:
|
||||
* <uses-permission android:name="com.fsck.k9.permission.REMOTE_CONTROL"/>
|
||||
* in their AndroidManifest.xml
|
||||
*
|
||||
* An application that wishes to act on a particular Account in K-9 needs to fetch the list of configured Accounts by broadcasting an
|
||||
* {@link Intent} using K9_REQUEST_ACCOUNTS as the Action. The broadcast must be made using the {@link ContextWrapper}
|
||||
* sendOrderedBroadcast(Intent intent, String receiverPermission, BroadcastReceiver resultReceiver,
|
||||
* Handler scheduler, int initialCode, String initialData, Bundle initialExtras).sendOrderedBroadcast}
|
||||
* method in order to receive the list of Account UUIDs and descriptions that K-9 will provide.
|
||||
*
|
||||
* @author Daniel I. Applebaum
|
||||
*
|
||||
*/
|
||||
public class K9RemoteControl
|
||||
{
|
||||
/**
|
||||
* {@link Intent} Action to be sent to K-9 using {@link ContextWrapper.sendOrderedBroadcast} in order to fetch the list of configured Accounts.
|
||||
* The responseData will contain two String[] with keys K9_ACCOUNT_UUIDS and K9_ACCOUNT_DESCRIPTIONS
|
||||
*/
|
||||
public final static String K9_REQUEST_ACCOUNTS = "com.fsck.k9.K9RemoteControl.requestAccounts";
|
||||
public final static String K9_ACCOUNT_UUIDS = "com.fsck.k9.K9RemoteControl.accountUuids";
|
||||
public final static String K9_ACCOUNT_DESCRIPTIONS = "com.fsck.k9.K9RemoteControl.accountDescriptions";
|
||||
|
||||
/**
|
||||
* The {@link {@link Intent}} Action to set in order to cause K-9 to check mail. (Not yet implemented)
|
||||
*/
|
||||
//public final static String K9_CHECK_MAIL = "com.fsck.k9.K9RemoteControl.checkMail";
|
||||
|
||||
/**
|
||||
* The {@link {@link Intent}} Action to set when remotely changing K-9 Mail settings
|
||||
*/
|
||||
public final static String K9_SET = "com.fsck.k9.K9RemoteControl.set";
|
||||
/**
|
||||
* The key of the {@link Intent} Extra to set to hold the UUID of a single Account's settings to change. Used only if K9_ALL_ACCOUNTS
|
||||
* is absent or false.
|
||||
*/
|
||||
public final static String K9_ACCOUNT_UUID = "com.fsck.k9.K9RemoteControl.accountUuid";
|
||||
/**
|
||||
* The key of the {@link Intent} Extra to set to control if the settings will apply to all Accounts, or to the one
|
||||
* specified with K9_ACCOUNT_UUID
|
||||
*/
|
||||
public final static String K9_ALL_ACCOUNTS = "com.fsck.k9.K9RemoteControl.allAccounts";
|
||||
|
||||
public final static String K9_ENABLED = "true";
|
||||
public final static String K9_DISABLED = "false";
|
||||
|
||||
/*
|
||||
* Key for the {@link Intent} Extra for controlling whether notifications will be generated for new unread mail.
|
||||
* Acceptable values are K9_ENABLED and K9_DISABLED
|
||||
*/
|
||||
public final static String K9_NOTIFICATION_ENABLED = "com.fsck.k9.K9RemoteControl.notificationEnabled";
|
||||
/*
|
||||
* Key for the {@link Intent} Extra for controlling whether K-9 will sound the ringtone for new unread mail.
|
||||
* Acceptable values are K9_ENABLED and K9_DISABLED
|
||||
*/
|
||||
public final static String K9_RING_ENABLED = "com.fsck.k9.K9RemoteControl.ringEnabled";
|
||||
/*
|
||||
* Key for the {@link Intent} Extra for controlling whether K-9 will activate the vibrator for new unread mail.
|
||||
* Acceptable values are K9_ENABLED and K9_DISABLED
|
||||
*/
|
||||
public final static String K9_VIBRATE_ENABLED = "com.fsck.k9.K9RemoteControl.notificationEnabled";
|
||||
|
||||
public final static String K9_FOLDERS_NONE = "NONE";
|
||||
public final static String K9_FOLDERS_ALL = "ALL";
|
||||
public final static String K9_FOLDERS_FIRST_CLASS = "FIRST_CLASS";
|
||||
public final static String K9_FOLDERS_FIRST_AND_SECOND_CLASS = "FIRST_AND_SECOND_CLASS";
|
||||
public final static String K9_FOLDERS_NOT_SECOND_CLASS = "NOT_SECOND_CLASS";
|
||||
/**
|
||||
* Key for the {@link Intent} Extra to set for controlling which folders to be synchronized with Push.
|
||||
* Acceptable values are K9_FOLDERS_ALL, K9_FOLDERS_FIRST_CLASS, K9_FOLDERS_FIRST_AND_SECOND_CLASS,
|
||||
* K9_FOLDERS_NOT_SECOND_CLASS, K9_FOLDERS_NONE
|
||||
*/
|
||||
public final static String K9_PUSH_CLASSES = "com.fsck.k9.K9RemoteControl.pushClasses";
|
||||
/**
|
||||
* Key for the {@link Intent} Extra to set for controlling which folders to be synchronized with Poll.
|
||||
* Acceptable values are K9_FOLDERS_ALL, K9_FOLDERS_FIRST_CLASS, K9_FOLDERS_FIRST_AND_SECOND_CLASS,
|
||||
* K9_FOLDERS_NOT_SECOND_CLASS, K9_FOLDERS_NONE
|
||||
*/
|
||||
public final static String K9_POLL_CLASSES = "com.fsck.k9.K9RemoteControl.pollClasses";
|
||||
|
||||
public final static String[] K9_POLL_FREQUENCIES = { "-1", "1", "5", "10", "15", "30", "60", "120", "180", "360", "720", "1440"};
|
||||
/**
|
||||
* Key for the {@link Intent} Extra to set with the desired poll frequency. The value is a String representing a number of minutes.
|
||||
* Acceptable values are available in K9_POLL_FREQUENCIES
|
||||
*/
|
||||
public final static String K9_POLL_FREQUENCY = "com.fsck.k9.K9RemoteControl.pollFrequency";
|
||||
|
||||
/**
|
||||
* Key for the {@link Intent} Extra to set for controlling K-9's global "Background sync" setting.
|
||||
* Acceptable values are K9_BACKGROUND_OPERATIONS_ALWAYS, K9_BACKGROUND_OPERATIONS_NEVER
|
||||
* K9_BACKGROUND_OPERATIONS_WHEN_CHECKED
|
||||
*/
|
||||
public final static String K9_BACKGROUND_OPERATIONS = "com.fsck.k9.K9RemoteControl.backgroundOperations";
|
||||
public final static String K9_BACKGROUND_OPERATIONS_WHEN_CHECKED = "WHEN_CHECKED";
|
||||
public final static String K9_BACKGROUND_OPERATIONS_ALWAYS = "ALWAYS";
|
||||
public final static String K9_BACKGROUND_OPERATIONS_NEVER = "NEVER";
|
||||
|
||||
/**
|
||||
* Key for the {@link Intent} Extra to set for controlling which display theme K-9 will use. Acceptable values are
|
||||
* K9_THEME_LIGHT, K9_THEME_DARK
|
||||
*/
|
||||
public final static String K9_THEME = "com.fsck.k9.K9RemoteControl.theme";
|
||||
public final static String K9_THEME_LIGHT = "LIGHT";
|
||||
public final static String K9_THEME_DARK = "DARK";
|
||||
|
||||
}
|
57
src/com/fsck/k9/service/RemoteControlReceiver.java
Normal file
57
src/com/fsck/k9/service/RemoteControlReceiver.java
Normal file
|
@ -0,0 +1,57 @@
|
|||
|
||||
package com.fsck.k9.service;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.K9RemoteControl;
|
||||
import com.fsck.k9.Preferences;
|
||||
|
||||
import static com.fsck.k9.K9RemoteControl.*;
|
||||
|
||||
public class RemoteControlReceiver extends CoreReceiver
|
||||
{
|
||||
public Integer receive(Context context, Intent intent, Integer tmpWakeLockId)
|
||||
{
|
||||
if (K9.DEBUG)
|
||||
Log.i(K9.LOG_TAG, "RemoteControlReceiver.onReceive" + intent);
|
||||
|
||||
if (K9RemoteControl.K9_SET.equals(intent.getAction()))
|
||||
{
|
||||
RemoteControlService.set(context, intent, tmpWakeLockId);
|
||||
tmpWakeLockId = null;
|
||||
}
|
||||
else if (K9RemoteControl.K9_REQUEST_ACCOUNTS.equals(intent.getAction()))
|
||||
{
|
||||
try
|
||||
{
|
||||
Preferences preferences = Preferences.getPreferences(context);
|
||||
Account[] accounts = preferences.getAccounts();
|
||||
String[] uuids = new String[accounts.length];
|
||||
String[] descriptions = new String[accounts.length];
|
||||
for (int i = 0; i < accounts.length; i++)
|
||||
{
|
||||
Account account = accounts[i];
|
||||
|
||||
uuids[i] = account.getUuid();
|
||||
descriptions[i] = account.getDescription();
|
||||
}
|
||||
Bundle bundle = getResultExtras(true);
|
||||
bundle.putStringArray(K9_ACCOUNT_UUIDS, uuids);
|
||||
bundle.putStringArray(K9_ACCOUNT_DESCRIPTIONS, descriptions);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.e(K9.LOG_TAG, "Could not handle K9_RESPONSE_INTENT", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return tmpWakeLockId;
|
||||
}
|
||||
|
||||
}
|
167
src/com/fsck/k9/service/RemoteControlService.java
Normal file
167
src/com/fsck/k9/service/RemoteControlService.java
Normal file
|
@ -0,0 +1,167 @@
|
|||
package com.fsck.k9.service;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.K9RemoteControl;
|
||||
import com.fsck.k9.Preferences;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.Account.FolderMode;
|
||||
|
||||
import static com.fsck.k9.K9RemoteControl.*;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class RemoteControlService extends CoreService
|
||||
{
|
||||
private final static String RESCHEDULE_ACTION = "com.fsck.k9.service.RemoteControlService.RESCHEDULE_ACTION";
|
||||
|
||||
private final static String SET_ACTION = "com.fsck.k9.service.RemoteControlService.SET_ACTION";
|
||||
|
||||
public static void set(Context context, Intent i, Integer wakeLockId)
|
||||
{
|
||||
// Intent i = new Intent();
|
||||
i.setClass(context, RemoteControlService.class);
|
||||
i.setAction(RemoteControlService.SET_ACTION);
|
||||
addWakeLockId(i, wakeLockId);
|
||||
if (wakeLockId == null)
|
||||
{
|
||||
addWakeLock(context, i);
|
||||
}
|
||||
context.startService(i);
|
||||
}
|
||||
|
||||
public static final int REMOTE_CONTROL_SERVICE_WAKE_LOCK_TIMEOUT = 20000;
|
||||
|
||||
@Override
|
||||
public void startService(final Intent intent, final int startId)
|
||||
{
|
||||
if (K9.DEBUG)
|
||||
Log.i(K9.LOG_TAG, "RemoteControlService started with startId = " + startId);
|
||||
final Preferences preferences = Preferences.getPreferences(this);
|
||||
|
||||
if (RESCHEDULE_ACTION.equals(intent.getAction()))
|
||||
{
|
||||
if (K9.DEBUG)
|
||||
Log.i(K9.LOG_TAG, "RemoteControlService requesting MailService reschedule");
|
||||
MailService.actionReschedule(this, null);
|
||||
}
|
||||
else if (RemoteControlService.SET_ACTION.equals(intent.getAction()))
|
||||
{
|
||||
if (K9.DEBUG)
|
||||
Log.i(K9.LOG_TAG, "RemoteControlService got request to change settings");
|
||||
execute(getApplication(), new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
String uuid = intent.getStringExtra(K9_ACCOUNT_UUID);
|
||||
boolean allAccounts = intent.getBooleanExtra(K9_ALL_ACCOUNTS, false);
|
||||
if (K9.DEBUG)
|
||||
{
|
||||
if (allAccounts)
|
||||
{
|
||||
Log.i(K9.LOG_TAG, "RemoteControlService changing settings for all accounts");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.i(K9.LOG_TAG, "RemoteControlService changing settings for account with UUID " + uuid);
|
||||
}
|
||||
}
|
||||
Account[] accounts = preferences.getAccounts();
|
||||
for (Account account : accounts)
|
||||
{
|
||||
if (allAccounts || account.getUuid().equals(uuid))
|
||||
{
|
||||
|
||||
if (K9.DEBUG)
|
||||
Log.i(K9.LOG_TAG, "RemoteControlService changing settings for account " + account.getDescription());
|
||||
|
||||
String notificationEnabled = intent.getStringExtra(K9_NOTIFICATION_ENABLED);
|
||||
String ringEnabled = intent.getStringExtra(K9_RING_ENABLED);
|
||||
String vibrateEnabled = intent.getStringExtra(K9_VIBRATE_ENABLED);
|
||||
String pushClasses = intent.getStringExtra(K9_PUSH_CLASSES);
|
||||
String pollClasses = intent.getStringExtra(K9_POLL_CLASSES);
|
||||
String pollFrequency = intent.getStringExtra(K9_POLL_FREQUENCY);
|
||||
|
||||
if (notificationEnabled != null)
|
||||
{
|
||||
account.setNotifyNewMail(Boolean.parseBoolean(notificationEnabled));
|
||||
}
|
||||
if (ringEnabled != null)
|
||||
{
|
||||
account.setRing(Boolean.parseBoolean(ringEnabled));
|
||||
}
|
||||
if (vibrateEnabled != null)
|
||||
{
|
||||
account.setVibrate(Boolean.parseBoolean(vibrateEnabled));
|
||||
}
|
||||
if (pushClasses != null)
|
||||
{
|
||||
account.setFolderPushMode(FolderMode.valueOf(pushClasses));
|
||||
}
|
||||
if (pollClasses != null)
|
||||
{
|
||||
account.setFolderSyncMode(FolderMode.valueOf(pollClasses));
|
||||
}
|
||||
if (pollFrequency != null)
|
||||
{
|
||||
String[] allowedFrequencies = getResources().getStringArray(R.array.account_settings_check_frequency_values);
|
||||
for (String allowedFrequency : allowedFrequencies)
|
||||
{
|
||||
if (allowedFrequency.equals(pollFrequency))
|
||||
{
|
||||
account.setAutomaticCheckIntervalMinutes(Integer.parseInt(allowedFrequency));
|
||||
}
|
||||
}
|
||||
}
|
||||
account.save(Preferences.getPreferences(RemoteControlService.this));
|
||||
}
|
||||
}
|
||||
if (K9.DEBUG)
|
||||
Log.i(K9.LOG_TAG, "RemoteControlService changing global settings");
|
||||
|
||||
String backgroundOps = intent.getStringExtra(K9_BACKGROUND_OPERATIONS);
|
||||
if (K9RemoteControl.K9_BACKGROUND_OPERATIONS_ALWAYS.equals(backgroundOps)
|
||||
|| K9RemoteControl.K9_BACKGROUND_OPERATIONS_NEVER.equals(backgroundOps)
|
||||
|| K9RemoteControl.K9_BACKGROUND_OPERATIONS_WHEN_CHECKED.equals(backgroundOps))
|
||||
{
|
||||
K9.setBackgroundOps(backgroundOps);
|
||||
}
|
||||
|
||||
String theme = intent.getStringExtra(K9_THEME);
|
||||
if (theme != null)
|
||||
{
|
||||
K9.setK9Theme(K9RemoteControl.K9_THEME_DARK.equals(theme) ? android.R.style.Theme : android.R.style.Theme_Light);
|
||||
}
|
||||
|
||||
SharedPreferences sPrefs = preferences.getPreferences();
|
||||
|
||||
Editor editor = sPrefs.edit();
|
||||
K9.save(editor);
|
||||
editor.commit();
|
||||
|
||||
Intent i = new Intent();
|
||||
i.setClassName(getApplication().getPackageName(), "com.fsck.k9.service.RemoteControlService");
|
||||
i.setAction(RESCHEDULE_ACTION);
|
||||
long nextTime = System.currentTimeMillis() + 10000;
|
||||
BootReceiver.scheduleIntent(RemoteControlService.this, nextTime, i);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.e(K9.LOG_TAG, "Could not handle K9_SET", e);
|
||||
Toast toast = Toast.makeText(RemoteControlService.this, e.getMessage(), Toast.LENGTH_LONG);
|
||||
toast.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
, RemoteControlService.REMOTE_CONTROL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue