I have implemented a code that opens an app when we shake our device. As far as i kept all my code into the MainActivity and without any background service, it all went well. But its not working when i tried to add a background service as i want it keep working without going into an app every time. So can anybody suggest me where am i doing wrong.Thanks!
BackgroundService.java
public class BackgroundService extends Service implements SensorEventListener {
public BackgroundService() {
}
private SensorManager mSensorManager;
private Sensor mSensor;
private long lastUpdate = 0;
private float last_x, last_y, last_z;
private static final int SHAKE_THRESHOLD = 600;
#Override
public void onCreate() {
super.onCreate();
// Get sensor manager on starting the service.
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
// Registering...
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
// Get default sensor type
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Get sensor manager on starting the service.
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
// Registering...
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
// Get default sensor type
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not Yet Implemented");
}
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
Sensor mySensor = sensorEvent.sensor;
mSensorManager.registerListener(this, mySensor, SensorManager.SENSOR_DELAY_NORMAL);
if (mySensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float[] values = sensorEvent.values;
float x = values[0];
float y = values[1];
float z = values[2];
long curTime = System.currentTimeMillis();
if ((curTime - lastUpdate) > 100) {
long diffTime = (curTime - lastUpdate);
lastUpdate = curTime;
float speed
= Math.abs(x + y + z - last_x - last_y - last_z) / diffTime * 10000;
if (speed > SHAKE_THRESHOLD) {
openWhatsApp();
}
last_x = x;
last_y = y;
last_z = z;
}
// Stop the sensor and service
mSensorManager.unregisterListener(this);
stopSelf();
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
public void openWhatsApp() {
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.whatsapp");
if (launchIntent != null) {
startService(launchIntent);
}
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Intent i = new Intent(MainActivity.this, BackgroundService.class);
startService(i);
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="joshipinak.com.shakeshooksaken">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".BackgroundService" />
</application>
</manifest>
In GitHub Android Examples there is a complete app. It uses the command pattern like your code for checking the sensor values and AlarmManager.
In this question on SO is an example using the SensorEventListener interface.
The Android developer site says to use IntentService on this page.
You can also read what is the difference between Service and IntentService in this question on SO.
These links may also help you:
A question on SO about having an Android app running in the background
Duplicate of previous link with other information
SO question about communication between Activity and Service
Related
I try do do some background calculation tasks in an Android application.
My Main class :
public class MainActivity extends AppCompatActivity {
private CalculationReceiver calculationReceiver = new CalculationReceiver();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
final Context mContext = this;
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
calculationReceiver.doAddition(mContext, 2, 2);
}
});
}
}
My service :
public class CalculationService extends IntentService {
public CalculationService() {
super("Calculation Service");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
int nb1 = intent.getIntExtra(NUMBER_1,0);
int nb2 = intent.getIntExtra(NUMBER_2,0);
doAddition(nb1,nb2);
CalculationReceiver.completeWakefulIntent(intent);
}
public void doAddition(int number1, int number2){
int result = number1+number2;
System.out.println("Result : " + result);
}
}
My receiver :
public class CalculationReceiver extends WakefulBroadcastReceiver {
public static final String NUMBER_1 = "NUMBER_1";
public static final String NUMBER_2 = "NUMBER_2";
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, CalculationService.class);
int receiverNumber1 = intent.getIntExtra(NUMBER_1,0);
int receiverNumber2 = intent.getIntExtra(NUMBER_2,0);
service.putExtra(NUMBER_1,receiverNumber1);
service.putExtra(NUMBER_2,receiverNumber2);
startWakefulService(context, service);
}
public void doAddition (Context context, int number1, int number2){
Intent intent = new Intent(context, CalculationReceiver.class);
intent.putExtra(NUMBER_1,number1);
intent.putExtra(NUMBER_2,number2);
context.sendBroadcast(intent);
}
}
My Manifest :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testservices">
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".ReductionService"
android:enabled="true" />
<receiver android:name=".ReductionReceiver"/>
<service android:name=".CalculationService"
android:enabled="true" />
<receiver android:name=".CalculationReceiver"/>
</application>
</manifest>
The calculations of the application are more complex than these additions, and can take several minutes (in average 15 minutes) to be done.
According to the Google documentation (https://developer.android.com/training/scheduling/wakelock.html), I decided to implement this architecture to make sure that the calculation is done to the end.
The idea is that the user starts his calculation and then waits for the application to give the result. In the meantime, he can launch other apps or lock his phone, the calculation must not stop.
This approach seems to work.
What bothers me here is the call to service in the receiver:
context.sendBroadcast (intent);
Is there a more "clean" way to start the service?
What strikes me is that it does not seem very "clean", especially the passage of several times the same parameter (number1 and number2)
Thanks
According to the Google documentation (https://developer.android.com/training/scheduling/wakelock.html), I decided to implement this architecture to make sure that the calculation is done to the end.
That is not how the documentation shows using WakefulBroadcastReceiver. Plus, WakefulBroadcastReceiver was deprecated in version 26.0.0 of the support libraries.
The idea is that the user starts his calculation and then waits for the application to give the result.
My interpretation of this is that the user is requesting, through your activity's UI, to start the calculation. This means that at this point in time, the screen is on and you have an activity in the foreground.
Is there a more "clean" way to start the service?
Call startService().
Step #1: Delete your use of the deprecated WakefulBroadcastReceiver
Step #2: Have your activity call startService() to start the service
Step #3: Have your service acquire a partial WakeLock through the PowerManager system service, in the service's onCreate() method
Step #4: Have your service release that WakeLock in the service's onDestroy() method
Step #5: Modify the service to be a foreground service, calling startForeground() in onCreate() with a suitable Notification to allow the user to control the behavior of the service
Note that:
If you skip Step #5, your service will stop running after ~1 minute on Android 8.0+.
This will still not work on Android 6.0+ if the device enters into Doze mode. That should not happen for ~1 hour, but you need to make sure that your calculations are done by then.
Consider offloading the calculation work to a server, rather than burning up the user's CPU for an extended period of time (through your calculation work plus the wakelock)
It was in this way that I resolved it, following the advice of #CommonsWare
Main Activity :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
final Context mContext = this;
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent service = new Intent(mContext, CalculationService.class);
service.putExtra(NUMBER_1,2);
service.putExtra(NUMBER_2,2);
startService(service);
}
});
}
}
Calculation Service :
public class CalculationService extends IntentService {
public static final String NUMBER_1 = "NUMBER_1";
public static final String NUMBER_2 = "NUMBER_2";
private static final int FOREGROUND_ID = 42;
PowerManager.WakeLock wakeLock;
public CalculationService() {
super("Calculation Service");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
int nb1 = intent.getIntExtra(NUMBER_1,0);
int nb2 = intent.getIntExtra(NUMBER_2,0);
doAddition(nb1,nb2);
}
public void doAddition(int number1, int number2){
int result = number1+number2;
System.out.println("Result : " + result);
}
#Override
public void onCreate() {
super.onCreate();
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"CalculationServiceWakelockTag");
wakeLock.acquire();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Calculation App")
.setContentText("Calculation in progress")
.setContentIntent(pendingIntent).build();
startForeground(FOREGROUND_ID, notification);
}
#Override
public void onDestroy() {
super.onDestroy();
wakeLock.release();
}
}
This is working great :)
But can I call
startForegroundService(service)
instead of
startService(service);
or not ? And why ?
So I need a service for my app, but I need it to keep running all the time until the user press the end Button in the app. It goes like this : The user press start, my service start (starting a notification btw), then 2-3h or more later the user has to click on the notification which get him back to the app where he can press the "End" button and end the service. I call this a Start-End cycle for simplicity purposes.
My user will use many Start-End cycles a day, but the problem is my notification goes away after some time when the phone his lock.
I've already been able to put the notification and service thanks to Stackoverflow so I hope you have a solution for this too :)!
Here is my main activity :
public class MainActivity extends AppCompatActivity{
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkEnabled();
mTimeListenerD.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) { //Button to set the Start time
setDebutTime();
checkEnabled();
new Thread(new Runnable() {
#Override
public void run() {
Intent start=new Intent(MainActivity.this,TimeService.class);
start.putExtra("StopSig",false);
start.putExtra("Temps_travail",mTempsTravail); //Envoi Long
start.putExtra("mSmallest",mSmallest); //Envoi Long
start.putExtra("file_src",src); //Envoi String
start.putExtra("file_dst",dst); //Envoi String
start.putExtra("Debut",sDebut); //Envoi String
start.putExtra("Fin",sFin); //Envoi String
start.putExtra("Name",sName);//Envoi String
start.putExtra("String_travail",sTempsTravail); //Envoi String
start.putExtra("Smallest",sSmallest);//Envoi String*/
startService(start);
}
}).start();
}
});
mTimeListenerF.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) { //Button to set the End Time
setFinTime();
checkEnabled();
new Thread(new Runnable() {
#Override
public void run() {
Intent end = new Intent(MainActivity.this,TimeService.class);
end.putExtra("StopSig",true);
end.putExtra("TimeF",mTimeF);
end.putExtra("Temps_travail",mTempsTravail); //Envoi Long
end.putExtra("mSmallest",mSmallest); //Envoi Long
end.putExtra("file_src",src); //Envoi String
end.putExtra("file_dst",dst); //Envoi String
end.putExtra("Debut",sDebut); //Envoi String
end.putExtra("Fin",sFin); //Envoi String
end.putExtra("Name",sName);//Envoi String
end.putExtra("String_travail",sTempsTravail); //Envoi String
end.putExtra("Smallest",sSmallest);
// startService(end);
stopService(end);
}
}).start();
}
});
mMail.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendMail();
}
}); //Send data by mail
Here is the service i use, with the method that show the notification:
public class TimeService extends Service {
#Override
public void onCreate() {
Log.i(TAG, "Service onCreate");
mContext=TimeService.this;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service onStartCommand");
Toast.makeText(this,"TimeServiceStarted",Toast.LENGTH_LONG).show();
stopSig=intent.getBooleanExtra("StopSig",false); //Receiving Boolean
setDebutTime();
setNotification();
//Stop service once it finishes its task
//stopSelf();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
Log.i(TAG, "Service onBind");
TSTempsTravail=arg0.getLongExtra("Temps_travail",TSTempsTravail); //Receiving Long
TSSmallest=arg0.getLongExtra("mSmallest",TSSmallest);//Receiving Long
sName=arg0.getStringExtra("Name");//Receiving String
sDebut= arg0.getStringExtra("Debut");//Receiving String
sFin= arg0.getStringExtra("Fin");//Receiving String
sTempsTravail= arg0.getStringExtra("String_travail");//Receiving String
sSmallest=arg0.getStringExtra("Smallest");//Receiving String
return null;
}
#Override
public void onDestroy() {
stopSig=true;
setFinTime();
// getName();
getHeureSupp(TimeD,TimeF);
Clock();
writeToFile(sDebut,sFin,sName,sTempsTravail);
try {
copyFile(src,dst);
} catch (IOException e) {
e.printStackTrace();
}
//sendMail();
Log.i(TAG, "Service onDestroy");
//Toast.makeText(this,"Service stopped",Toast.LENGTH_LONG).show();
}
public void setNotification() {
Intent notificationIntent = new Intent(this, MainActivity.class);
/*notificationIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);*/
PendingIntent pendingIntent = PendingIntent.getActivity(this, 15, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Bitmap icon = BitmapFactory.decodeResource(getResources(),
R.drawable.logo);
NotificationCompat.Builder notification = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setContentTitle("myTitle")
.setTicker("myTicker")
.setContentText("myText")
.setSmallIcon(R.drawable.logo_small)
.setLargeIcon(Bitmap.createScaledBitmap(icon, 128, 128, false))
.setContentIntent(pendingIntent)
.setOngoing(true);
startForeground(15, notification.build());
}
And finally here is the Manifest if that can be useful in anyway :
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.benjii.myapp">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<application
android:allowBackup="true"
android:icon="#drawable/logo_small"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".TimeService"
android:icon="#drawable/logo_small"
android:label="#string/service">
</service>
</application>
</manifest>
Application components (services, activities, etc) always run in main thread, no matter what thread they are started from. Consider starting thread in your Service instead, or use an IntentService.
So i want to make a floating app which on click would stop location.
here's the MainActivity class
public class MainActivity extends Service {
private WindowManager windowManager;
private ImageView chatHead;
#Override public void onCreate() {
super.onCreate();
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
chatHead = new ImageView(this);
chatHead.setImageResource(R.mipmap.ic_launcher);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.LEFT;
params.x = 0;
params.y = 100;
windowManager.addView(chatHead, params);
chatHead.setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
initialX = params.x;
initialY = params.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
return true;
case MotionEvent.ACTION_UP:
return true;
case MotionEvent.ACTION_MOVE:
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
windowManager.updateViewLayout(chatHead, params);
return true;
}
return false;
}
});
chatHead.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent=new Intent(MainActivity.this,LocationService.class);
startService(intent);
}
});
}
#Override
public void onDestroy() {
super.onDestroy();
if (chatHead != null) windowManager.removeView(chatHead);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
In the manifest i have set the MainActivity as a service. now when i try to run the app it shows an error
Could not identify launch activity: Default Activity not found
What is the issue here? i mean i know there is no activity and i intend to have no activity because it is a service ( a floating app).
What to do
----------------------------------EDIT------------------------------------
Manifest file
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<service
android:name=".MainActivity"
android:label="#string/app_name">
</service>
<service android:name=".LocationService"/>
</application>
Issue is that you need to start the service from some activity. Service will not be started automatically. To start the service create an activity. Lets say Activity A. Now in its layout lets say there is a button.
on click of button you need to start your service using startService(new Intent(this,MainActivity.class))
Now A should be declared in manifest as launcher activity.
You can not have application without launcher activity!!!
Because it needs a way to start your service..and here it does not have one..
Also you can not use any type of broadcast receiver like BOOT_COMPELETED to start your service because starting from android 3.0 your application should be launched at least once to receive any broadcast like that..
So it would be better if you have one launcher activity although u didn't require it..you can just start your service from that activity and finish it..
And as soon as your service starts you will have your chathead ready!!
I'm trying to acquire accelerometer data using an Android Wear app on a smartwatch (Samsung Gear Live). To acquire that data I use a service which listens to three components:
a SensorEventListener, where the onSensorChanged method triggers a SensorEventLoggerTask that stores the accelerometer data with timestamps in a file on the smartwatch
a System intent that listens to the battery
an Intent that listens button clicks on an activity. The activity is used to annotate the data, so I have an idea at what timestamp an (person)activity (running, eating, sleeping,...) was started:
This works fine and I can sample the data every (more or less) 5-6 ms. However this only works when the smartwatch is connected through adb or when the activity is active (to press a button). From the moment it is not connected anymore, there are gaps in the data. With gaps I mean that the time between two timestamps of accelerometer values is much larger than the 5-6 ms. Going to seconds... The gaps appear irregular. But when the activity becomes active (to press a button) or I connect the smartwatch to the adb, the values are gathered. It appears that the service is paused/sleeps/shut down, when the smartwatch is not active.
Below I post the code. The project consists of two classes WearableActivity and WearableService. Furthermore, I also show the Manifest. Allthough this is only prototyping code, any help in resolving the data gaps or suggestions to the code, would be greatly appreciated.
WearableActivity.java
public class WearableActivity extends Activity {
//Set strings and widgets
private static final String TAG = "WearableActivity";
private TextView mTextView;
private Button[] buttons;
private String[] strings;
#Override
protected void onCreate(Bundle savedInstanceState) {
//setscreen
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wearable);
//check if service is already running
if(this.check() == false)
this.startService(new Intent(this, WearableService.class));
Resources res = this.getResources();
strings = res.getStringArray(R.array.button_names);
buttons = new Button[strings.length];
final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
#Override
public void onLayoutInflated(WatchViewStub stub) {
mTextView = (TextView) stub.findViewById(R.id.text);
mTextView.setText("ActiMon_Store Started");
buttons[0] = (Button)stub.findViewById(R.id.button1);
buttons[1] = (Button)stub.findViewById(R.id.button2);
buttons[2] = (Button)stub.findViewById(R.id.button3);
buttons[3] = (Button)stub.findViewById(R.id.button4);
buttons[0].setText(strings[0]);
buttons[1].setText(strings[1]);
buttons[2].setText(strings[2]);
buttons[3].setText(strings[3]);
for(Button b : buttons)
b.setOnClickListener(btnListener);
}
});
}
//---create an anonymous class to act as a button click listener---
private OnClickListener btnListener = new OnClickListener()
{
public void onClick(View v)
{
Intent buttonIntent = new Intent("button_activity");
Button b = (Button)v;
buttonIntent.putExtra("time", Long.toString(System.currentTimeMillis()));
buttonIntent.putExtra("button", b.getText().toString());
sendBroadcast(buttonIntent);
Toast.makeText(getApplicationContext(),
"Event sent", Toast.LENGTH_LONG).show();
}
};
//Checks is the service WearableService already started
public boolean check(){
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE))
{
if ("com.example.WearableService"
.equals(service.service.getClassName()))
{
Log.i(TAG,"Service already running!");
return true;
}
}
Log.i(TAG,"Service already running!");
return false;
}
}
WearableService.java
public class WearableService extends Service implements SensorEventListener {
private PrintStream ps;
private PrintStream ps_bat;
private PrintStream ps_button;
private String androidpath;
private float[] gravity = new float[3];
private float[] linear_acceleration = new float[3];
private PowerManager pm;
private PowerManager.WakeLock wl;
private SensorManager mSensorManager;
private Sensor mAcceleroSensor;
//Create the service and register the listeners
#Override
public void onCreate(){
super.onCreate();
this.registerListeners();
}
//Registers the SensorManager, the listener to the battery and the intent
private void registerListeners(){
mSensorManager = (SensorManager)this.getSystemService(SENSOR_SERVICE);
mAcceleroSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this,mAcceleroSensor,SensorManager.SENSOR_DELAY_FASTEST);
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = this.registerReceiver(battery_receiver, ifilter);
this.registerReceiver(broadcastReceiver, new IntentFilter("button_activity"));
}
//Start service as at STICKY
#Override
public int onStartCommand(Intent intent, int flags, int startId){
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
this.getFile();
pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.ON_AFTER_RELEASE,"KeepCPUWorking");
wl.acquire();
return Service.START_STICKY;
}
//When sensor value has changed
public void onSensorChanged(SensorEvent event){
if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
//Perform a background task to store the data
new SensorEventLoggerTask().execute(event);
}
}
//Get handles to files where data has to be stored
public void getFile(){
androidpath = Environment.getExternalStorageDirectory().toString();
try{
ps = new PrintStream(new FileOutputStream(androidpath + "/data_acc.dat"));
ps_bat = new PrintStream(new FileOutputStream(androidpath + "/data_bat.dat"));
ps_button = new PrintStream(new FileOutputStream(androidpath + "/data_button.dat"));
} catch (Exception e){
e.printStackTrace();
}
}
//Create receiver that listens to Intents from the Battery
private BroadcastReceiver battery_receiver = new BroadcastReceiver(){
#Override
public void onReceive(Context arg0, Intent arg1) {
int bLevel = arg1.getIntExtra("level", -1); // gets the battery level
int bScale = arg1.getIntExtra("scale", -1);
ps_bat.println("" + System.currentTimeMillis() + ";" + bLevel + ";" + bScale);
}
};
#Override
public void onDestroy(){
if(wl.isHeld()) wl.release();
}
// For receiving the broadcast event of the buttons.
private BroadcastReceiver broadcastReceiver = new
BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String msg = intent.getStringExtra("button") + ";" + intent.getStringExtra("time");
ps_button.println(msg);
}
};
//Create a Task that logs events to a file
private class SensorEventLoggerTask extends AsyncTask<SensorEvent, Void, Void>{
#Override
protected Void doInBackground(SensorEvent... events) {
//Getting the event and values
SensorEvent event = events[0];
String msg = "" + event.values[0] + ";" + event.values[1] + ";" + event.values[2];
//constructing the the line
msg = "" + System.currentTimeMillis() + ";" + msg;
//writing to file
ps.println(msg);
return null;
}
}
}
Manifest.xml
`<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.wearabledemo"
android:versionCode="1"
android:versionName="1.0" >
<uses-feature android:name="android.hardware.type.watch" />
<uses-sdk
android:minSdkVersion="20"
android:targetSdkVersion="20" />
<uses-permission android:name="android.permission.BODY_SENSORS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.DeviceDefault" >
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity
android:name=".WearableActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:enabled="true"
android:name=".WearableService"
android:label="#string/app_name"
android:exported="true"
android:permission="android.permission.WAKE_LOCK" >
</service>
</application>
</manifest>`
I am trying to start a Service that implements SensorEventListener. I am getting an error in my logcat claiming:
android.content.ActivityNotFoundException:Unable to find explicit activity class
{com.devicemoved/com.devicemoved.ShakeWakeupService};
have you declared this activity in your AndroidManifest.xml?
My Service is declared in my manifest as shown:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.devicemoved"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.devicemoved.launcherGo"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.devicemoved.ShakeWakeupService" />
</application>
The Activity
public class ShakeWakeupService extends Service implements SensorEventListener {
private Context mContext;
SensorManager mSensorEventManager;
Sensor mSensor;
// BroadcastReceiver for handling ACTION_SCREEN_OFF.
public BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Check action just to be on the safe side.
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
Log.v("shake mediator screen off", "trying re-registration");
// Unregisters the listener and registers it again.
mSensorEventManager.unregisterListener(ShakeWakeupService.this);
mSensorEventManager.registerListener(ShakeWakeupService.this,
mSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
};
#Override
public void onCreate() {
super.onCreate();
Log.v("shake service startup", "registering for shake");
mContext = getApplicationContext();
// Obtain a reference to system-wide sensor event manager.
mSensorEventManager = (SensorManager) mContext
.getSystemService(Context.SENSOR_SERVICE);
// Get the default sensor for accel
mSensor = mSensorEventManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
// Register for events.
mSensorEventManager.registerListener(this, mSensor,
SensorManager.SENSOR_DELAY_NORMAL);
// Register our receiver for the ACTION_SCREEN_OFF action. This will
// make our receiver
// code be called whenever the phone enters standby mode.
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
registerReceiver(mReceiver, filter);
}
#Override
public void onDestroy() {
// Unregister our receiver.
unregisterReceiver(mReceiver);
// Unregister from SensorManager.
mSensorEventManager.unregisterListener(this);
}
#Override
public IBinder onBind(Intent intent) {
// We don't need a IBinder interface.
return null;
}
public void onShake() {
// Poke a user activity to cause wake?
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// not used right now
}
// Used to decide if it is a shake
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
return;
Log.v("sensor", "sensor change is verifying");
}
}
The only thing I could possibly think of is that I am suppose to declare a broadcast receiver since I am using it in my class but I am not sure how to do that in this instance because I am not extending Broadcastreceiver.
I am calling this class from an activity with a button.
Any help will be great Thank You
You can already declared the package in the manifest tag, you should only need the .ShakeWakeupService part. Also make sure there is an empty constructor available for the system to construct your service