I am running an android service. I wish to change a TextView text when I get expected result from the service. I have implemented an interface method to get a callback to change my textView. Interface abstract method runs well but cannot change the Textview text of my activity.
I have simplified sample code here
public class MainActivity extends Activity implements MyInterface {
TextView mTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.sample_text);
Button btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("Asim----", "Start service"); // print this line well
startService(new Intent(MainActivity.this, MyService.class));
}
});
}
#Override
public void testMe() {
Log.e("Asim----", "Hi"); // print this line well
mTextView.setText("New Text"); // Chrashes happens here
}
}
The MyService class here
public class MyService extends Service {
#Override
public void onCreate() {
//super.onCreate();
Log.e("test1------", "onCreate"); // print this line well
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("test2------", "onStartCommand"); // print this line well
MyInterface mi = new MainActivity();
mi.testMe();
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
mTextView should be null you have to find it in this method
#Override
public void testMe() {
Log.e("Asim----", "Hi"); // print this line well
mTextView = (TextView) findViewById(R.id.sample_text);
mTextView.setText("New Text"); // Chrashes happens here
}
Try it once.
you need to pass Activity in your interface as well
#Override
public void testMe(Activity actvity) {
Log.e("Asim----", "Hi"); // print this line well
mTextView = (TextView) activity.findViewById(R.id.sample_text);
mTextView.setText("New Text"); // Chrashes happens here
}
Related
This is a test activity when the button is pressed the textToSpeech works just fine, but it wont work when the function playString() is called, playString() is being called from the onCreate() of this TestActivity.
public class TestActivity extends Activity {
TextToSpeech textToSpeech;
EditText editText;
Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
editText=(EditText)findViewById(R.id.editText);
button=(Button)findViewById(R.id.button);
textToSpeech=new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR) {
textToSpeech.setLanguage(Locale.UK);
}
}
});
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String sentence = "Testing String";
textToSpeech.speak(sentence, TextToSpeech.QUEUE_FLUSH, null);
}
});
playString();
}
public void playString(){
String sentence = "Testing String";
textToSpeech.speak(sentence, TextToSpeech.QUEUE_FLUSH, null);
}
public void onPause(){
if(textToSpeech !=null){
textToSpeech.stop();
textToSpeech.shutdown();
}
super.onPause();
}
}
From documentation:
TextToSpeech instance can only be used to synthesize text once it has completed its initialization.
Initialization may take long time (on my device it's take ~30 seconds), so you can't use handler with some random delay.
Instead, you can place playString() in onInit block right after textToSpeech.setLanguage(Locale.UK);, so string will be played when it can be played.
Please use below code in oncreate method to call the texttospeech:
textToSpeech = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
textToSpeech.setLanguage(Locale.UK);
}
}
});
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 100ms
String sentence = "Testing String";
textToSpeech.speak(sentence, TextToSpeech.QUEUE_FLUSH, null);
}
}, 500);
My task is a call service in the RecyclerView when user click on switcher. My service is CountDownTimer work on background. And I dont know how call service from my holder.
I have error:
Non-static method 'startServiceTimer()' cannot be referenced from a
static contex
And I need to enable multiply countDownTimer`s in my service, can you help me with it?
My Holder
class SiteHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener{
CardView cardView;
TextView sitename;
ImageView sitePhoto;
SwitchCompat switchNotify;
TextView textDate;
LinearLayout linearCard;
CountDownTimer t;
SiteHolder(View itemView) {
super(itemView);
cardView = itemView.findViewById(R.id.cardView);
sitename = itemView.findViewById(R.id.site_name);
sitePhoto = itemView.findViewById(R.id.site_photo);
switchNotify = itemView.findViewById(R.id.notificationSwitcher);
textDate = itemView.findViewById(R.id.textDate);
linearCard = itemView.findViewById(R.id.linearCard);
switchNotify.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (b){
t = new CountDownTimer(finish, tick) {...}.start(); //my local timer in recycler view
; MainActivity.startServiceTimer();
} else {
switchOff();
t.cancel();
}
}
});
startServiceTimer on MainActivity
protected void startServiceTimer(){
startService(new Intent(this, BroadcastService.class));
Log.d("BroadcastService", "Started service");
}
and my Service with random
public class BroadcastService extends Service {
private final static String TAG = "BroadcastService";
private final static String COUNTDOWN_BR = "package.countdown_br";
Intent bi = new Intent(COUNTDOWN_BR);
CountDownTimer cdt = null;
private int cnt_service = 0;
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "Starting service timer...");
cnt_service++;
Log.d(TAG, "Count service = " + cnt_service);
cdt = new CountDownTimer(30000, 1000) {
#Override
public void onTick(long l) {
Log.d(TAG, "Countdown timer seconds reamaning: " + l/1000);
bi.putExtra("countdown", l);
sendBroadcast(bi);
}
#Override
public void onFinish() {
Log.d(TAG, "FIRST timer finished.");
}
}.start();
}
#Override
public void onDestroy() {
cdt.cancel();
Log.d(TAG, "Timer cancelled");
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
cnt_service++;
Log.d(TAG, "Calling onStart command");
Log.d(TAG, "Count service = " + cnt_service);
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Sorry for this question, I am only learn this:)
You should implement Listener pattern here. Your activity will be listening to 'startTimer' event from recyclerview.
Do following:
First, declare Interface:
public interface TimerStarter {
void startTimer();
}
Pass this interface to yours RecyclerViewAdapter & ViewHolder consturctors and save it to local variable.
public class MyRvAdapter extends RecyclerViewAdapter<SiteHolder> {
private TimerStarter starter;
public MyRvAdapter(TimerStarter timerStarter) {
starter = timerStarter;
}
// Your code
// Do not forget to pass TimerStarter to SiteHolder via consturctor
}
class SiteHolder extends RecyclerView.ViewHolder implements
View.OnClickListener, View.OnLongClickListener{
... // Your fields
private TimerStarter starter;
SiteHolder(View itemView, TimerStarter timerStarter) {
starter = timerStarter;
}
// You can call starter.startTimer() where nesessary
}
Next, implement this interface in your activity
public class MainActivity extends Activity implements TimerStarter {
... // Your methods here
#Override
public void onCreate(Bundle savedInstanceState) {
... // Instructions
// this = TimerStarter
RecyclerViewAdapter adapter = new YourAdapter(this)
... // etc
}
#Override
public void startServiceTimer(){ // Make method public
startService(new Intent(this, BroadcastService.class));
Log.d("BroadcastService", "Started service");
}
... // Other methods
}
i have following problem:
I've made a simple android app that adds 1 to an integer every 1000 ms using a handler, and then display this integer.
The problem is that when i start another activity the same thing happens, which would be fine, if that was intended. The mentioned function is not called in the new activity and yet it seems to be. Please look over my code and show me where it went wrong..
MainActivity:
public class MainActivity extends ActionBarActivity {
protected TextView text;
protected int position;
private Handler handler = new Handler();
private int i = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.text);
position=0;
SetButtonCLickListener();
counter();
}
protected void SetButtonCLickListener() {
Button btn = (Button) findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SwitchActivity();
}
});
}
private void counter() {
handler.removeCallbacks(count);
handler.postDelayed(count, 1000);
}
private Runnable count = new Runnable() {
public void run() {
i++;
text.setText("Count: " + i);
handler.postDelayed(count, 1000);
}
};
protected void SwitchActivity() {
if (position == 1) {
finish();
} else {
Intent intent = new Intent(this, MainActivity2.class);
startActivity(intent);
}
}
}
SecondActivity
public class MainActivity2 extends MainActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_activity2);
text = (TextView) findViewById(R.id.text);
SetButtonCLickListener();
position=1;
}
}
MainActivity2 has an onCreate() method. In the onCreate() method, you call super.onCreate(), which triggers the MainActivity implementation of onCreate(). The MainActivity implementation of onCreate() is where you are starting your counter thing, via its call to the counter() method. Hence, when MainActivity2 starts up, its onCreate() calls MainActivity's onCreate(), which calls counter().
My guess is that MainActivity2 should inherit from Activity, not from MainActivity.
Hi!
I have a service that should be playing an audio file when it is started from an activity (by a click on the button). The problem is though, the service won't start when i click the required button in my activity.
Service class (with imports and some other methods omitted):
public class ClockService extends Service {
MediaPlayer myMediaPlayer;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
myMediaPlayer = MediaPlayer.create(this, R.raw.audio);
myMediaPlayer.setLooping(true);
}
#Override
public void onStart(Intent intent, int startid) {
myMediaPlayer.start();
}
}
The activity it is called from:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startButton = (Button) findViewById(R.id.startButton);
startButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
startService(new Intent(getBaseContext(), ClockService.class));
}
});
}
}
I've struggled with it for an hour already, and i can't see what's wrong.
u got problem on below code line.u cant use this for context inside service.u need to pass context of mainactivity to service to get mediaplayer instance inside service.
myMediaPlayer = MediaPlayer.create(this, R.raw.audio);//wrong one
The problem is how you started the service
Change this line to startservice(new intent(mainactivity.this, clockservice));
here is a link you can refer to.
I am doing some investigations with the GoogleTV and a Android tablet. I have managed to make an android application that can send control messages to the google tv from the main Activity, what I am trying to do is launch a new activity from the main Activity and continue using the AnymoteClientService Service with the new activity. In my main activity I get an anymoteSender handle which I use to send KeyEvent messages to the google tv, how do I transfer this to the new activity (SlidepuzzleActivity)? I could instantiate it all again, but that would mean having to go through the whole pairing process again.
From the code below you will see that I have an anymoteSender in my SlidepuzzleActivity class, this will throw an error, but illustrates where I need to reuse that variable.
Code:
MainActivity.java:
package uk.co.myapp.gtvremote;
//imports removed for paste
public class MainActivity extends Activity implements ClientListener{
private AnymoteSender anymoteSender;
private TextView statusText;
protected AnymoteClientService mAnymoteClientService;
private static String statusPrefix = "Status: ";
private Context mContext;
private ProgressBar progressBar;
private Handler handler;
private TouchHandler touchPadHandler;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
progressBar = (ProgressBar) findViewById(R.id.a_progressbar);
progressBar.setVisibility(View.VISIBLE);
mContext = this;
ImageButton upArrowButton = (ImageButton) findViewById(R.id.upArrow);
ImageButton leftArrowButton = (ImageButton) findViewById(R.id.leftArrow);
ImageButton centreButton = (ImageButton) findViewById(R.id.centreButton);
ImageButton rightArrowButton = (ImageButton) findViewById(R.id.rightArrow);
ImageButton downArrowButton = (ImageButton) findViewById(R.id.downArrow);
ImageButton backButton = (ImageButton) findViewById(R.id.backButton);
ImageButton homeButton = (ImageButton) findViewById(R.id.homeButton);
Button testButton = (Button) findViewById(R.id.testButton);
upArrowButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
sendKeyEvent(KeyEvent.KEYCODE_DPAD_UP);
}
});
leftArrowButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
sendKeyEvent(KeyEvent.KEYCODE_DPAD_LEFT);
}
});
centreButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
sendKeyEvent(KeyEvent.KEYCODE_DPAD_CENTER);
}
});
rightArrowButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
sendKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT);
}
});
downArrowButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
sendKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN);
}
});
backButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
sendKeyEvent(KeyEvent.KEYCODE_BACK);
}
});
homeButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
sendKeyEvent(KeyEvent.KEYCODE_HOME);
}
});
testButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent myIntent = new Intent(MainActivity.this, SlidepuzzleActivity.class);
MainActivity.this.startActivity(myIntent);
}
});
handler = new Handler();
// Bind to the AnymoteClientService
Intent intent = new Intent(mContext, AnymoteClientService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
statusText = (TextView) findViewById(R.id.statusText);
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
/*
* ServiceConnection listener methods.
*/
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
mAnymoteClientService = ((AnymoteClientService.AnymoteClientServiceBinder) service)
.getService();
mAnymoteClientService.attachClientListener(MainActivity.this);
}
#Override
public void onServiceDisconnected(ComponentName name) {
mAnymoteClientService.detachClientListener(MainActivity.this);
mAnymoteClientService = null;
}
};
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void onConnected(AnymoteSender anymoteSender) {
if (anymoteSender != null) {
// Send events to Google TV using anymoteSender.
// save handle to the anymoteSender instance.
this.anymoteSender = anymoteSender;
attachTouchListnertoTouchPad();
} else {
statusText.setText(statusPrefix + "Connection attempt failed, cant find send handler");
//attempt to connect again?
//attemptToConnect();
}
// Hide the progressBar once connection to Google TV is established. Make the text display appropriately
handler.post(new Runnable() {
public void run() {
progressBar.setVisibility(View.INVISIBLE);
statusText.setText(statusPrefix + "Connected to GoogleTV");
}
});
}
#Override
public void onDisconnected() {
// show message to tell the user about disconnection.
statusText.setText(statusPrefix + "Disconnected");
// Try to connect again if needed. This may be need to be done via button
attemptToConnect();
this.anymoteSender = null;
}
#Override
public void onConnectionError() {
// show message to tell the user about disconnection.
statusText.setText(statusPrefix + "Connection error encountered");
// Try to connect again if needed.
attemptToConnect();
this.anymoteSender = null;
}
#Override
protected void onDestroy() {
if (mAnymoteClientService != null) {
mAnymoteClientService.detachClientListener(this);
}
unbindService(mConnection);
super.onDestroy();
}
private void attachTouchListnertoTouchPad()
{
// Attach touch handler to the touchpad view
touchPadHandler = new TouchHandler(
findViewById(R.id.touchPad), Mode.POINTER_MULTITOUCH, anymoteSender);
}
public void attemptToConnect()
{
//stub to invoke connection attempt
}
private void sendKeyEvent(final int keyEvent) {
// create new Thread to avoid network operations on UI Thread
if (anymoteSender == null) {
Toast.makeText(MainActivity.this, "Waiting for connection",
Toast.LENGTH_LONG).show();
return;
}
anymoteSender.sendKeyPress(keyEvent);
}
}
SlidepuzzleActivity.java:
package uk.co.myapp.gtvremote;
//imports removed for paste
public class SlidepuzzleActivity extends Activity implements ClientListener{
private AnymoteClientService mAnymoteClientService;
private Context mContext;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.slidepuzzle);
mContext = this;
ImageButton piece1x1 = (ImageButton) findViewById(R.id.piece1x1);
ImageButton piece1x2 = (ImageButton) findViewById(R.id.piece1x2);
ImageButton piece1x3 = (ImageButton) findViewById(R.id.piece1x3);
ImageButton piece2x1 = (ImageButton) findViewById(R.id.piece2x1);
ImageButton piece2x2 = (ImageButton) findViewById(R.id.piece2x2);
ImageButton piece2x3 = (ImageButton) findViewById(R.id.piece2x3);
ImageButton piece3x1 = (ImageButton) findViewById(R.id.piece3x1);
ImageButton piece3x2 = (ImageButton) findViewById(R.id.piece3x2);
ImageButton piece3x3 = (ImageButton) findViewById(R.id.piece3x3);
Intent intent = new Intent(mContext, AnymoteClientService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
piece1x1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
private ServiceConnection mConnection = new ServiceConnection() {
/*
* ServiceConnection listener methods.
*/
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
mAnymoteClientService = ((AnymoteClientService.AnymoteClientServiceBinder) service)
.getService();
mAnymoteClientService.attachClientListener(SlidepuzzleActivity.this);
}
#Override
public void onServiceDisconnected(ComponentName name) {
mAnymoteClientService.detachClientListener(SlidepuzzleActivity.this);
mAnymoteClientService = null;
}
};
private void sendKeyEvent(final int keyEvent) {
// create new Thread to avoid network operations on UI Thread
if (anymoteSender == null) {
Toast.makeText(SlidepuzzleActivity.this, "Waiting for connection",
Toast.LENGTH_LONG).show();
return;
}
anymoteSender.sendKeyPress(keyEvent);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.slidepuzzle, menu);
return true;
}
#Override
public void onConnected(AnymoteSender anymoteSender) {
// TODO Auto-generated method stub
}
#Override
public void onDisconnected() {
// TODO Auto-generated method stub
}
#Override
public void onConnectionError() {
// TODO Auto-generated method stub
}
#Override
protected void onDestroy() {
if (mAnymoteClientService != null) {
mAnymoteClientService.detachClientListener(this);
}
unbindService(mConnection);
super.onDestroy();
}
}
Just published an update to AnymoteLibrary for this.
In your MainActivity call both bindService() (already) and startService() for AnymoteClientService. The reason behind calling startService() is to keep the service and its anymoteSender instance around so that other Activitys in the same app can use it.
In the second Activity, implement ClientListener ( if you want to get onDisconnected() callback) and bind to the service and attachClientListener(). To get the AnymoteSender instance, call AnymoteClientService.getAnymoteSender(). Note that it can return null if the connection to Google TV is lost.
When all Activitys are done using AnymoteSender, remember to call stopService() for AnymoteClientService.