在后台服务运行? [英] Service run in background?

查看:117
本文介绍了在后台服务运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个应用程序,我要建有记录功能的功能。我做到这一点,在服务启动MediaRecorder对象:

 意向意图=新的意图(v.getContext(),RecordService.class);
信使送信=新使者(处理);
intent.putExtra(COUNT,基本);
intent.putExtra(信使信使);

。v.getContext()startService(意向);

//服务

// ...
mRecorder =新MediaRecorder();
// ...
 

现在我介绍了一个通知,这不得不让用户知道的情况是记录自己的东西,因为如果你去家里或打后退按钮,就必须继续录制。因此,如果你打的通知,你去返回到应用程序

这就是我挣扎,如果我点击的通知,我回去的应用程序,但一切都设置为初始状态(定时器又回来了00:00:00和我打录音键,而不是再次暂停按钮),我的完成,当然,它的保存记录的,而且我可以看到正在进行的计时器+停止按钮。注意:定时不是一个服务,现在..任何想法,我应该如何处理这个

修改

假如我关闭应用程序下,该服务仍然在运行。重新打开应用程序(因此活动在服务最初是从所谓的),我们可以做的:

 私人布尔isMyServiceRunning(){
        ActivityManager经理=(ActivityManager)myContext.getSystemService(Context.ACTIVITY_SERVICE);
        对于(RunningServiceInfo服务:manager.getRunningServices(Integer.MAX_VALUE的)){
            如果(MyService.class.getName()。等于(service.service.getClassName())){
                返回true;
            }
        }
        返回false;
    }
 

所以,我也稍微有盖的,但是,从该服务到该活动通过变量现在都没有了。看来,我在我的活动处理程序是不是重新打开活动后接他们?

 专用处理器处理器=新的处理程序(){
        公共无效的handleMessage(消息消息){

            // ..
            束束= message.getData();
            文件名= bundle.getString(文件名);
            tvFileName.setText(文件名);


            Log.e(文件名,转移+文件名);

        };
    };
 

//修改

片段:

 公共类LayoutOne扩展片段实现OnClickListener {

    //瓦尔
    @覆盖
    公共无效的onPause(){
        super.onPause();
        如果(mRecorder!= NULL){
            mRecorder.release();
            mRecorder = NULL;
        }

        如果(MPLAYER!= NULL){
            mPlayer.release();
            MPLAYER = NULL;
        }
    }

    私人处理程序处理程序=新的处理程序(){
        公共无效的handleMessage(消息消息){

            INT I = message.arg1;
            束束= message.getData();
            文件名= bundle.getString(文件名);
            tvFileName.setText(文件名);

            Log.e(处理器,成功与转移:+(Integer.toString(ⅰ)));
            Log.e(文件名,成功与转移:+文件名);
        };
    };

    @覆盖
    公共无效的onClick(视图v){

        开关(v.getId()){
        案例R.id.bRecord:

            如果(mStartRecording){
                mStartRecording = FALSE;
                意向意图=新的意图(v.getContext(),RecordService.class);

                信使送信=新使者(处理);
                intent.putExtra(信使信使);
                。v.getContext()startService(意向);


            } 其他 {
                mRecordButton.setText(记录);
                意图stopIntent =新的意图(v.getContext()
                        RecordService.class);

                尝试 {
                    。v.getContext()stopService(stopIntent);
                }赶上(例外五){
                    e.printStackTrace();

                }
                mStartRecording = TRUE;
            }

            打破;

        案例R.id.bStop:
            意图stopIntent =新的意图(v.getContext(),RecordService.class);
            。v.getContext()stopService(stopIntent);
            打破;

        }
    }

    公共静态片段的newInstance(上下文的背景下){
        LayoutOne F =新LayoutOne();
        返回F;
    }

    @覆盖
    公共查看onCreateView(LayoutInflater充气,容器的ViewGroup,捆绑savedInstanceState){
        根=(ViewGroup中)inflater.inflate(R.layout.layout_one,NULL);
        myContext = container.getContext();

        //按钮

        经理=(NotificationManager)myContext.getSystemService(Context.NOTIFICATION_SERVICE);
        返回根;
    }



    公共无效notifyMe(视图v){
        通知注=新的通知(R.drawable.ic_launcher,
                的getString(R.string.notificationbar),System.currentTimeMillis的());
        PendingIntent I = PendingIntent.getActivity(myContext,0,新的意向(
                myContext,ViewPagerStyle1Activity.class),0);

        note.setLatestEventInfo(myContext,的getString(R.string.app_name)
                的getString(R.string.notification),I);
        note.number = ++计数;
        note.vibrate =新长[] {500L,200L,200L,500L};
        note.flags | = Notification.FLAG_AUTO_CANCEL;

        mgr.notify(NOTIFY_ME_ID,请注意);
    }

    公共无效clearNotification(视图v){
        mgr.cancel(NOTIFY_ME_ID);
    }

    // /共享preFERENCES设置///
// ...

    私人无效initiatePopupWindow(){
        // ..
    }



    @覆盖
    公共无效onResume(){
        super.onResume();
        意向意图=新的意图(myContext,RecordService.class);
        myContext.startService(意向);
        myContext.bindService(意向,mServiceConnection,Context.BIND_AUTO_CREATE);
    }

    私人ServiceConnection mServiceConnection =新ServiceConnection(){
        @覆盖
        公共无效onServiceConnected(组件名名称,服务的IBinder){
            // TODO自动生成方法存根
             LocalBinder粘合剂=(LocalBinder)服务;
                为myService = binder.getService();
                //myService.setBound(true);
                initializeUI();

        }

        @覆盖
        公共无效onServiceDisconnected(组件名名){
            // TODO自动生成方法存根

        }
    };

    保护无效initializeUI(){
        // ..

        }

    }

    @覆盖
    公共无效的onDestroy(){
        // TODO自动生成方法存根
        myContext.unbindService(mServiceConnection);
    }

    @覆盖
    公共无效的onStop(){
        // TODO自动生成方法存根
        myContext.unbindService(mServiceConnection);
    }



}
 

