这是一个计算某些数据的应用程序,如果应用程序关闭,我希望它在后台运行。这是我的代码
这是主要活动。
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
答案 0 :(得分:0)
从您的服务中移除Toast
Toast.makeText(getApplicationContext(),""+kehonpaino,Toast.LENGTH_SHORT).show();
服务有一些限制: 它无法与您的用户界面直接互动。
答案 1 :(得分:0)
默认情况下,服务仅在主线程上运行。您必须在服务的onStartCommand函数中处理新线程创建和处理,或者使用默认启动新后台线程的IntentService。
答案 2 :(得分:0)
在onStartCommand()方法中,您将返回标志 START_STICKY 。当您的操作系统终止服务时使用此标志,它可能是
START_STICKY :如果系统终止了服务进程,则将重新启动服务,并且不会将任何已处理的Intent传递给onStartCommand函数。如果没有启动Intents正在等待传递,则将null Intent传递给onStartCommand函数。如果在系统终止服务之前没有返回启动请求,则在重新启动的服务上再次提交启动请求,并在onStartCommand第二个参数上传递START_FLAG_RETRY。
START_NOT_STICKY :如果系统终止了服务,则只有在至少有一个待处理的启动请求要传递时才会重新启动服务。
START_REDELIVER_INTENT :如果系统终止了服务,则服务将重新启动,重新启动上次发送的启动意图和任何待处理请求。这种服务类似于START_STICKY,但不是在start命令中提供null Intent,而是调度最后成功传递的Intent。重新传递启动请求时,会在onStartCommand第二个参数上传入标志START_ FLAG_REDELIVERY。
当您关闭应用时,您将终止该服务所在的过程。
我建议你返回 START_NOT_STICKY 或 START_REDELIVER_INTENT 并检查它是否有效。 此外,在清单文件的服务标记中添加属性 android:stopTask =“false”后,检查问题是否得到解决,这在应用程序被杀死时基本上不会终止服务。
如果您仍有疑问,请浏览此链接: Understanding Android Services