I already have this application that once the user clicks a button, the main activity calls a Broadcast Receiver that in turn calls a Service which sends the GPS Location of the user to an EMail Address in a certain interval. The app works just fine.
However, what I want to do is that when the user activates the Power Button of the device, the Broadcast Receiver will activate. So far, I've seen this question and I've used it so my manifest file looks something like:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.angelo.serviceexample"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.angelo.serviceexample.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.permission.PREVENT_POWER_KEY" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.angelo.serviceexample.GPSLoggerService" />
<receiver android:name="com.angelo.serviceexample.AlarmReceiver">
<intent-filter>
<action android:name="android.intent.action.SCREEN_OFF"></action>
<action android:name="android.intent.action.SCREEN_ON"></action>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"> </action>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"></action>
<action android:name="android.intent.action.ACTION_SHUTDOWN"></action>
</intent-filter>
</receiver>
</application>
</manifest>
And the Broadcast Receiver class has intent-filters to call it when activated. The AlarmReceiver.java file looks like this so far:
package com.angelo.serviceexample;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context,GPSLoggerService.class));
//Toast.makeText(, "power button clicked",Toast.LENGTH_LONG).show();
Log.v("Tag", "AlarmReceiver called.");
}
}
However, when I was checking LogCat, the Log only activates whenever the user presses the button in the Main Activity as shown here:
public class MainActivity extends Activity {
private int currentIntervalChoice = 0;
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {
setAppInfo();
addButtonListeners();
enableControls();
return true;
}
return super.dispatchKeyEvent(event);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setAppInfo();
addButtonListeners();
enableControls();
}
private void setAppInfo() {
TextView txtInfo = (TextView)findViewById(R.id.app_info);
txtInfo.setText(Html.fromHtml(getString(R.string.app_info)));
Linkify.addLinks(txtInfo, Linkify.ALL);
}
private void addButtonListeners() {
((Button)findViewById(R.id.start_logging)).setOnClickListener(btnClick);
((Button)findViewById(R.id.logging_interval)).setOnClickListener(btnClick);
}
private void enableControls(){
boolean isServiceRunning = AppSettings.getServiceRunning(this);
String buttonText = getString(R.string.start_logging);
if(isServiceRunning){
buttonText = getString(R.string.stop_logging);
((Button)findViewById(R.id.logging_interval)).setEnabled(false);
}
else{
((Button)findViewById(R.id.logging_interval)).setEnabled(true);
}
((Button)findViewById(R.id.start_logging)).setText(buttonText);
}
private void changeLoggingIntercal(){
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
final String loggingIntervals[] = { "1 minute", "3 minute", "5 minutes", "10 minutes" };
builder.setTitle(getString(R.string.logging_interval));
builder.setSingleChoiceItems(loggingIntervals, currentIntervalChoice, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
currentIntervalChoice = which;
setLoggingInterval(currentIntervalChoice);
dialog.dismiss();
}
});
builder.show();
}
private void setLoggingInterval(int intervalChoice){
int interval = 1;
switch(intervalChoice){
case 0: interval = 1; break;
case 1: interval = 3; break;
case 2: interval = 5; break;
case 3: interval = 10; break;
default: interval = 1; break;
}
AppSettings.setLoggingInterval(this, interval);
}
public void setLogFileName(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = sdf.format(new Date());
String filename = "GPSLog." + dateString + ".kml";
AppSettings.setLogFileName(this, filename);
}
private View.OnClickListener btnClick = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.start_logging:{
toggleLogging(AppSettings.getServiceRunning(MainActivity.this),
AppSettings.getLoggingInterval(MainActivity.this));
enableControls();
break;
}
case R.id.logging_interval:{
changeLoggingIntercal();
break;
}
}
}
};
private void toggleLogging(boolean isStart, int interval){
AlarmManager manager = (AlarmManager)getSystemService(Service.ALARM_SERVICE);
PendingIntent loggerIntent = PendingIntent.getBroadcast(this, 0,new Intent(this,AlarmReceiver.class), 0);
if(isStart){
manager.cancel(loggerIntent);
AppSettings.setServiceRunning(this, false);
AppLog.logString("Service Stopped.");
}
else{
setLogFileName();
long duration = interval * 60 * 1000;
manager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(), duration, loggerIntent);
AppSettings.setServiceRunning(this, true);
Toast.makeText(getApplicationContext(), "Service Started with interval " + interval
+ ", Logfile name: " + AppSettings.getLogFileName(this), Toast.LENGTH_LONG).show();
AppLog.logString("Service Started with interval " + interval
+ ", Logfile name: " + AppSettings.getLogFileName(this));
}
}
}
Also, this is the Service Class that is in question:
public class GPSLoggerService extends Service implements LocationListener{
private static final int gpsMinTime = 500;
private static final int gpsMinDistance = 0;
private static final int TIMER_DELAY = 1000;
private LocationManager manager = null;
private double latitude = 0.0;
private double longitude = 0.0;
private Timer monitoringTimer = null;
public GPSLoggerService() {
AppLog.logString("GPSLoggerService.GPSLoggerService().");
}
@Override
public IBinder onBind(Intent arg0) {
AppLog.logString("GPSLoggerService.onBind().");
return null;
}
@Override
public void onCreate() {
AppLog.logString("GPSLoggerService.onCreate().");
super.onCreate();
}
public int onStartCommand(Intent intent, int flags, int startId) {
AppLog.logString("GPSLoggerService.onStartCommand().");
startLoggingService();
startMonitoringTimer();
return Service.START_STICKY;
}
@Override
public void onLocationChanged(Location location) {
AppLog.logString("GPSLoggerService.onLocationChanged().");
latitude = location.getLatitude();
longitude = location.getLongitude();
}
@Override
public void onProviderDisabled(String provider) {
AppLog.logString("GPSLoggerService.onProviderDisabled().");
}
@Override
public void onProviderEnabled(String provider) {
AppLog.logString("GPSLoggerService.onProviderEnabled().");
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
AppLog.logString("GPSLoggerService.onStatusChanged().");
}
private void startLoggingService(){
if (manager == null){
manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
}
final Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_LOW);
final String bestProvider = manager.getBestProvider(criteria, true);
if (bestProvider != null && bestProvider.length() > 0){
manager.requestLocationUpdates(bestProvider, gpsMinTime,gpsMinDistance, this);
}
else{
final List<String> providers = manager.getProviders(true);
for (final String provider : providers){
manager.requestLocationUpdates(provider, gpsMinTime, gpsMinDistance, this);
}
}
}
private void stopLoggingService(){
stopSelf();
}
private void startMonitoringTimer(){
monitoringTimer = new Timer();
monitoringTimer.scheduleAtFixedRate(
new TimerTask(){
@Override
public void run(){
if (longitude != 0.0 && latitude != 0.0){
monitoringTimer.cancel();
monitoringTimer = null;
manager.removeUpdates(GPSLoggerService.this);
sendCoordinates(latitude, longitude);
stopLoggingService();
}
}
},
GPSLoggerService.TIMER_DELAY,
GPSLoggerService.TIMER_DELAY);
}
private void sendCoordinates(double latitude, double longitude){
Looper.prepare();
GMailSender sender = new GMailSender("sender@gmail.com", "password");
//Subject, Body, Sender, Recipient
try {
sender.sendMail("Sample GPS Location",
"This should go to my yahoo account. My Location is at is - Lat: " + latitude + " Long: " + longitude,
"sender@gmail.com",
"receiver@yahoo.com");
Toast.makeText(getApplicationContext(), "Mail Sent", Toast.LENGTH_SHORT).show();
}
catch (Exception e) {
Log.e("SendMail", e.getMessage(), e);
}
}
}
So far, I'm reading online on how to call a Broadcast Receiver through a phone event which in turn, calls the Service. I think I'm having problems because of the bind override I set though I'm not sure.