问题
I am not sure where/how I can run this service to work in background. I develop application which use a CountDownTimer. I found that I should create a CountDownTimer in Service.class and run a Service.class in MainActivity.class.
Why TextView doesn't show on my screen? I put this in OnCreate and onStartCommand. Next I try run this in MainActivity but without success.
I still try to implement my code to work this CountDownTimer properly in a background. On official Android website I see that they use a "Log.i" command to run this Foreground method. How can I use this in my code? Should I add this in Service.class?
Below is my code:
MainActivity:
Button btnStart, btnStop;
TextView textViewTime;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startService(View view)
{
Intent intent = new Intent(this,MyService.class);
startService(intent);
}
public void stopService(View view)
{
Intent intent = new Intent(this,MyService.class);
stopService(intent);
}
MyService:
Button btnStart, btnStop;
TextView textViewTime;
public String hms;
@Override
public void onCreate() {
btnStart = (Button) btnStart.findViewById(R.id.btnStart);
btnStop = (Button) btnStop.findViewById(R.id.btnStop);
textViewTime = (TextView) textViewTime.findViewById(R.id.textViewTime);
textViewTime.setText("00:01:30");
final CounterClass timer = new CounterClass(90000, 1000);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//startService(v);
timer.start();
}
});
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) { // create start a service
textViewTime.setText("00:01:30");
Toast.makeText(this, "Service Started...", Toast.LENGTH_LONG).show();
// timer.start();
//return START_STICKY; // return integer value
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() { // stop a service
Toast.makeText(this, "Service Destroyed...", Toast.LENGTH_LONG).show();
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) { // it's not needed but we must override this method
return null;
}
public class CounterClass extends CountDownTimer {
public CounterClass(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
@Override
public void onTick(long millisUntilFinished) {
long millis = millisUntilFinished;
hms = String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
System.out.println(hms);
textViewTime.setText(hms);
}
@Override
public void onFinish() {
textViewTime.setText("Completed.");
}
}
回答1:
Here is your solution was easy though :)
activity xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="in.ashish29agre.stackoverflow.sample.servicetimer.ServiceTimerActivity">
<TextView
android:id="@+id/status_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="TImer will start here" />
<Button
android:id="@+id/start_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="startService"
android:text="Start" />
<Button
android:id="@+id/stop_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="stopService"
android:text="Stop" />
</LinearLayout>
Java code
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import in.ashish29agre.stackoverflow.R;
public class ServiceTimerActivity extends AppCompatActivity {
TextView textViewTime;
private TimerStatusReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service_timer);
textViewTime = (TextView) findViewById(R.id.status_tv);
receiver = new TimerStatusReceiver();
}
@Override
protected void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, new IntentFilter(CountdownTimerService.TIME_INFO));
}
@Override
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
public void startService(View view) {
Intent intent = new Intent(this, CountdownTimerService.class);
startService(intent);
}
public void stopService(View view) {
Intent intent = new Intent(this, CountdownTimerService.class);
stopService(intent);
}
private class TimerStatusReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent != null && intent.getAction().equals(CountdownTimerService.TIME_INFO)) {
if (intent.hasExtra("VALUE")) {
textViewTime.setText(intent.getStringExtra("VALUE"));
}
}
}
}
}
service code
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.NotificationCompat;
import java.util.concurrent.TimeUnit;
import in.ashish29agre.stackoverflow.R;
public class CountdownTimerService extends Service {
public static final String TIME_INFO = "time_info";
private CounterClass timer;
@Override
public void onCreate() {
super.onCreate();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
timer = new CounterClass(90000, 1000);
timer.start();
Intent notificationIntent = new Intent(this, ServiceTimerActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentText("Counter down service")
.setContentIntent(pendingIntent).build();
startForeground(101, notification);
return START_NOT_STICKY;
}
@Override
public void onDestroy() {
timer.cancel();
super.onDestroy();
Intent timerInfoIntent = new Intent(TIME_INFO);
timerInfoIntent.putExtra("VALUE", "Stopped");
LocalBroadcastManager.getInstance(CountdownTimerService.this).sendBroadcast(timerInfoIntent);
}
public class CounterClass extends CountDownTimer {
public CounterClass(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
@Override
public void onTick(long millisUntilFinished) {
long millis = millisUntilFinished;
String hms = String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
System.out.println(hms);
Intent timerInfoIntent = new Intent(TIME_INFO);
timerInfoIntent.putExtra("VALUE", hms);
LocalBroadcastManager.getInstance(CountdownTimerService.this).sendBroadcast(timerInfoIntent);
}
@Override
public void onFinish() {
Intent timerInfoIntent = new Intent(TIME_INFO);
timerInfoIntent.putExtra("VALUE", "Completed");
LocalBroadcastManager.getInstance(CountdownTimerService.this).sendBroadcast(timerInfoIntent);
}
}
}
Forget to mention need to add service in manifest
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<service android:name=".sample.servicetimer.CountdownTimerService" />
</application>
回答2:
Firstly:
You have to write Broadcast Receiver in MainActivity.java and register it in oncreate() and unregister in onDetstroy().
Secondly
In Service in onTick() method you have to sendbroadcast() which will invoke onReceive() in MainActivity.java and then in onReceive method you can chage text of Textview of activity.
来源:https://stackoverflow.com/questions/34853271/how-to-set-service-startforeground-to-work-countdowntimer-properly