I would like to pass callback to IntentService. Here are my current codes:
My callback interface
import android.os.Message;
public interface SampleCallback {
public void doSomethingFromCurrentThread();
public void doSomethingFromUIThread(final Message msg);
}
My IntentService
import android.app.IntentService;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class SampleCallbackIntentService extends IntentService {
private final String LOG_LOGCAT_TAG = "SampleCallbackIntentService";
private final SampleCallback _callback;
private Handler _handler;
public SampleCallbackIntentService(String name, SampleCallback callback) {
super(name);
_callback = callback;
}
#Override
public void onCreate() {
super.onCreate();
// initialize variables for pause & resume thread
_mPauseLock = new Object();
_mPaused = false;
_mFinished = false;
// initialize handler to switch to UI/Main thread
_handler = new Handler()
{
#Override
public void handleMessage(final Message msg)
{
_callback.doSomethingFromUIThread(msg);
}
};
}
private final int CALLBACK_MESSAGE = 1;
#Override
protected void onHandleIntent(Intent arg0) {
Log.i(LOG_LOGCAT_TAG, "loop started");
while (!_mFinished) {
// do stuff here
_callback.doSomethingFromCurrentThread();
// process and create the result to pass
String someResult = "some result here";
_handler.sendMessage(_handler.obtainMessage(CALLBACK_MESSAGE, someResult));
synchronized (_mPauseLock) {
while (_mPaused) {
try {
Log.i(LOG_LOGCAT_TAG, "loop paused");
_mPauseLock.wait();
Log.i(LOG_LOGCAT_TAG, "loop resumed");
} catch (InterruptedException e) {
Log.e(LOG_LOGCAT_TAG, "error occured on pause", e);
}
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(LOG_LOGCAT_TAG, "error occured on sleep", e);
}
}
Log.i(LOG_LOGCAT_TAG, "loop ended");
}
private Object _mPauseLock;
private boolean _mPaused;
private boolean _mFinished;
/**
* Call this on pause.
*/
public void pause() {
Log.i(LOG_LOGCAT_TAG, "pause() called");
synchronized (_mPauseLock) {
_mPaused = true;
}
}
/**
* Call this on resume.
*/
public void resume() {
Log.i(LOG_LOGCAT_TAG, "resume() called");
synchronized (_mPauseLock) {
_mPaused = false;
_mPauseLock.notifyAll();
}
}
}
Any guidance on how to pass my callback is appreciated.
You might be looking for a ResultReceiver. It implements Parcelable so you can pass it to an intent service.
Sorry for giving you an answer 4 years later.
Here's a good answer about notifying an activity from a service: Notify activity from service. As for me, Activity.createPendingResult() is a great way to call parent activity.
That's not actually a callback but AFAIK there's no good way to implement such a callback without bound service.
Related
I am writing an Android app to print text on a bluetooth thermal printer.
Here is the complete code
The app works fine in the debug mode but when I generate a signed APK and install it on the device, it does not respond at all.
I have tried different solution suggested on stackoverflow but non of them worked.
This is my main activity
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.lvrenyang.io.IOCallBack;
import java.lang.ref.WeakReference;
public class MainActivity extends AppCompatActivity {
private Handler mHandler; // Our main handler that will receive callback notifications
// #defines for identifying shared types between calling functions
private final static int REQUEST_ENABLE_BT = 1; // used to identify adding bluetooth names
private static String TAG = "MAIN_ACTIVITY";
private Activity activity;
private Button btnConnect;
private String name = "MTP-II";
private String mac_address = "02:15:44:31:49:05";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Get the activity
this.activity = this;
//Button from the XML view
btnConnect = findViewById(R.id.btnConnect);
//Start the Init Work Service Async task
new InitWorkService().execute();
//Set onClickListener for test print button
btnConnect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
//Check if name and address are set
if (name != "null" && mac_address != "null" && mac_address.contains(":")) {
if (!WorkService.workThread.isConnected()) {
WorkService.workThread.connectBt(mac_address);
//Sleep for 3 seconds
try {
Thread.sleep(3000);
} catch (Exception e) {
}
}
//Check if connected
if (WorkService.workThread.isConnected()) {
//Collect data in background Thread
new PrintData().execute();
} else {
Toast.makeText(activity, Global.toast_notconnect, Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(activity, "Please setup printer first!", Toast.LENGTH_LONG).show();
}
}
catch(Exception e){
Log.e(TAG, e.getMessage(), e.fillInStackTrace());}
}
});
}
/**
* Background Async Task
* */
private class InitWorkService extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected String doInBackground(String... args){
try{
WorkService.cb = new IOCallBack() {
public void OnOpen() {
if (null != mHandler) {
Message msg = mHandler.obtainMessage(Global.MSG_IO_ONOPEN);
mHandler.sendMessage(msg);
}
}
public void OnClose() {
if (null != mHandler) {
Message msg = mHandler.obtainMessage(Global.MSG_IO_ONCLOSE);
mHandler.sendMessage(msg);
}
}
};
}
catch(Exception e){
Log.e(TAG, e.getMessage(), e.fillInStackTrace());
}
return null;
}
protected void onPostExecute(String file_url){
try {
mHandler = new MHandler(MainActivity.this);
WorkService.addHandler(mHandler);
if (null == WorkService.workThread) {
Intent intent = new Intent(activity, WorkService.class);
startService(intent);
}
}
catch (Exception e) {
Log.e(TAG, e.getMessage(), e.fillInStackTrace());
Toast.makeText(activity, "Unable to initiate the WorkService!", Toast.LENGTH_LONG).show();
}
}
}
/**
* Background Async Task
* */
class PrintData extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected String doInBackground(String... args){
try{
int nTextAlign=1;
String text = "Test message!\r\n\r\n\r\n";
String encoding = "UTF-8";
byte[] hdrBytes = {0x1c, 0x26, 0x1b, 0x39, 0x01};
Bundle dataAlign = new Bundle();
Bundle dataTextOut = new Bundle();
Bundle dataHdr = new Bundle();
dataHdr.putByteArray(Global.BYTESPARA1, hdrBytes);
dataHdr.putInt(Global.INTPARA1, 0);
dataHdr.putInt(Global.INTPARA2, hdrBytes.length);
dataAlign.putInt(Global.INTPARA1, nTextAlign);
dataTextOut.putString(Global.STRPARA1, text);
dataTextOut.putString(Global.STRPARA2, encoding);
WorkService.workThread.handleCmd(Global.CMD_POS_WRITE,dataHdr);
WorkService.workThread.handleCmd(Global.CMD_POS_SALIGN,dataAlign);
WorkService.workThread.handleCmd(Global.CMD_POS_STEXTOUT,dataTextOut);
}catch(Exception e){
Log.e(TAG, e.getMessage(), e.fillInStackTrace());
}
return null;
}
protected void onPostExecute(String file_url){}
}
#Override
protected void onUserLeaveHint()
{
Log.d("onUserLeaveHint","Home button pressed");
super.onUserLeaveHint();
//Unregister bluetooth receiver
try{unregisterReceiver(bluetoothReceiver);}catch(Exception e){}
//Disconnect bt connection
try{WorkService.workThread.disconnectBt();}catch(Exception e){}
// remove the handler
try{WorkService.delHandler(mHandler);}catch(Exception e){}
mHandler = null;
}
/**
* Broadcast receiver for bluetooth state changes
*/
private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent)
{
final String action = intent.getAction();
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED))
{
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,BluetoothAdapter.ERROR);
switch (state)
{
case BluetoothAdapter.STATE_OFF:
// closeConnection();//Close on going connection and disable button
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
break;
case BluetoothAdapter.STATE_ON:
break;
}
}
}
};
private static class MHandler extends Handler {
WeakReference<MainActivity> mActivity;
MHandler(MainActivity activity) {
mActivity = new WeakReference<>(activity);
}
#Override
public void handleMessage(Message msg) {
MainActivity theActivity = mActivity.get();
switch (msg.what) {
case Global.CMD_POS_STEXTOUTRESULT:
case Global.CMD_POS_WRITERESULT: {
int result = msg.arg1;
Toast.makeText(
theActivity,
(result == 1) ? Global.toast_success
: Global.toast_fail, Toast.LENGTH_SHORT).show();
Log.v(TAG, "Result: " + result);
break;
}
}
}
}
}
Does your app manifest declare permissions for bluetooth to be used?
https://developer.android.com/guide/topics/connectivity/bluetooth#Permissions
In order to use Bluetooth features in your application, you must declare two permissions. The first of these is BLUETOOTH. You need this permission to perform any Bluetooth communication, such as requesting a connection, accepting a connection, and transferring data.
The other permission that you must declare is either
ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION. A location permission
is required because Bluetooth scans can be used to gather information
about the location of the user. This information may come from the
user's own devices, as well as Bluetooth beacons in use at locations
such as shops and transit facilities.
If it only happens when u sign the apk, it looks like u have to update ur proguard rules, to exclude the printer lib clases or similar
One reason for the application not responding is that you stop the main thread for 3 seconds on line 60 in the click listener of the button.
Replace the onCreate() method with the code below
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Get the activity
this.activity = this;
//Button from the XML view
btnConnect = findViewById(R.id.btnConnect);
//Start the Init Work Service Async task
new InitWorkService().execute();
final ExecutorService es = Executors.newFixedThreadPool(1);
//Set onClickListener for test print button
btnConnect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
btnConnect.setEnabled(false);
es.submit(new Runnable() {
#Override
public void run() {
connect();
}
});
}
});
}
private void connect() {
try {
//Check if name and address are set
if (name != null && mac_address != null && mac_address.contains(":")) {
if (!WorkService.workThread.isConnected()) {
WorkService.workThread.connectBt(mac_address);
//Sleep for 3 seconds
try {
Thread.sleep(3000);
} catch (Exception e) {
}
}
//Check if connected
if (WorkService.workThread.isConnected()) {
//Collect data in background Thread
new PrintData().execute();
} else {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Toast.makeText(activity, Global.toast_notconnect, Toast.LENGTH_SHORT).show();
}
});
}
} else {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Toast.makeText(activity, "Please setup printer first!", Toast.LENGTH_LONG).show();
}
});
}
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e.fillInStackTrace());
}
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
btnConnect.setEnabled(true);
}
});
}
Now the connection part executes in a new thread and only the UI operations go on the main one.
Please note that this code is not the optimal solution because it does not take into account the activity lifecycle. If the activity is re-created while the thread sleeps, there is still a reference kept to the old activity. But it should be a starting point for you.
I am creating bound service for socket connection.Which means it is creating a long polling connection and listens my server.If user closes the app in task manager my service is killing i have no problem with this.But when user presses the back button I am calling activity.finish() method for close app.But with this method my service doesn't kill,it is still connected to socket server.
Is this normal ? And Could be this drain the battery ?
My service:
public class SocketService extends Service {
//you need constants to tell servise and activity what you are sending a message for
public static final int REGISTER_CHAT_ACTIVITY = 1;
public static final int MESSAGE_RECEIVED = 2;
final Messenger mMessenger = new Messenger(new IncomingHandler());
Messenger chat;
private Socket socket;
#Override
public void onCreate() {
try {
socket = IO.socket("ip");
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
}
}).on("connected", new Emitter.Listener() {
#Override
public void call(Object... args) {
}
}).on("message", new Emitter.Listener() {
#Override
public void call(Object... args) {
try {
chat.send(android.os.Message.obtain(null, MESSAGE_RECEIVED, args[0]));
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
//and add all the other on listeners here
socket.connect();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (socket != null) {
socket.disconnect();
socket.connect();
} else {
try {
socket = IO.socket("ip");
socket.connect();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
class IncomingHandler extends Handler {
#Override
public void handleMessage(android.os.Message msg) {
switch(msg.what){
case REGISTER_CHAT_ACTIVITY:
chat = msg.replyTo;
break;
}
}
}
public class LocalBinder extends Binder {
SocketService getService() {
return SocketService.this;
}
}
}
I had something similar a while ago i solved the issue by using shared preferences.(Note: I dont think it's the best answer but it solved my problem)
I saved in preferences a boolean to register when i dont need the service anymore but lost reference of it.
public class YourService extends Service {
private YourService serv;
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
serv = this;
Then Somehwere on your code that the service does frequently.
if(!sharedPref.getBoolean("TurnOffService", false)){
serv.stopSelf();
}
Hope it helps.
I want to stop my service went it complete its tasks. but service wont be stopped I override the onDestroy() but it dose not work. When service stops it will start a new activity.below is my code
DataService.java
package com.remote.synchronizer.haris;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.http.NameValuePair;
import android.app.Service;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class DataService extends Service {
boolean wifi,edge;
private Timer timer= new Timer();
SQLiteDatabase db;
String un,shop,city,date,order;
private SQLiteAdapter mySQLiteAdapter;
#Override
public void onCreate(){
super.onCreate();
mySQLiteAdapter = new SQLiteAdapter(this);
// this.stopSelf();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
final Handler mHandler = new Handler();
new Thread(new Runnable(){
#Override
public void run() {
Log.e("Service Started", "Successful");
while(true){
try{
Thread.sleep(10000);
mHandler.post(new Runnable() {
#Override
public void run() {
//Checking network connectivity
wifi=NetworkInfo.Wifi(DataService.this);
edge=NetworkInfo.EDGE(DataService.this);
if(wifi==true||edge==true)
{
int count=mySQLiteAdapter.getCCount();
int counter=0;
if(mySQLiteAdapter.getCCount()>0){
while(counter<count){
Log.e("Service Network", "Network is online");
int id=mySQLiteAdapter.getID();
List<NameValuePair> contacts=new ArrayList<NameValuePair>();
contacts=mySQLiteAdapter.getSingleRecord(id);
String url="http://10.0.2.2:3325/Product/Create?";
int response = 0;
try
{
response = CustomHttpClient.executeHttpPost(url, contacts);
if(response==200){
mySQLiteAdapter.delete_byID(id);
Log.e("Data Sent", "Response 200");
counter++;
}
else{
Log.e("Service Data", "Faield to upload data" );
}
}
catch (Exception e)
{
Log.e("Data Sending Error", e.toString());
e.printStackTrace();
}
}
}
//
Thread.currentThread().interrupt();
}
else
{
Log.e("Service Network", "Network is offline");
}
}
});
}
catch (InterruptedException e) {
Log.e("Data Sending Error", e.toString());
e.printStackTrace();
}
}
}
}).start();
return START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onDestroy() {
Log.v("SERVICE","Service killed");
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_SHORT).show();
//timer.cancel();
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
callIntent.setClass(this, com.remote.synchronizer.haris.Login.class);
startActivity(callIntent);
super.onDestroy();
}
}
somewhere i have read that don`t stop the service Android will stop itself. If it is like that then kindly edit my code and tell how can i start a new activity when my work finish. Do i need to stop the timer? Then the onStartCommand will stop and it will call the onDestroy? if yes then how can i stop the timer because i have tried but no success.
if you need a service to stop itself after it completed,you shoud use IntentService
onDestory() is used to release your resource,it will be called when the service is no longer used.
start activity like this:
final Handler mHandler = new Handler() {
public void HandleMessage(Message msg) {
if(msg.what == START_NEW_ACTIVITY) {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
callIntent.setClass(this, com.remote.synchronizer.haris.Login.class);
startActivity(callIntent);
}
}
};
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread() {
#Override
public void run() {
// do your job here
mHandler.sendEmptyMessage(START_NEW_ACTIVITY);
}
}.start();
}
To stop the service after your work has been finished simply call stopSelf() or stopSelf(startId).
If you want to start the activity after the service has been finished, Before calling the stopSelf() or stopSelf(startId), you should create the intent of the activity and set the flag mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);.
and start your activity by calling startActivity(intent)
First I will explain the current situation.
I've 2 different threads in 2 services(read from usb port service and make web requests service). I'm starting them in onCreate of my activity like:
serialServiceIntent = new Intent(NDKSerialActivity.this, SerialService.class);
startService(serialServiceIntent);
webServiceIntent = new Intent(NDKSerialActivity.this, RecordWebService.class);
startService(webServiceIntent);
There is nothing wrong with serial service but in RecordWebService when I make a request my gui stops until response comes.
The code is like that:
public class RecordWebService extends Service
{
public static final String SERVER_ADDRESS = "http://192.168.1.100:8080/MobilHM/rest";
private static final String TAG = RecordWebService.class.getSimpleName();
private RecordWebThread recordWebThread;
#Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
recordWebThread = new RecordWebThread(true);
recordWebThread.start();
}
#Override
public void onDestroy()
{
super.onDestroy();
Log.i(TAG, "RecordWebService Destroyed");
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
}
and
public class RecordWebThread extends Thread
{
private static final String TAG = RecordWebThread.class.getSimpleName();
public boolean always;
public RecordWebThread(boolean always)
{
this.always = always;
}
#Override
public void run()
{
PatientRecord patientRecord = new PatientRecord();
while (always)
{
RestClient restClient = new RestClient(RecordWebService.SERVER_ADDRESS + "/hello");
try
{
restClient.execute(RequestMethod.GET);
}
catch (Exception e1)
{
Log.e(TAG, "", e1);
}
Log.i(TAG, "Server Response Code:->" + restClient.getResponseCode());
Log.i(TAG, "Server Response:->" + restClient.getResponse());
try
{
sleep(4 * 1000);
}
catch (InterruptedException e)
{
Log.e(TAG, "Web service interrupted", e);
}
}
}
}
Also I've tried to remove sleep part and make the thread to run with timer and timer task like:
public void sendRecord()
{
scanTask = new TimerTask()
{
public void run()
{
handler.post(new Runnable()
{
public void run()
{
RestClient restClient = new RestClient(RecordWebService.SERVER_ADDRESS + "/hello");
try
{
restClient.execute(RequestMethod.GET);
}
catch (Exception e1)
{
Log.e(TAG, "", e1);
}
Log.i(TAG, "Server Response Code:->" + restClient.getResponseCode());
Log.i(TAG, "Server Response:->" + restClient.getResponse());
}
});
}
};
t.schedule(scanTask, 1000, 4000);
}
but no luck, my gui hangs when it comes to restClient.execute .
You can find RestClient.java # http://www.giantflyingsaucer.com/blog/?p=1462
How can I make my requests not block my gui thread?
Edit:
public void sendRecord()
{
scanTask = new TimerTask()
{
public void run()
{
RestClient restClient = new RestClient(RecordWebService.SERVER_ADDRESS + "/hello");
try
{
restClient.execute(RequestMethod.GET);
}
catch (Exception e1)
{
Log.e(TAG, "", e1);
}
Log.i(TAG, "Server Response Code:->" + restClient.getResponseCode());
Log.i(TAG, "Server Response:->" + restClient.getResponse());
}
};
t.schedule(scanTask, 1000, 4000);
}
Without handler, I call this in onCreate of my activity but still ui hanging.
Or you can use an IntentService which will handle the thread issues for you.
This is an example class:
public class MyService extends IntentService {
public MyService() {
super("MyService");
}
public MyService(String name) {
super(name);
}
#Override
protected void onHandleIntent(Intent arg0) {
//Do what you want
}
}
Then you just call:
Intent intent = new Intent(getApplicationContext(),MyService.class);
startService(intent);
Edit:
To repeat the same thing every 4 seconds you should do something like this:
PendingIntent serviceIntent= PendingIntent.getService(context,
0, new Intent(context, MyService.class), 0);
long firstTime = SystemClock.elapsedRealtime();
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
long intervalInSec = 4;
am.setRepeating(AlarmManager.ELAPSED_REALTIME, firstTime, intervalInSec*1000, serviceIntent)
;
In your code (2d version) happens next: You create thread, and it asks UI thread to do some net interaction. Just exclude handler.post(...) while executing request. Later you can use this for simple runnable for updating your UI with results of request.
Good Morning All,
I am currently buidling a media player for Android, and I am having trouble binding my player service to an Activity and pulling data from it. Bear with me...a lot of code follows.
My code---
Interface:
interface MyInterface{
void playFile( in String file);
void shuffle ();
String getPlayingData();
}
Service:
public class MyService extends Service {
public Context context;
public static String nowPlayingData = null;
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private final MyInterface.Stub mBinder = new MyInterface.Stub() {
public void playFile(String file) throws DeadObjectException {
//Song playing method working great!
}
public void shuffle()throws DeadObjectException {
//This method picks a random song and passes it to nowPlayingData string
}
public String getPlayingData() throws RemoteException {
return nowPlayingData;
}
};
#Override
public void onCreate() {
//Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
mp.setLooping(false); // Set looping
}
#Override
public void onDestroy() {
//Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
mp.stop();
}
#Override
public void onStart(Intent intent, int startid) {
//Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
}
}
Main Screen Activity, Shuffle Button:
Service is started in onCreate. When I click on the shuffle button it uses a method in the service to play a random song, thus setting the nowPlayingData string.
public class mainMenu extends Activity {
private MyInterface mInterface;
private ServiceToken mToken;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent startedSvc = new Intent(mainMenu.this, MyService.class);
boolean success = this.bindService(
startedSvc, svcConn, Context.BIND_AUTO_CREATE);
this.startService(startedSvc);
findViewById(R.id.shuffle).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
sInterface.shuffle();
} catch (RemoteException e) {
e.printStackTrace();
}
Intent play_screen = new Intent(MyPlayer.getContext(), NowPlaying.class);
startActivity(play_screen);
}
Player Activity:
I want to bind to the service, and pull nowPlayingData over using the interfaces getPlayingData method.
public class NowPlaying extends Activity implements OnClickListener {
public static String nowPlayingData = null;
MyInterface mInterface;
boolean isConnected = false;
RemoteServiceConnection conn = null;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.now_playing);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
Log.i("Log", "Player Loaded");
bindService();
getData();
fillView();
}
public void fillView(){
//This method needs the nowPlayingData string to update the view
}
class RemoteServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName className,
IBinder boundService ) {
mInterface = MyInterface.Stub.asInterface((IBinder)boundService);
isConnected = true;
Log.d("Now Playing", "Service Connected" );
}
public void onServiceDisconnected(ComponentName className) {
sInterface = null;
// updateServiceStatus();
isConnected = false;
Log.d( getClass().getSimpleName(), "onServiceDisconnected" );
getData();
}
};
private void bindService() {
if(conn == null) {
conn = new RemoteServiceConnection();
Intent i = new Intent();
i.setClassName("com.musicplayer.MyPlayer", "com.musicplayer.MyPlayer.MyService");
bindService(i, conn, Context.BIND_AUTO_CREATE);
Log.d( getClass().getSimpleName(), "bindService()" );
} else {
Toast.makeText(NowPlaying.this, "Cannot bind - service already bound", Toast.LENGTH_SHORT).show();
}
}
private void getData() {
if(conn == null) {
Log.i("getData", "No Connection");
} else {
try {
String data = mInterface.getPlayingData();
Log.i("Data Recieved", data);
Log.d( getClass().getSimpleName(), "invokeService()" );
} catch (RemoteException re) {
Log.e( getClass().getSimpleName(), "RemoteException" );
}
}
}
}
I have been studying many examples online, and perhaps my mish-mash of attempts has caused this to not work. My code works all the way through to binding the service, but OnServiceConnected is never called, and conn remains null.
Any help you guys can provide is greatly appreciated.
Thanks,
Josh
Android will not make re-entrant event calls to your activity, so onServiceConnected can't be called until onCreate has returned