//服务

 公共类RecordService延伸服务{

    //瓦尔

     公共类LocalBinder扩展粘合剂{
            RecordService的getService(){
                返回RecordService.this;
            }
        }

    @覆盖
    公共无效的onCreate(){
        Log.i(OnCreate中,服务的onCreate);
    }

    @覆盖
    公众诠释onStartCommand(意向意图,诠释标志,诠释startId){
        捆绑额外= intent.getExtras();
        如果(临时演员!= NULL){

            信使=(信使)extras.get(信使);
            数= Integer.toString(extras.getInt(COUNT));
            尝试 {
                消息消息=新的Message();
                INT ARG = 0;
                message.arg1 = ARG;

                mFileNamePass =测试;
                束束=新包();
                bundle.putString(文件名,mFileNamePass);
                message.setData(包);
                messenger.send(消息);
            }赶上(android.os.RemoteException E1){
                Log.w(的getClass()的getName(),异常发送消息,E1);
            }
        }
        其他 {
            Log.i(其他,没有找到临时演员);
        }

        可运行R =新的Runnable(){

            @覆盖
            公共无效的run(){
                checkIfFolderExists();
                串dateFull = calculateDate();
                mFileName = Environment.getExternalStorageDirectory()
                        .getAbsolutePath();
                mFileName + =test.3gp;

                mRecorder =新MediaRecorder();
                mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                mRecorder.setOutputFile(mFileName);
                mRecorder.setAudioEn codeR(MediaRecorder.AudioEn coder.AMR_NB);

                尝试 {
                    mRecorder prepare()。
                }赶上(IOException异常E){
                    Log.e(LOG_TAG,prepare()失败);
                }

                mRecorder.start();
                Log.i(服务,服务运行);

            }
        };

        线程t =新主题(R);
        t.start();
        返回RecordService.START_STICKY;
    }

    @覆盖
    公共无效的onDestroy(){

        可运行STO precord =新的Runnable(){

            @覆盖
            公共无效的run(){
                mRecorder.stop();
                mRecorder.release();
                mRecorder = NULL;

            }

        };
        主题STO precordThread =新主题(STO precord);
        STO precordThread.start();
        Log.i(服务,服务已停止);
        super.onDestroy();
    }

    @覆盖
    公众的IBinder onBind(意向意图){
        // TODO自动生成方法存根
        返回null;
    }



}
 

解决方案

首先,你并不需要检查,如果你的服务是由一些<$运行C $ C> ActivityManager 方法。如果你调用 startService()及和放大器; bindService() onResume(),Android是足够聪明,只是绑定到服务,如果它已经在运行,如果没有,它会创建服务经历它的正确的记录生命周期,然后绑定到它。

你可以做这里是这样的:

  @覆盖
公共无效onResume(){
    super.onResume();
    意向意图=新的意图(这一点,YourService.class);
    startService(意向);
    bindService(意向,mServiceConnection,Context.BIND_AUTO_CREATE);
}
 

现在,让我们说你的服务已经在运行,你想要得到它的正确的价值观。在你的 ServiceConnection的 onServiceConnected()办法(),你可以调用像的方法initializeUI()完成绑定时:

 私人ServiceConnection mServiceConnection =新ServiceConnection(){
    公共无效onServiceConnected(组件名的className,服务的IBinder){
        LocalBinder粘合剂=(LocalBinder)服务;
        为myService = binder.getService();
        myService.setBound(真正的);
        initializeUI();
    }

    公共无效onServiceDisconnected(组件名的className){
    }
};
 

