So after 2-3 hours of failures i finally got my remote service to work somehow but it's acting real strange.
I'm using AIDL to send mediaPath string to my service and it starts playing music just fine, but the onStartCommand never gets called and the Service entry in Apps doesn't have the label/description I set in the manifest file. [http://i50.tinypic.com/344p349.png]
Also the Service terminates if I terminate the main Activity process, although it resides in a separate process. Is this how it's supposed to be? [http://i49.tinypic.com/16hpa86.png]
And I never get the "Service disconnected" Log which should happen when Service gets unbound from Activity.
Service code:
package com.example.randomserviceshitnot;
import java.io.IOException;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class MojPrviServis extends Service {
private final Servis.Stub binder = new Servis.Stub() {
public void execute(String mediaPath) throws RemoteException {
MediaPlayer mp = new MediaPlayer();
try {
mp.setDataSource(mediaPath);
mp.prepare();
} catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) {
e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace();
} catch (IOException e) { e.printStackTrace(); }
mp.start();
}
};
public void onCreate() {
super.onCreate();
Log.d("Filip", "Service onCreate called.");
}
public IBinder onBind(Intent intent) {
return binder;
}
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("Filip ", "Service onStart called.");
return START_STICKY;
}
}
Activity code:
package com.example.randomserviceshitnot;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class MainActivity extends Activity {
private Servis mBoundService;
private boolean mIsBound = false;
private static final String mediaPath = Environment.getExternalStorageDirectory().toString()+"/Music/Art Of The Dress(Archie Remix).mp3";
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("Filip ", "Service connected.");
mBoundService = Servis.Stub.asInterface(service);
try {
mBoundService.execute(mediaPath);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void onServiceDisconnected(ComponentName name) {
Log.d("Filip ", "Service disconnected.");
mBoundService = null;
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onStart() {
super.onStart();
doBindService();
}
void doBindService() {
Intent s = new Intent();
s.setAction("remote.servis");
bindService(s, mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
#Override
protected void onDestroy() {
super.onDestroy();
doUnbindService();
}
public void onPause() {
super.onPause();
doUnbindService();
}
void doUnbindService() {
if(mIsBound) {
unbindService(mConnection);
mIsBound=false;
}
}
}
AIDL:
package com.example.randomserviceshitnot;
interface Servis {
void execute(String s);
}
Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.randomserviceshitnot"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MojPrviServis"
android:label="#string/servis_koji_notifikuje"
android:description="#string/proces_desc"
android:icon="#drawable/ic_launcher"
android:process=":dep" >
<intent-filter>
<action android:name="remote.servis" />
</intent-filter>
</service>
</application>
</manifest>
http://developer.android.com/guide/components/services.html
Read the documentation of onStartCommand() and onBind()
When you call bindService() onStartCommand() is NOT called. But onBind() is called.
Also the service terminates if all the clients exited if the service was stared with bindservice().
For playing music you should use startService() instead of bind. If service is started this way then it does not stop when client exists. It has to stop itself when done.
Related
I have created two different Android applications. One contains a Service and the other one the Activity which binds the Service. This works well on all devices expected one. On the problematic device runs Android 6.0.1. On all other tested devices running Android 6 there are no problems. Same for devices with newer and older versions.
With packageManager.getPackageInfo("com.example.myexampleservice", 0) I checked that the service APK is installed.
My Activity class, which binds the Service (MainActivity.java, 1. project):
package com.example.myexampleactivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
final static int MSG_SAY_HELLO = 1;
Messenger mService = null;
boolean mBound;
TextView textView;
Button button;
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
mService = new Messenger(service);
mBound = true;
button.setText("Send Message");
textView.setText("Everything is fine. You can press the button to send a message.");
}
#Override
public void onServiceDisconnected(ComponentName className) {
mService = null;
mBound = false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
textView = findViewById(R.id.text_view);
button = findViewById(R.id.button);
textView.setText("Press the button to bind the service.");
button.setText("Bind service");
}
#Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mConnection);
mBound = false;
button.setText("Bind service");
}
}
public void onClickButton(View v) {
if (!mBound) {
Intent intent = new Intent("com.example.myexampleservice.SERVICE");
intent.setPackage("com.example.myexampleservice");
if (getApplicationContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) {
textView.setText("Everything is fine.");
} else {
// This happens only on one device. Why???
textView.setText("bindService(...) returns false. The following message is probably shown in the logcat:\n\n" +
"I BackgroundManagerService package not in whitelist com.example.myexampleservice\n" +
"I BackgroundManagerService not whitelist service Intent { act=com.example.myexampleservice.SERVICE pkg=com.example.myexampleservice }\n" +
"I BackgroundManagerService skipService Intent { act=com.example.myexampleservice.SERVICE pkg=com.example.myexampleservice } because of activity not started!");
}
} else {
Message msg = Message.obtain(null, MSG_SAY_HELLO, 0, 0);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}
My Service (MyExampleService.java, 2. project):
package com.example.myexampleservice;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.widget.Toast;
public class MyExampleService extends Service {
static final int MSG_SAY_HELLO = 1;
static class IncomingHandler extends Handler {
private Context applicationContext;
IncomingHandler(Context context) {
applicationContext = context.getApplicationContext();
}
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(applicationContext, "hello!", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
Messenger mMessenger;
#Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
mMessenger = new Messenger(new IncomingHandler(this));
return mMessenger.getBinder();
}
}
And the AndroidManifest of the Service application (AndroidManifest, 2. project):
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myexampleservice">
<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">
<service android:name=".MyExampleService">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="com.example.myexampleservice.SERVICE" />
</intent-filter>
</service>
</application>
</manifest>
Only on the one device that doesn't work the method bindService(...) returns false. For this device, the Logcat shows the followoing:
I BackgroundManagerService package not in whitelist com.example.myexampleservice
I BackgroundManagerService not whitelist service Intent { act=com.example.myexampleservice.SERVICE pkg=com.example.myexampleservice }
I BackgroundManagerService skipService Intent { act=com.example.myexampleservice.SERVICE pkg=com.example.myexampleservice } because of activity not started!
I am helpless, because the application on all other devices runs without problems. The Google search does not return any results for these log messages. Has anyone seen these log messages before and knows what to do here? Does anyone have any idea how to fix this problem?
I have created a service which lives within a library. The library is then included in another project which attempts to launch the service. I am using AIDL to interact however when I attempt to connect to the service my onConnected method is never hit.
From the log files I can see the following error:
D/ActivityManager: bindService callerProcessName:com.something.services.dummyproject, calleePkgName: com.something.services.dummyproject, action: com.something.services.dummyservice.IDummyService
W/ActivityManager: Unable to start service Intent { act=com.something.services.dummyservice.IDummyService cmp=com.something.services.dummyproject/com.something.services.dummyservice.IDummyService } U=0: not found
D/ActivityManager: bindService callerProcessName:com.something.services.dummyproject, calleePkgName: com.something.services.dummyservice.service, action: null
W/ActivityManager: Unable to start service Intent { cmp=com.something.services.dummyservice.service/.DummyService } U=0: not found
The DummyService.java file is as follows:
package com.something.services.dummyservice.services;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.something.services.dummyservice.IDummyService;
public class DummyService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private final IDummyService.Stub mBinder = new IDummyService.Stub() {
#Override
public String dummyHello() throws RemoteException {
return "Hello";
}
#Override
public void exit() throws RemoteException {
stopSelf();
}
};
}
The DummyService Manifest is as follows:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.something.services.dummyservice">
<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">
<service
android:name=".services.DummyService"
android:exported="true"
android:label="#string/app_name"
tools:ignore="ExportedService" />
</application>
</manifest>
The IDummyService.aidl file is as follows:
// IDummyService.aidl
package com.something.services.dummyservice;
// Declare any non-default types here with import statements
interface IDummyService {
String dummyHello();
void exit();
}
I'm generating a .aar file with the above.
I've then included that library into my main project file.
The manifest in my main project is as follows:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.something.services.dummyproject">
<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"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
The MainActivity.java file is as follows:
package com.something.services.dummyproject;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.something.services.dummyservice.IDummyService;
import butterknife.Bind;
import butterknife.ButterKnife;
public class MainActivity extends AppCompatActivity {
private IDummyService mDummyService;
#Bind(R.id.btnStartService)
Button btnStartService;
#Bind(R.id.btnEndService)
Button btnEndService;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
btnStartService.setOnClickListener(startServiceOnClickListener);
btnEndService.setOnClickListener(endServiceOnClickListener);
}
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
mDummyService = IDummyService.Stub.asInterface(service);
dummyHello();
}
#Override
public void onServiceDisconnected(ComponentName className) {
mDummyService = null;
}
};
private final View.OnClickListener startServiceOnClickListener = new View.OnClickListener() {
#Override
public void onClick(final View completeButton) {
Intent intent = new Intent(MainActivity.this, com.something.services.dummyservice.IDummyService.class);
intent.setAction(IDummyService.class.getName());
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
};
private final View.OnClickListener endServiceOnClickListener = new View.OnClickListener() {
#Override
public void onClick(final View completeButton) {
exitService();
}
};
private void dummyHello() {
try {
String response = mDummyService.dummyHello();
Toast.makeText(getApplicationContext(), response, Toast.LENGTH_LONG);
} catch (RemoteException e) {
e.printStackTrace();
}
}
private void exitService() {
try {
if (mDummyService != null) {
mDummyService.exit();
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
The dummyProject also contains the exact same AIDL file. In both cases the AIDL file lives in an aidl folder which lives alongside the src\JAVA folder. That contains a package folder which contains the AIDL file.
Any help with identifying why I'm unable to connect to the service is very much appreciated!
I am trying to create sample application in android which could access the remote service already created in android.
Below are the code of my service, it's AIDL and sample application. Please note that I am trying to run it in android emulator.
My AIDL file
// IMyAidlInterface.aidl
package com.example.mmjoshi.binderservice;
// Declare any non-default types here with import statements
interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
int findFactorialService(int x);
}
My Service file
package com.example.mmjoshi.binderservice;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
/**
* Created by mmjoshi on 8/12/2015.
*/
public class MyService extends Service {
private final IBinder mBinder = new LocalBinder();
#Override
public IBinder onBind(Intent intent)
{
//return mBinder;
return new IMyAidlInterface.Stub(){
public int findFactorialService(int x) throws RemoteException
{
int fact =1;
for(int i=1;i<=x;i++)
{
fact = fact*i;
}
return fact;
//return 5;
}
};
}
public class LocalBinder extends Binder
{
public MyService getService()
{
return MyService.this;
}
}
/*public int findFactorial(int x)
{
int fact =1;
for(int i=1;i<=x;i++)
{
fact = fact*i;
}
return fact;
//return 5;
}*/
}
Service Manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mmjoshi.binderservice" >
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
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=".MyService" android:process=":remote"
android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="com.example.mmjoshi.binderservice.MyService.IMyAidlInterface"></action>
</intent-filter>
</service>
</application>
</manifest>
Another application which access this service
package secondndapp.service_client;
import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.example.mmjoshi.binderservice.IMyAidlInterface;
public class MainActivity extends Activity implements View.OnClickListener {
EditText etValue1, etValue2;
Button bAdd;
ServiceConnection AddServiceConnection;
protected IMyAidlInterface iMyAidlInterface;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etValue1 = (EditText)findViewById(R.id.txtinput);
bAdd = (Button)findViewById(R.id.btnCalc);
bAdd.setOnClickListener(this);
initConnection();
}
void initConnection() {
AddServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
iMyAidlInterface = IMyAidlInterface.Stub.asInterface((IBinder) service);
Toast.makeText(getApplicationContext(),
"Service Connected", Toast.LENGTH_SHORT)
.show();
Log.d("IRemote", "Binding is done - Service connected");
}
#Override
public void onServiceDisconnected(ComponentName name) {
iMyAidlInterface = null;
Toast.makeText(getApplicationContext(), "Service Disconnected",
Toast.LENGTH_SHORT).show();
Log.d("IRemote", "Binding - Service disconnected");
}
};
if (iMyAidlInterface == null) {
Intent it = new Intent("com.example.mmjoshi.binderservice.MyService");
it.setPackage("com.example.mmjoshi");
it.setAction("com.example.mmjoshi.binderservice.MyService.IMyAidlInterface");
it.setComponent(new ComponentName("com.example.mmjoshi", "com.example.mmjoshi.binderservice.MyService"));
// binding to remote service
startService(it);
Log.d("Service-MJ","Service is going to start");
bindService(it, AddServiceConnection, Service.BIND_AUTO_CREATE);
Log.d("Service-MJ", "Service is started");
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void onClick(View v)
{
int num = Integer.parseInt(etValue1.getText().toString());
Toast.makeText(getApplicationContext(), "num is " + num,
Toast.LENGTH_LONG).show();
int result = 0;
try {
result = iMyAidlInterface.findFactorialService(num);
} catch (RemoteException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(), "Result" + result,Toast.LENGTH_SHORT).show();
}
}
Now, first I run the Binder Service in emulator and then I run this application in emulator.
But I am getting this error: "java.lang.NullPointerException: Attempt to invoke interface method 'int com.example.mmjoshi.binderservice.IMyAidlInterface.findFactorialService(int)' on a null object reference"
Please help me, I am stuck with this since last 2 days.
Thanks in Advance.
Maulik
I am working on a larger project but have become stuck on a very simple element that is binding to an android service. My issue is that I cannot seem to bind to the service. No errors are being thrown at all when calling bindService() and I have used the internal debugger and manual tracing of print statements and I am still failing to understand what is causing this error. Any help appreciated! (This is especially irritating as it is largely C+P from the android development website yet still won't work!)
Main Activity:
package com.example.servicetest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
public class MainActivity extends Activity {
LocalService mService;
boolean mBound = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// START Activity
Intent intent = new Intent(this, BindingActivity.class);
startActivity(intent);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Binding Activity:
package com.example.servicetest;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.Toast;
import com.example.servicetest.LocalService.LocalBinder;
public class BindingActivity extends Activity {
LocalService mService;
boolean mBound = false;
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
System.out.println("End onServiceConnected");
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bind);
}
#Override
protected void onStart() {
super.onStart();
// Bind to LocalService
System.out.println("onStart called");
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
this.startService(intent);
}
#Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
/** Called when a button is clicked (the button in the layout file attaches to
* this method with the android:onClick attribute) */
public void onButtonClick(View v) {
if (mBound) {
// Call a method from the LocalService.
// However, if this call were something that might hang, then this request should
// occur in a separate thread to avoid slowing down the activity performance.
System.out.println("Button click");
int num = mService.getRandomNumber();
Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
System.out.println("" + num);
} else {
System.out.println("Not bound");
}
}
}
LocalService:
package com.example.servicetest;
import java.util.Random;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
public class LocalService extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
// Random number generator
private final Random mGenerator = new Random();
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
System.out.println("onBind called");
return mBinder;
}
/** method for clients */
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}
And finally the manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.servicetest"
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.example.servicetest.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.servicetest.BindingActivity"
android:label="#string/app_name" >
</activity>
</application>
</manifest>
I think you need to add your service in Mainfest.xml
<service android:name="LocalService" android:enabled="true"></service>
try it and feed me back
I have an Activity class, in which I have a static flag, let's say
public static volatile flag = false;
Then in the class, I start a thread, which checks the flag and do different things.
I also have a broadcastreceiver, which sets the flag to true or false.
I though volatile will force the flag to the most recent value. But I can see my broadcastreceiver sets the static flag to true, but my thread is still getting it as false.
Am I missing something basic here? Any help would be appreciated!
Simplified Code (Updated) - So the flag is supposed to change to true after one minute. But it never did. But message from broadcast receiver shows it has been change to true
TestappActivity.java:
package com.test;
import java.util.Calendar;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
public class TestappActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent0 = new Intent(this, TestService.class);
this.startService(intent0);
Intent intent = new Intent(this, TestReceiver.class);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
PendingIntent sender = PendingIntent.getBroadcast(this,
1, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Calendar slot = Calendar.getInstance();
int min = slot.get(Calendar.MINUTE);
slot.set(Calendar.MINUTE, min+1);
am.set(AlarmManager.RTC_WAKEUP, slot.getTimeInMillis(), sender);
}
}
TestService.java:
package com.test;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class TestService extends Service {
private static final String TAG = "TestService";
public static volatile boolean flag = false;
private MyTopThread mTopThread;
public TestService() {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
}
#Override
public void onDestroy() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
protect();
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
/**
* Run protection
*
*/
private void protect() {
mTopThread = new MyTopThread();
mTopThread.start();
}
private class MyTopThread extends Thread {
#Override
public void run() {
while (true) {
try {
Thread.sleep(150);
Log.d(TAG, "Flag is " + TestService.flag);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
TestReceiver.java:
package com.test;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class TestReceiver extends BroadcastReceiver {
final static private String TAG = "TestReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive is triggered ...");
TestService.flag = true;
Log.d(TAG, "flag is changed to " + TestService.flag);
}
}
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".TestappActivity"
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=".TestService" />
<receiver
android:name=".TestReceiver"
android:process=":remote" >
</receiver>
</application>
</manifest>
I think the problem is that you are running the receiver in its own process. From the docs for the android:process attribute of <receiver>:
If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed and the broadcast receiver runs in that process.
I think the receiver is modifying a process-local version of TestService.flag, not the one being used by TestService. Try removing the android:process attribute from the <receiver> tag in your manifest.
From this link
http://www.javamex.com/tutorials/synchronization_volatile.shtml
Essentially, volatile is used to indicate that a variable's value will
be modified by different threads.
I really hope your service thread is not this one (I don't see any other one):
private class MyTopThread extends Thread {
#Override
public void run() {
while (true) {
try {
Thread.sleep(150);
Log.d(TAG, "Flag is " + TestService.flag);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Because you have while(true) here, not while(!flag) as it should be.