Cannot use findViewById in Service,used LayoutInflater but did not help,no value shown

huangapple go评论63阅读模式
英文:

Cannot use findViewById in Service,used LayoutInflater but did not help,no value shown

问题

我开发了一个用于计步的应用程序,我希望它能够在后台运行[服务]。
在这里提到了使用服务的findViewbyId存在问题:
https://stackoverflow.com/questions/6992748/android-findviewbyid-in-service

我尝试了这个方法,但值始终为0,我做错了什么?

这是我的MainActivity类:

public class MainActivity extends AppCompatActivity {
    private final int PHYISCAL_ACTIVITY = 0;
    private Button btnStopService;
    private Button btnStartService;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACTIVITY_RECOGNITION) == PackageManager.PERMISSION_DENIED) {
            // 请求权限
            requestPermissions(new String[]{Manifest.permission.ACTIVITY_RECOGNITION}, PHYISCAL_ACTIVITY);
        }
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        btnStartService = findViewById(R.id.btnStartService);
        btnStopService = findViewById(R.id.btnStopService);
        initButtonsOnClick();
    }

    private void initButtonsOnClick() {
        OnClickListener listener = new OnClickListener() {
            public void onClick(View v) {
                switch (v.getId()) {
                    case R.id.btnStartService:
                        startMyService();
                        break;
                    case R.id.btnStopService:
                        stopMyService();
                        break;
                    default:
                        break;
                }
            }
        };
        btnStartService.setOnClickListener(listener);
        btnStopService.setOnClickListener(listener);
    }

    private void startMyService() {
        Intent serviceIntent = new Intent(this, MyService.class);
        startService(serviceIntent);
    }

    private void stopMyService() {
        Intent serviceIntent = new Intent(this, MyService.class);
        stopService(serviceIntent);
    }
}

这是我的服务类MyService

public class MyService extends Service implements SensorEventListener {
    private Toast toast;
    private Timer timer;
    private TimerTask timerTask;
    private SensorManager sensorManager;
    private Sensor mineSensor;
    int Steps;

    private TextView textView;

    @Override
    public void onSensorChanged(SensorEvent sensorEvent) {
        if (sensorEvent.sensor == mineSensor) {
            Steps = (int) sensorEvent.values[0];
            textView.setText(String.valueOf(Steps));
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int i) {

    }

    private class MyTimerTask extends TimerTask {
        @Override
        public void run() {
            showToast("Your service is still working");
        }
    }

    private void showToast(String text) {
        toast.setText(text);
        toast.show();
    }

    private void writeToLogs(String message) {
        Log.d("HelloServices", message);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        writeToLogs("Called onCreate() method.");
        timer = new Timer();
        toast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        writeToLogs("Called onStartCommand() method");
        clearTimerSchedule();
        initTask();
        timer.scheduleAtFixedRate(timerTask, 4 * 1000, 4 * 1000);
        showToast("Your service has been started");
        return super.onStartCommand(intent, flags, startId);
    }

    private void clearTimerSchedule() {
        if (timerTask != null) {
            timerTask.cancel();
            timer.purge();
        }
    }

    private void initTask() {
        timerTask = new MyTimerTask();
        LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
        View layout = inflater.inflate(R.layout.activity_main, null);
        textView = (TextView) layout.findViewById(R.id.image);
        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        if (sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER) != null) {
            mineSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);

        } else {

            textView.setText("No Sensor ");

        }
    }

    @Override
    public void onDestroy() {
        writeToLogs("Called onDestroy() method");
        clearTimerSchedule();
        showToast("Your service has been stopped");
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
}

请注意,我已将HTML标签"更正为正常的引号"。如果你有任何其他翻译或问题,请告诉我。

英文:

I developed an app to count footsteps,I wanted it to be able to work in background [service]
There is a problem with findViewbyId using services mentioned here:

https://stackoverflow.com/questions/6992748/android-findviewbyid-in-service

I tried this approach,but the value is always 0,what i did wrong?

This is mine MainActivity class:

public class MainActivity extends AppCompatActivity {
private  final int PHYISCAL_ACTIVITY = 0;
private Button btnStopService;
private Button btnStartService;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACTIVITY_RECOGNITION) == PackageManager.PERMISSION_DENIED) {
//ask for permission
requestPermissions(new String[]{Manifest.permission.ACTIVITY_RECOGNITION}, PHYISCAL_ACTIVITY);
}
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
btnStartService =  findViewById(R.id.btnStartService);
btnStopService = findViewById(R.id.btnStopService);
initButtonsOnClick();
}
private void initButtonsOnClick() {
OnClickListener listener = new OnClickListener() {
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnStartService:
startMyService();
break;
case R.id.btnStopService:
stopMyService();
break;
default:
break;
}
}
};
btnStartService.setOnClickListener(listener);
btnStopService.setOnClickListener(listener);
}
private void startMyService() {
Intent serviceIntent = new Intent(this, MyService.class);
startService(serviceIntent);
}
private void stopMyService() {
Intent serviceIntent = new Intent(this, MyService.class);
stopService(serviceIntent);
}}

