我想在后台运行我的应用程序。但服务类不在后台运行

时间:2017-11-14 05:58:55

标签: android android-studio service background-process countdown

这是一个计算某些数据的应用程序,如果应用程序关闭,我希望它在后台运行。这是我的代码

这是主要活动。

  public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    RadioButton selectedRdb;
    RadioGroup gender;
    EditText drinkingTime;
    EditText bodyweight;
    EditText volume;

    EditText size;
    Intent counterIntent;

    String genderOfThePerson;
    Button start;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        gender = (RadioGroup) findViewById(R.id.genderRbGroup);

        drinkingTime = (EditText) findViewById(R.id.juontiAika);
        bodyweight = (EditText) findViewById(R.id.kehonPaino);

        volume = (EditText)findViewById(R.id.vahvuus);
        size = (EditText)findViewById(R.id.koko);
        start = (Button)findViewById(R.id.startBtn);
        counterIntent = new Intent(this, Counter.class);
    }


    public void startCounter(View view) {
        if(gender.getCheckedRadioButtonId()==-1)
        {
            Toast.makeText(getApplicationContext(), "Please select Gender", Toast.LENGTH_SHORT).show();
        }
        else{
            int selectedId = gender.getCheckedRadioButtonId();
            selectedRdb = (RadioButton)findViewById(selectedId);
            if(selectedRdb.getText().toString().equalsIgnoreCase("male")){
                genderOfThePerson = "male";
            }
            else if(selectedRdb.getText().toString().equalsIgnoreCase("female")){
                genderOfThePerson = "female";
            }

        }


        int bodyWeight = Integer.parseInt(bodyweight.getText().toString());

        double drinkSize = Double.parseDouble(size.getText().toString());
        drinkSize = drinkSize/10;

        double drinkVolume = Double.parseDouble(volume.getText().toString());
        double drinkingtime = Double.parseDouble(drinkingTime.getText().toString());

        //muutetaan juomisaika tunneiksi
        drinkingtime = drinkingtime / 60;

        counterIntent.putExtra("juomankoko", drinkSize);
        counterIntent.putExtra("juomanvahvuus", drinkVolume);
        counterIntent.putExtra("sukupuoli", genderOfThePerson);
        counterIntent.putExtra("kehonpaino", bodyWeight);

        counterIntent.putExtra("juontiaika", drinkingtime);

        startActivity(counterIntent);




    }




}

这是反活动: -

    package com.mypackage.henri.beerdrinkreminder;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

import android.content.IntentFilter;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.mypackage.henri.beerdrinkreminder.Un.MainActivity;

import java.text.DecimalFormat;

public class Counter extends AppCompatActivity {

