我的应用程序使用相机,它显示相机预览,并在每个预览帧上将帧数据编码为base64格式,以调用我的远程Web服务。
由于产生帧的速度与消耗帧(调用Web服务)的速度不匹配,因此我考虑在服务中使用缓冲区(消息队列),因此我使用Messenger来绑定服务。
因此,我考虑使用该服务,并将其绑定到我的CameraActivity。默认情况下,服务在与UI线程相同的线程中运行,但是,我想在另一个线程中运行服务。我已经读过Service和Bound service,他们只是提到我可以在其他线程中运行该服务,但没有给出示例。
CameraActivity
public class CameraActivity extends AppCompatActivity implements Camera.PreviewCallback {
private Camera camera;
private CameraPreview preview;
int cnt = 0, RATE = 0;
private Messenger messenger;//use to communicate with CloudService
private boolean bound = false;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
messenger = new Messenger(service);
bound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
messenger = null;
bound = false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
camera = getCamera();
RATE = camera.getParameters().getPreviewFrameRate() / 5;
preview = new CameraPreview(this, camera);
FrameLayout layout = findViewById(R.id.camera_preview);
layout.addView(preview);
bindService(new Intent(this, CloudService.class), connection,
Context.BIND_AUTO_CREATE);
}
public static Camera getCamera() {
Camera camera = null;
try {
camera = Camera.open();
} catch (Exception e) {
e.printStackTrace();
}
return camera;
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (cnt == RATE) {
if (bound) {
Message message = Message.obtain(null, 0, data);
try {
messenger.send(message);
Log.d("activity", "send msg");
} catch (RemoteException e) {
e.printStackTrace();
}
}
cnt = 0;
}
cnt++;
}
protected void onStop() {
super.onStop();
if (bound){
unbindService(connection);
bound = false;
}
}
}
CloudService
private Thread thread;
private Messenger messenger;
public CloudService() {
Log.d("cloud service", "create");
thread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("cloud service", "thread running");
}
}
});
}
@Override
public IBinder onBind(Intent intent) {
messenger = new Messenger(new PreviewHandler(this));
return messenger.getBinder();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("cloud service", "start");
thread.start();
return START_STICKY;
}
@Override
public void onDestroy() {
thread.interrupt();
Log.d("cloud service", "destroy");
}
static class PreviewHandler extends Handler {
private CloudService service;
public PreviewHandler(CloudService service) {
this.service = service;
}
@Override
public void handleMessage(Message message) {
byte[] data = (byte[]) message.obj;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("message", "msg!!!");
}
}
}
如何在CloudService中正确使用线程?
答案 0 :(得分:0)
解决方案:一起使用HandlerThread
和Handler
完成任务。
public class CloudService extends Service {
private static final String TAG = "CloudService";
private HandlerThread handlerThread;
private PreviewHandler handler;
private Messenger messenger;
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
handlerThread = new HandlerThread("CloudService_HandlerThread");
handlerThread.start();
handler = new PreviewHandler(handlerThread.getLooper());
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
messenger = new Messenger(handler);
return messenger.getBinder();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
return START_STICKY;
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
handlerThread.quit();
}
static class PreviewHandler extends Handler {
PreviewHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message message) {
byte[] data = (byte[]) message.obj;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "handleMessage from thread " + Thread.currentThread().getName());
}
}
}