This is my service class:

public class MyService extends Service implements SensorEventListener {
private Toast toast;
private Timer timer;
private TimerTask timerTask;
private SensorManager sensorManager;
private Sensor mineSensor;
int Steps;
private TextView textView;
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor == mineSensor) {
Steps= (int) sensorEvent.values[0];
textView.setText(String.valueOf(Steps));
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
private class MyTimerTask extends TimerTask {
@Override
public void run() {
showToast("Your service is still working");
}
}
private void showToast(String text) {
toast.setText(text);
toast.show();
}
private void writeToLogs(String message) {
Log.d("HelloServices", message);
}
@Override
public void onCreate() {
super.onCreate();
writeToLogs("Called onCreate() method.");
timer = new Timer();
toast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
writeToLogs("Called onStartCommand() methond");
clearTimerSchedule();
initTask();
timer.scheduleAtFixedRate(timerTask, 4 * 1000, 4 * 1000);
showToast("Your service has been started");
return super.onStartCommand(intent, flags, startId);
}
private void clearTimerSchedule() {
if(timerTask != null) {
timerTask.cancel();
timer.purge();
}
}
private void initTask() {
timerTask = new MyTimerTask();
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.activity_main, null);
textView = (TextView) layout.findViewById(R.id.image);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER) != null) {
mineSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
} else {
textView.setText("No Sensor ");
}
}
@Override
public void onDestroy() {
writeToLogs("Called onDestroy() method");
clearTimerSchedule();
showToast("Your service has been stopped");
super.onDestroy();
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}}

答案1

得分: 0

你需要在主活动中注册广播接收器以从服务中获取值,如下所示:

private BroadcastReceiver broadcastReceiver;

if (broadcastReceiver == null) {
    broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // 在这里获取来自服务的值
            // 从 intent 中获取值并设置到你的布局中
        }
    };
    registerReceiver(broadcastReceiver, new IntentFilter("my_receiver"));
    Intent i = new Intent(getApplicationContext(), yourservice.class);
    startService(i);
}

在服务类中:

Intent i = new Intent("my_receiver");
i.putExtra("myvalues", yourvalues);
sendBroadcast(i);

这段代码用于在主活动中注册广播接收器以接收来自服务的值,并在服务类中发送广播以传递这些值。

英文:

You need to register a broadcast reciever in main activity to get value from service like this:

private BroadcastReceiver broadcastReceiver;
if(broadcastReceiver == null){
broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// here you get the values from service 
//get values from intent and set it to your layout
}
};
registerReceiver(broadcastReceiver,new IntentFilter("my_reciever"));
Intent i =new Intent(getApplicationContext(),yourservice.class);
startService(i);
}

In service class:

Intent i = new Intent("my_reciever");
i.putExtra("myvalues",yourvalues);
sendBroadcast(i);

答案2

得分: 0

以下是您要翻译的代码部分:

我认为一个简单的解决方案但也许不是更好的是创建一个单例例如DataController),其中包含LiveData字段
在应用程序类中创建此控制器然后将值从服务传递并在活动中观察

public final class DataController {

    private static volatile DataController instance;
    private static final Object lock = new Object();

    private MutableLiveData<Integer> counter = new MutableLiveData(0);
    private MutableLiveData<String> message = new MutableLiveData();

    public static DataController get() {
        if (instance == null) {
            synchronized (lock) {
                if (instance == null) {
                    instance = new DataController();
                }
            }
        }
        return instance;
    }

    public void setCounter(Integer count){
        counter.postValue(count);
    }

    public void setMessage(String str){
        message.postValue(str);
    }

    public MutableLiveData<Integer> getCounter() {
        return counter;
    }

    public MutableLiveData<String> getMessage() {
        return message;
    }
}
英文:

I think a simple solution (but maybe not better) is to create a singleton (for example DataController) with live data field.
Create this controller inside application class, then past values from the service, and observe in the activity.

    public final class DataController {
private static volatile DataController instance;
private static final Object lock = new Object();
private MutableLiveData&lt;Integer&gt; counter = new MutableLiveData(0);
private MutableLiveData&lt;String&gt; message = new MutableLiveData();
public static DataController get() {
if (instance == null) {
synchronized (lock) {
if (instance == null) {
instance = new DataController();
}
}
}
return instance;
}
public void setCounter(Integer count){
counter.postValue(count);
}
public void setMessage(String str){
message.postValue(str);
}
public MutableLiveData&lt;Integer&gt; getCounter() {
return counter;
}
public MutableLiveData&lt;String&gt; getMessage() {
return message;
}
}

huangapple
  • 本文由 发表于 2020年8月9日 18:57:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/63325422.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定