    Intent mainactivityIntent;
    Intent serviceIntent;
    TextView promilletTxt;
    TextView kanniAika;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_counter);

        mainactivityIntent  = new Intent(this, MainActivity.class);

        promilletTxt = (TextView)findViewById(R.id.bacTxt);
        kanniAika = (TextView)findViewById(R.id.känniAika);

        Button drinkButton = (Button)findViewById(R.id.drinkBtn);
        Button lopetaBtn = (Button)findViewById(R.id.stopBtn);
        Intent i = getIntent();



        //GETS THE USER INFO VARIABLES FROM INTENT AND SENDS THE FORWARD TO THE SERVICE
        serviceIntent = new Intent(Counter.this, CounterService.class);

        serviceIntent.putExtra("juomankoko", i.getDoubleExtra("juomankoko", 0));
        serviceIntent.putExtra("juomanvahvuus", i.getDoubleExtra("juomanvahvuus", 0));
        serviceIntent.putExtra("sukupuoli", i.getStringExtra("sukupuoli"));
        serviceIntent.putExtra("kehonpaino", i.getIntExtra("kehonpaino", 0));
        serviceIntent.putExtra("juontiaika", i.getDoubleExtra("juontiaika",0));

        startService(serviceIntent);
        registerReceiver(broadcastReceiver, new IntentFilter(CounterService.BROADCAST_ACTION));






        drinkButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //THIS IS FOR ADDING ANOTHER DRINK WHEN THE CALCULATOR IS ALREADY RUNNING
                AlertDialog.Builder builder = new AlertDialog.Builder(Counter.this);
                View dView = getLayoutInflater().inflate(R.layout.drinkdialog,null);
                final EditText dSize = (EditText)dView.findViewById(R.id.drinkSize);
                final EditText dTime = (EditText)dView.findViewById(R.id.drinkingTime);
                final EditText dStrenght = (EditText)dView.findViewById(R.id.juomanVahvuus);
                Button submitBtn = (Button)dView.findViewById(R.id.drinkBtn);

                builder.setView(dView);
                final AlertDialog dialog = builder.create();

                dialog.show();

                submitBtn.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if(dSize.getText().toString().isEmpty()){
                            Toast.makeText(Counter.this, "Add the size of the drink", Toast.LENGTH_SHORT).show();
                        }
                        else if(dTime.getText().toString().isEmpty()){
                            Toast.makeText(Counter.this, "Add the drinking time", Toast.LENGTH_SHORT).show();
                        }
                        else{
                            double juomankoko = Double.parseDouble(dSize.getText().toString());
                            double juontiaika = Double.parseDouble(dTime.getText().toString());
                            double juomanvahvuus = Double.parseDouble(dStrenght.getText().toString());

                            serviceIntent.putExtra("juomankoko", juomankoko);
                            serviceIntent.putExtra("juontiaika", juontiaika);
                            serviceIntent.putExtra("juomanvahvuus", juomanvahvuus);

                            //THIS IS ID IS FOR CHECKING WHERE DID THE START REQUEST COME FROM. IF THE ID IS NOT 0,
                            // THEN THE SERVICE HAS ALREADY STARTED ATLEAST ONCE AND THE ALCOHOL CALCULATOR HAS BEEN CREATED ALREADY.
                            serviceIntent.putExtra("id", 123);

                            //STARTS SERVICE AGAIN
                            startService(serviceIntent);
                            dialog.cancel();

                        }
                    }
                });



            }
        });

        //THIS BUTTON IS FOR CANCELLING THE CALCULATIONS
        lopetaBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                AlertDialog.Builder builder = new AlertDialog.Builder(Counter.this);
                View dView = getLayoutInflater().inflate(R.layout.lopetusdialogi,null);

                TextView bac = (TextView) dView.findViewById(R.id.bac);
                TextView aikaaPäisn = (TextView)dView.findViewById(R.id.aikaaPäisn);
                /*bac.setText(alcCal.calculateCurrentBac(palamisVauhtiSekunissa) + "%");

                double aika = (alcCal.getGrammat() / palamisVauhtiSekunissa) / 3600;
                int tunnit = (int)Math.floor(aika);
                int minuutit = (int)Math.floor((aika - tunnit) * 60);

                aikaaPäisn.setText(tunnit + " hours " + minuutit + " minutes");
                */
                builder.setView(dView);
                final AlertDialog dialog = builder.create();

                dialog.show();

                Button dialoginLopetus = (Button)dView.findViewById(R.id.dialoginLopetus);

                dialoginLopetus.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        startActivity(mainactivityIntent);
                    }
                });


            }
        });
    }

    @Override
    protected void onPause() {
        super.onPause();

        startService(serviceIntent);
        registerReceiver(broadcastReceiver, new IntentFilter(CounterService.BROADCAST_ACTION));
    }

    @Override
    protected void onStop() {
        super.onStop();

        unregisterReceiver(broadcastReceiver);
        startService(new Intent(this, CounterService.class));
     //   registerReceiver(broadcastReceiver, new IntentFilter(CounterService.BROADCAST_ACTION));

    }

    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            updateUI(intent);
        }
    };

    private void updateUI(Intent intent) {

        //THIS METHOD GETS THE CALCULATED ALCOHOL LEVEL AND TIME FROM THE PARAMETER INTENT AND DISPLAYS IT IN THE TEXTVIEWS
        double promillet = intent.getDoubleExtra("promillet", 0.0);
        double aikaPäisn = intent.getDoubleExtra("aika", 0.0);
        double grammat = intent.getDoubleExtra("grammat", 0.0);

        DecimalFormat df = new DecimalFormat("0.000");



        int tunnit = (int)Math.floor(aikaPäisn);
        int minuutit = (int)Math.floor((aikaPäisn - tunnit) * 60);

        promilletTxt.setText(df.format(promillet) + " %");
        kanniAika.setText(tunnit + " hours " + minuutit + " minutes");

    }
}

