আমার আসল উত্তরের জন্য নীচে দেখুন - সেই প্যাটার্নটি ভাল কাজ করেছে তবে সম্প্রতি আমি পরিষেবা / ক্রিয়াকলাপের যোগাযোগের জন্য আলাদা পদ্ধতির ব্যবহার শুরু করেছি:
- একটি সীমাবদ্ধ পরিষেবা ব্যবহার করুন যা ক্রিয়াকলাপটিকে পরিষেবাতে সরাসরি রেফারেন্স পেতে সক্ষম করে, সুতরাং এজেন্টগুলি ব্যবহার না করে সরাসরি কলগুলিকে অনুমতি দেয়।
অ্যাসিক্রোনাস অপারেশনগুলি সম্পাদন করতে আরএক্সজাভা ব্যবহার করুন।
যদি কোনও ক্রিয়াকলাপ না চলাকালীনও যদি পরিষেবার জন্য ব্যাকগ্রাউন্ড ক্রিয়াকলাপ চালিয়ে যাওয়া প্রয়োজন হয় তবে অ্যাপ্লিকেশন শ্রেণি থেকে পরিষেবাটিও শুরু করুন যাতে আনবাউন্ড হওয়া বন্ধ না হয়।
স্টার্ট সার্ভিস () / লোকালব্রডকাস্ট কৌশলটির তুলনায় এই পদ্ধতির মধ্যে আমি যে সুবিধাগুলি পেয়েছি তা হ'ল
- পার্সেবল বাস্তবায়নের জন্য ডেটা অবজেক্টগুলির প্রয়োজন নেই - এটি আমার পক্ষে বিশেষভাবে গুরুত্বপূর্ণ কারণ আমি এখন অ্যান্ড্রয়েড এবং আইওএসের মধ্যে কোড ভাগ করছি (রোবওএমএম ব্যবহার করে)
- আরএক্সজাভা ক্যানড (এবং ক্রস-প্ল্যাটফর্ম) শিডিয়ুলিং এবং ক্রমানুসারে অ্যাসিঙ্ক্রোনাস অপারেশনগুলির সহজ সংমিশ্রণ সরবরাহ করে।
- লোকালব্রোডকাস্ট ব্যবহারের চেয়ে এটি আরও দক্ষ হওয়া উচিত, যদিও আরএক্সবাভা ব্যবহারের ওভারহেড এটি ছাড়িয়ে যেতে পারে।
কিছু উদাহরণ কোড। প্রথম পরিষেবা:
public class AndroidBmService extends Service implements BmService {
private static final int PRESSURE_RATE = 500000; // microseconds between pressure updates
private SensorManager sensorManager;
private SensorEventListener pressureListener;
private ObservableEmitter<Float> pressureObserver;
private Observable<Float> pressureObservable;
public class LocalBinder extends Binder {
public AndroidBmService getService() {
return AndroidBmService.this;
}
}
private IBinder binder = new LocalBinder();
@Nullable
@Override
public IBinder onBind(Intent intent) {
logMsg("Service bound");
return binder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
Sensor pressureSensor = sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);
if(pressureSensor != null)
sensorManager.registerListener(pressureListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
if(pressureObserver != null) {
float lastPressure = event.values[0];
float lastPressureAltitude = (float)((1 - Math.pow(lastPressure / 1013.25, 0.190284)) * 145366.45);
pressureObserver.onNext(lastPressureAltitude);
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}, pressureSensor, PRESSURE_RATE);
}
@Override
public Observable<Float> observePressure() {
if(pressureObservable == null) {
pressureObservable = Observable.create(emitter -> pressureObserver = emitter);
pressureObservable = pressureObservable.share();
}
return pressureObservable;
}
@Override
public void onDestroy() {
if(pressureListener != null)
sensorManager.unregisterListener(pressureListener);
}
}
এবং একটি ক্রিয়াকলাপ যা পরিষেবার সাথে আবদ্ধ হয় এবং চাপের উচ্চতার আপডেটগুলি গ্রহণ করে:
public class TestActivity extends AppCompatActivity {
private ContentTestBinding binding;
private ServiceConnection serviceConnection;
private AndroidBmService service;
private Disposable disposable;
@Override
protected void onDestroy() {
if(disposable != null)
disposable.dispose();
unbindService(serviceConnection);
super.onDestroy();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.content_test);
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
logMsg("BlueMAX service bound");
service = ((AndroidBmService.LocalBinder)iBinder).getService();
disposable = service.observePressure()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(altitude ->
binding.altitude.setText(
String.format(Locale.US,
"Pressure Altitude %d feet",
altitude.intValue())));
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
logMsg("Service disconnected");
}
};
bindService(new Intent(
this, AndroidBmService.class),
serviceConnection, BIND_AUTO_CREATE);
}
}
এই ক্রিয়াকলাপের জন্য বিন্যাসটি হ'ল:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.controlj.mfgtest.TestActivity">
<TextView
tools:text="Pressure"
android:id="@+id/altitude"
android:gravity="center_horizontal"
android:layout_gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</layout>
সেবা চাহিদা একটি বাউন্ড ভ্রমণ ছাড়া পটভূমি চালানোর জন্য যদি পাশাপাশি অ্যাপ্লিকেশন ক্লাস থেকে শুরু করা যাবে OnCreate()ব্যবহার Context#startService()।
আমার আসল উত্তর (২০১৩ থেকে):
আপনার পরিষেবা: (নীচের উদাহরণ হিসাবে পরিষেবা হিসাবে সিওপিএ ব্যবহার করে)।
লোকালবারডকাস্টম্যানেজার ব্যবহার করুন। আপনার পরিষেবার অনকারেটে, সম্প্রচারক সেট আপ করুন:
broadcaster = LocalBroadcastManager.getInstance(this);
আপনি যখন কোনও কিছুর UI কে অবহিত করতে চান:
static final public String COPA_RESULT = "com.controlj.copame.backend.COPAService.REQUEST_PROCESSED";
static final public String COPA_MESSAGE = "com.controlj.copame.backend.COPAService.COPA_MSG";
public void sendResult(String message) {
Intent intent = new Intent(COPA_RESULT);
if(message != null)
intent.putExtra(COPA_MESSAGE, message);
broadcaster.sendBroadcast(intent);
}
আপনার ক্রিয়াকলাপে:
অনক্রিটটিতে শ্রোতা তৈরি করুন:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.copa);
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String s = intent.getStringExtra(COPAService.COPA_MESSAGE);
// do something here.
}
};
}
এবং এটি অন স্টার্টে নিবন্ধ করুন:
@Override
protected void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver((receiver),
new IntentFilter(COPAService.COPA_RESULT)
);
}
@Override
protected void onStop() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
super.onStop();
}