问题
I'm writing my first Android app and it's supposed to count steps (via accelerometer, source code from http://www.gadgetsaint.com/android/create-pedometer-step-counter-android/)
So what do I have for now:
- MainActivity with three TextView fields (steps, bonuses, speed).
- Service where I detect steps and calculate distanse, bonus and speed.
This service is a Bound Service and it consist of three classes: MyService, MyServiceBinder and MyServiceConnection. I've done it as explained in Xamarin.Android documentation and example: https://github.com/xamarin/monodroid-samples/tree/master/ApplicationFundamentals/ServiceSamples/BoundServiceDemo.
The point is every time I have a step, I want to show this on MainActivity (update those textviews) in real time. And I don't understand how to do this in a proper way. Events? Broadcast reciever? I get messed with binding/connection, it's a new thing to me. Please help me to get it work! Any examples (Java is ok) would be very helpful.
Here is the source code (I've cleaned it up from extra code).
MainActivity.cs
public class MainActivity : Activity
{
//BOUND SERVICE: STEPSERVICE
MyServiceConnection myServiceConnection;
//UI
internal TextView textBonus, textSteps, textSpeed;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Main);
textBonus = FindViewById<TextView>(Resource.Id.textViewBonus);
textStep = FindViewById<TextView>(Resource.Id.textViewDistance);
textSpeed = FindViewById<TextView>(Resource.Id.textViewSpeed);
}
protected override void OnStart()
{
base.OnStart();
if (myServiceConnection == null)
{
myServiceConnection = new MyServiceConnection(this);
}
DoBindMyService();
}
private void DoBindMyService()
{
Intent serviceIntent = new Intent(this, typeof(MyService));
BindService(serviceIntent, myServiceConnection, Bind.AutoCreate);
}
protected override void OnDestroy()
{
//stop services!
base.OnDestroy();
}
private void UpdateUI()
{
RunOnUiThread(() =>
{
textBonus.Text = myServiceConnection.Binder.Service.Bonus;
textSteps.Text = myServiceConnection.Binder.Service.Steps;
textSpeed.Text = myServiceConnection.Binder.Service.Speed;
});
}
}
MyService.cs
[Service]
public class MyService : Service, IStepListener, ISensorEventListener
{
//counters
private int bonus;
public int Bonus
{
get { return bonus; }
set { bonus = value; }
}
private int steps = 0;
public int StepsT
{
get { return steps; }
set
{
steps = value;
}
}
private float speed = 0.0F;
public float Speed
{
get { return speed; }
set
{
speed = value;
}
}
public IBinder Binder { get; private set; }
public override IBinder OnBind(Intent intent)
{
this.Binder = new MyServiceBinder(this);
return this.Binder;
}
public override void OnCreate()
{
base.OnCreate();
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
return StartCommandResult.Sticky;
}
public void Step(long timeNs)
{
Steps++;
Bonus++;
Speed++;
}
public void OnAccuracyChanged(Sensor sensor, SensorStatus accuracy)
{
// We don't want to do anything here.
}
public void OnSensorChanged(SensorEvent e)
{
simpleStepDetector.UpdateAccel(e.Timestamp, e.Values[0], e.Values[1], e.Values[2]);
}
}
MyServiceConnection.cs
public class MyServiceConnection : Java.Lang.Object, IServiceConnection
{
MainActivity mainActivity;
public MyServiceConnection(MainActivity activity)
{
IsConnected = false;
Binder = null;
mainActivity = activity;
}
public bool IsConnected { get; private set; }
public MyServiceBinder Binder { get; private set; }
public void OnServiceConnected(ComponentName name, IBinder service)
{
Binder = service as MyServiceBinder;
IsConnected = this.Binder != null;
string message = "onSecondServiceConnected - ";
if (IsConnected)
{
message = message + " bound to service " + name.ClassName;
}
else
{
message = message + " not bound to service " + name.ClassName;
}
mainActivity.textSpeed.Text = message;
}
public void OnServiceDisconnected(ComponentName name)
{
IsConnected = false;
Binder = null;
}
}
MyServiceBinder.cs
public class MyServiceBinder : Binder
{
public MyServiceBinder(MyService service)
{
this.Service = service;
}
public MyService Service { get; private set; }
}
PS. This is my first question here. Excuse me if I've made something wrong.
回答1:
There are three ways to complete it.
- Broadcast
- Interface
- BindService
BindService
In your
MyServiceConnectionadd this:public MyService myService;and in your
OnServiceConnectedmethod add this underBinder = service as MyServiceBinder;:myService=Binder.Service; myService.SetActivity(mainActivity);In your
MyServiceclass add this (so you can getMainActivityinstance in your service):MainActivity mainActivity; public void SetActivity(MainActivity activity) { this.mainActivity = activity; }and add
mainActivity.UpdateUI();in yourStep(long timeNs)method, so you can update your UI.In your
MainActivityreplaceprivate void UpdateUI()withpublic void UpdateUI().
Interface
Add
IUpdateinterfacepublic interface IUpdate { void Update(); }In your
MyServiceadd this:IUpdate update; public void SetIUpdate(IUpdate update) { this.update = update; }and add
this.update.Update();in yourStep(long timeNs)method.Implement the
IUpdateinterface in yourMyServiceConnectionclass, so it will like this:public class MyServiceConnection : Java.Lang.Object, IServiceConnection,IUpdate { MainActivity mainAtivity; public MyServiceConnection(MainActivity activity) { IsConnected = false; Binder = null; mainActivity = activity; } public bool IsConnected { get; private set; } public MyServiceBinder Binder { get; private set; } public MyService myService; public void OnServiceConnected(ComponentName name, IBinder service) { Binder = service as MyServiceBinder; myService=Binder.Service; myService.SetIUpdate(this); //myService.SetActivity(mainActivity); IsConnected = this.Binder != null; string message = "onSecondServiceConnected - "; if (IsConnected) { message = message + " bound to service " + name.ClassName; } else { message = message + " not bound to service " + name.ClassName; } mainActivity.textSpeed.Text = message; } public void OnServiceDisconnected(ComponentName name) { IsConnected = false; Binder = null; } public void Update() { mainActivity.UpdateUI(); } }
Broadcast
This is what you have already known.
来源:https://stackoverflow.com/questions/47778017/how-to-update-activity-every-time-the-data-had-been-changed-in-service