当我销毁所有活动时,我正在尝试运行此应用程序。 这是我的柜台服务

package com.mypackage.henri.beerdrinkreminder;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;


public class CounterService extends Service {

    private static final String TAG = "CounterService";
    private Intent intent;
    public static final String BROADCAST_ACTION = "com.mypackage.henri.beerdrinkreminder.CounterService";

    private Handler handler = new Handler();

    AlcoholCalc alcCalc;

    //VARIABLES FOR THE CALCULATIONS
    double palamisVauhtiSekunissa;
    double promillet;
    private int aloitusLukema = 0;

    @Override
    public void onCreate() {
        super.onCreate();
        intent = new Intent(BROADCAST_ACTION);

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
      //  intent = new Intent(BROADCAST_ACTION);
        aloitusLukema++;

        //THIS IS FOR CHECKING IF THE SERVICE IS STARTED FOR THE FIRST TIME. IF IT IS, THEN WE CONSTRUCT THE ALCOHOL CALCULATOR.



        if(aloitusLukema == 1){



            int kehonpaino = intent.getIntExtra("kehonpaino", 0);
            Toast.makeText(getApplicationContext(),""+kehonpaino,Toast.LENGTH_SHORT).show();

            double juomanKoko = intent.getDoubleExtra("juomankoko", 0.0);

            double juomanVahvuus = intent.getDoubleExtra("juomanvahvuus", 0.0);

            double juontiaika = (intent.getDoubleExtra("juontiaika", 0.0));

            String sukupuoli = intent.getStringExtra("sukupuoli");


            alcCalc = new AlcoholCalc(sukupuoli,
                    kehonpaino,
                    juomanVahvuus,
                    juontiaika,
                    juomanKoko);
            double palamisvauhtiTunnissa = kehonpaino / 10;

            palamisVauhtiSekunissa = palamisvauhtiTunnissa / 3600;



        }
       /*
        //THIS SECTION IS DONE IF THE USER PRESSES THE DRINK-BUTTON IN COUNTER ACVITIVY AND ADDS ANOTHER DRINK.
        else if (intent.getIntExtra("id", 0) != 0){

            double juomanKoko = intent.getDoubleExtra("juomankoko", 0.0);

            double juomanVahvuus = intent.getDoubleExtra("juomanvahvuus", 0.0);

            double juontiaika = (intent.getDoubleExtra("juontiaika", 0.0));

            alcCalc.drinkABeer(juomanKoko/10, juontiaika, juomanVahvuus);

        }
        */

        handler.removeCallbacks(sendUpdatesToUI);
        handler.postDelayed(sendUpdatesToUI, 1000);

        return START_STICKY;

    }

    private Runnable sendUpdatesToUI = new Runnable() {
        public void run() {
            AlcCalculations();
            handler.postDelayed(this, 1000);
        }
    };

    private void AlcCalculations() {

        //THIS IS FOR CALCULATING THE ALCOHOL LEVEL
        promillet = alcCalc.calculateCurrentBac(palamisVauhtiSekunissa);


        double aikaTunteina = (alcCalc.getGrammat() / palamisVauhtiSekunissa) / 3600;

        intent.putExtra("aika", aikaTunteina);
        intent.putExtra("promillet", promillet);
        intent.putExtra("grammat", alcCalc.getGrammat());
        sendBroadcast(intent);

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        handler.removeCallbacks(sendUpdatesToUI);

    }



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


}