而现在,你有为myService 变量指向你的服务的对象,你可以打电话给你的干将,喜欢 myService.getTimer() myService.isRecording()

 公共无效initializeUI(){
    timerTextview.setText(myService.getTime());
    someOtherUiElement.setText(myService.getSomething());
    如果(myService.isRecording())
        recordButton.setImageResource(R.drawable.pause);
} //等等...
 

顺便说一句,我不知道你是否还挣扎在保持你的服务运行时退出应用程序 如果你这样做,使用 startService(意向)将让你的服务运行,只要Android有足够的内存。您的必须的有一块code中,你可以叫 myService.stopService(),否则,服务将运行一个非常很长一段时间。

One of the functions of the app which I'm building had a record function. I do this by starting a MediaRecorder object in a service:

Intent intent = new Intent(v.getContext(), RecordService.class);
Messenger messenger = new Messenger(handler);
intent.putExtra("COUNT", basic);
intent.putExtra("MESSENGER", messenger);

v.getContext().startService(intent);

//service

//...
mRecorder = new MediaRecorder();
//...

Now I introduced a notification which had to let the user know what the status is of the recording itself because if you go the the home or hit the backbutton, it has to keep recording. Therefore, if you hit the notification, you go back to the app.

That is where I am struggling, if I click the notification, I go back to the app but everything is set to the initial state (Timer is back 00:00:00 and I can hit the record button again instead of the pause button) What I should accomplish is of course that it keeps recording and that I can see the ongoing timer + stop button. note: the Timer is not a service right now.. Any ideas how I should handle this?

EDIT

Suppose I shut the app down, the service is still running. Reopening the app (and thus activity where the service was initially called from) can we do with:

private boolean isMyServiceRunning() {
        ActivityManager manager = (ActivityManager) myContext.getSystemService(Context.ACTIVITY_SERVICE);
        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (MyService.class.getName().equals(service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }

So I partly have that covered, but, the variables passed from that Service to that activity are now gone. It seems that my Handler in my Activity is not picking them up after reopening that Activity?

private Handler handler = new Handler() {
        public void handleMessage(Message message) {

            //..
            Bundle bundle = message.getData();
            fileName = bundle.getString("FILENAME");
            tvFileName.setText(fileName);


            Log.e("Filename", "transfered: " + fileName);

        };
    };

//EDIT

Fragment:

public class LayoutOne extends Fragment implements OnClickListener {

    //vars
    @Override
    public void onPause() {
        super.onPause();
        if (mRecorder != null) {
            mRecorder.release();
            mRecorder = null;
        }

        if (mPlayer != null) {
            mPlayer.release();
            mPlayer = null;
        }
    }

    private Handler handler = new Handler() {
        public void handleMessage(Message message) {

            int i = message.arg1;
            Bundle bundle = message.getData();
            fileName = bundle.getString("FILENAME");
            tvFileName.setText(fileName);

            Log.e("Handler", "Succesfully transfered: " + (Integer.toString(i)));
            Log.e("Filename", "Succesfully transfered: " + fileName);
        };
    };

    @Override
    public void onClick(View v) {

        switch (v.getId()) {
        case R.id.bRecord:

            if (mStartRecording) {
                mStartRecording = false;
                Intent intent = new Intent(v.getContext(), RecordService.class);

                Messenger messenger = new Messenger(handler);
                intent.putExtra("MESSENGER", messenger);
                v.getContext().startService(intent);


            } else {
                mRecordButton.setText("Record");
                Intent stopIntent = new Intent(v.getContext(),
                        RecordService.class);

                try {
                    v.getContext().stopService(stopIntent);
                } catch (Exception e) {
                    e.printStackTrace();

                }
                mStartRecording = true;
            }

            break;

        case R.id.bStop:
            Intent stopIntent = new Intent(v.getContext(), RecordService.class);
            v.getContext().stopService(stopIntent);
            break;

        }
    }

    public static Fragment newInstance(Context context) {
        LayoutOne f = new LayoutOne();
        return f;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
        root = (ViewGroup) inflater.inflate(R.layout.layout_one, null);
        myContext = container.getContext();

        //buttons

        mgr = (NotificationManager) myContext.getSystemService(Context.NOTIFICATION_SERVICE);
        return root;
    }



    public void notifyMe(View v) {
        Notification note = new Notification(R.drawable.ic_launcher,
                getString(R.string.notificationbar), System.currentTimeMillis());
        PendingIntent i = PendingIntent.getActivity(myContext, 0, new Intent(
                myContext, ViewPagerStyle1Activity.class), 0);

        note.setLatestEventInfo(myContext, getString(R.string.app_name),
                getString(R.string.notification), i);
        note.number = ++count;
        note.vibrate = new long[] { 500L, 200L, 200L, 500L };
        note.flags |= Notification.FLAG_AUTO_CANCEL;

        mgr.notify(NOTIFY_ME_ID, note);
    }

    public void clearNotification(View v) {
        mgr.cancel(NOTIFY_ME_ID);
    }

    // /SHARED PREFERENCES SETTINGS///
//…

    private void initiatePopupWindow() {
        //..
    }



    @Override
    public void onResume() {
        super.onResume();
        Intent intent = new Intent(myContext, RecordService.class);
        myContext.startService(intent);
        myContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
    }

    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub
             LocalBinder binder = (LocalBinder) service;
                myService = binder.getService();
                //myService.setBound(true);
                initializeUI();

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub

        }
    };

    protected void initializeUI() {
        //..

        }

    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        myContext.unbindService(mServiceConnection);
    }

    @Override
    public void onStop() {
        // TODO Auto-generated method stub
        myContext.unbindService(mServiceConnection);
    }



}