该应用在OnPause State中运行良好。当我关闭应用程序时,它会显示一些错误消息: -

11-14 04:59:15.149 3539-3539/? E/AndroidRuntime: FATAL EXCEPTION: main
                                                 java.lang.RuntimeException: Unable to start service com.mypackage.henri.beerdrinkreminder.CounterService@536765c8 with null: java.lang.NullPointerException
                                                     at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2507)
                                                     at android.app.ActivityThread.access$1900(ActivityThread.java:130)
                                                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1292)
                                                     at android.os.Handler.dispatchMessage(Handler.java:99)
                                                     at android.os.Looper.loop(Looper.java:137)
                                                     at android.app.ActivityThread.main(ActivityThread.java:4745)
                                                     at java.lang.reflect.Method.invokeNative(Native Method)
                                                     at java.lang.reflect.Method.invoke(Method.java:511)
                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
                                                     at dalvik.system.NativeStart.main(Native Method)
                                                  Caused by: java.lang.NullPointerException
                                                     at com.mypackage.henri.beerdrinkreminder.CounterService.onStartCommand(CounterService.java:46)
                                                     at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2490)
                                                     at android.app.ActivityThread.access$1900(ActivityThread.java:130) 
                                                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1292) 
                                                     at android.os.Handler.dispatchMessage(Handler.java:99) 
                                                     at android.os.Looper.loop(Looper.java:137) 
                                                     at android.app.ActivityThread.main(ActivityThread.java:4745) 
                                                     at java.lang.reflect.Method.invokeNative(Native Method) 
                                                     at java.lang.reflect.Method.invoke(Method.java:511) 
                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 
                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
                                                     at dalvik.system.NativeStart.main(Native Method) 
11-14 04:59:17.345 3539-3539/? I/Process: Sending signal. PID: 3539 SIG: 9

3 个答案:

答案 0 :(得分:0)

从您的服务中移除Toast

Toast.makeText(getApplicationContext(),""+kehonpaino,Toast.LENGTH_SHORT).show();

服务有一些限制: 它无法与您的用户界面直接互动。

答案 1 :(得分:0)

默认情况下,服务仅在主线程上运行。您必须在服务的onStartCommand函数中处理新线程创建和处理,或者使用默认启动新后台线程的IntentService。

答案 2 :(得分:0)

在onStartCommand()方法中,您将返回标志 START_STICKY 。当您的操作系统终止服务时使用此标志,它可能是

  1. START_STICKY :如果系统终止了服务进程,则将重新启动服务,并且不会将任何已处理的Intent传递给onStartCommand函数。如果没有启动Intents正在等待传递,则将null Intent传递给onStartCommand函数。如果在系统终止服务之前没有返回启动请求,则在重新启动的服务上再次提交启动请求,并在onStartCommand第二个参数上传递START_FLAG_RETRY。

  2. START_NOT_STICKY :如果系统终止了服务,则只有在至少有一个待处理的启动请求要传递时才会重新启动服务。

  3. START_REDELIVER_INTENT :如果系统终止了服务,则服务将重新启动,重新启动上次发送的启动意图和任何待处理请求。这种服务类似于START_STICKY,但不是在start命令中提供null Intent,而是调度最后成功传递的Intent。重新传递启动请求时,会在onStartCommand第二个参数上传入标志START_ FLAG_REDELIVERY。

  4. 当您关闭应用时,您将终止该服务所在的过程。

    我建议你返回 START_NOT_STICKY START_REDELIVER_INTENT 并检查它是否有效。 此外,在清单文件的服务标记中添加属性 android:stopTask =“false”后,检查问题是否得到解决,这在应用程序被杀死时基本上不会终止服务。

    如果您仍有疑问,请浏览此链接: Understanding Android Services