//SERVICE

public class RecordService extends Service {

    //vars

     public class LocalBinder extends Binder {
            RecordService getService() {
                return RecordService.this;
            }
        }

    @Override
    public void onCreate() {
        Log.i("Oncreate", "Service onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Bundle extras = intent.getExtras();
        if (extras != null) {

            messenger = (Messenger) extras.get("MESSENGER");
            count = Integer.toString(extras.getInt("COUNT"));
            try {
                Message message = new Message();
                int arg = 0;
                message.arg1 = arg;

                mFileNamePass="test";
                Bundle bundle = new Bundle();
                bundle.putString("FILENAME", mFileNamePass);
                message.setData(bundle);
                messenger.send(message);
            } catch (android.os.RemoteException e1) {
                Log.w(getClass().getName(), "Exception sending message", e1);
            }
        }
        else {
            Log.i("Extras","Didn't find extras");
        }

        Runnable r = new Runnable() {

            @Override
            public void run() {
                checkIfFolderExists();
                String dateFull = calculateDate();
                mFileName = Environment.getExternalStorageDirectory()
                        .getAbsolutePath();
                mFileName += "test.3gp";

                mRecorder = new MediaRecorder();
                mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                mRecorder.setOutputFile(mFileName);
                mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

                try {
                    mRecorder.prepare();
                } catch (IOException e) {
                    Log.e(LOG_TAG, "prepare() failed");
                }

                mRecorder.start();
                Log.i("Service", "Service running");

            }
        };

        Thread t = new Thread(r);
        t.start();
        return RecordService.START_STICKY;
    }

    @Override
    public void onDestroy() {

        Runnable stopRecord = new Runnable() {

            @Override
            public void run() {
                mRecorder.stop();
                mRecorder.release();
                mRecorder = null;

            }

        };
        Thread stopRecordThread = new Thread(stopRecord);
        stopRecordThread.start();
        Log.i("Service", "Service stopped");
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }



}

解决方案

First of all, you don't need to check if your Service is running by some ActivityManager method. If you call startService() && bindService() in your onResume(), Android is smart enough to just bind to the Service if it's already running, and if not, it will create the Service going through it's proper documented lifecycle and then bind to it.

What you could do here is this:

@Override
public void onResume() {
    super.onResume();
    Intent intent = new Intent(this, YourService.class);
    startService(intent);
    bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}

Now, lets say your Service is already running and you want to get it's proper values. In the onServiceConnected() method of your ServiceConnection(), you can call a method like initializeUI() when the binding is done:

private ServiceConnection mServiceConnection = new ServiceConnection() {
    public void onServiceConnected(ComponentName className, IBinder service) {
        LocalBinder binder = (LocalBinder) service;
        myService = binder.getService();
        myService.setBound(true);
        initializeUI();
    }

    public void onServiceDisconnected(ComponentName className) {
    }
};

And now, you have the myService variable that points to your Service object which you can call your getters on, like myService.getTimer() and myService.isRecording().

public void initializeUI() {
    timerTextview.setText( myService.getTime() );
    someOtherUiElement.setText( myService.getSomething() );
    if( myService.isRecording() )
        recordButton.setImageResource( R.drawable.pause );
} //etc...

By the way, I don't know if you're also struggling on keeping your Service running when you exit the app If you do, using startService(intent) will keep your Service running as long as Android has enough memory. You MUST have a piece of code in which you can call myService.stopService(), otherwise, the Service will run for a very long time.

这篇关于在后台服务运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