英文:
Why My service don t work in the Backgroung?
问题
以下是MainActivity代码的翻译部分:
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
// ... (其他的变量声明和初始化)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ... (其他的UI元素初始化和逻辑处理)
googleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
updateFCM(M.getID(context));
}
// ... (其他的方法实现)
@Override
public void onLocationChanged(Location location) {
this.currentLocation = location;
if (currentLocation != null) {
new setCurrentLocation().execute(String.valueOf(location.getLatitude()),String.valueOf(location.getLongitude()));
}
}
private class setCurrentLocation extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
// ... (设置位置的网络请求)
return null;
}
@Override
protected void onPostExecute(String result) {
// ... (后续处理)
}
@Override
protected void onPreExecute() {
// ... (预处理)
}
}
// ... (其他的方法实现)
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case LOCATION_REQUEST_CODE: {
if (!isLocationEnabled(context))
showMessageEnabledGPS();
return;
}
}
}
public void showMessageEnabledGPSClient() {
// ... (显示GPS设置提示对话框)
}
public void showMessageEnabledGPS() {
// ... (显示GPS设置提示对话框)
}
private boolean isLocationEnabled(Context context) {
// ... (判断GPS是否开启)
}
}
以下是MyService代码的翻译部分:
import android.Manifest;
import android.app.Service;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.IBinder;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
public class MyService extends Service implements LocationListener {
private LocationRequest locationRequest;
public static Location currentLocation;
private GoogleApiClient googleApiClient;
public static Context context;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (ActivityCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// 权限检查
currentLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
startLocationUpdates();
}
return START_STICKY;
}
private void startLocationUpdates() {
locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(5000);
locationRequest.setFastestInterval(2000);
if (ActivityCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// 权限检查
}
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onLocationChanged(Location location) {
// ... (位置变化监听)
}
}
请注意,由于你的原始代码中有一些HTML实体编码(如"
),在翻译过程中我已将其还原为正常的双引号。另外,为了保持代码的清晰,我省略了一些重复或者与问题关系不大的部分。如果你需要对代码进行修改或添加,请务必注意代码的逻辑和结构。
英文:
Im working on an taxi app that need to keep tracking driver even when the app is in background or the screen is off
I tried to do it through a Service but it dons t work and I cant find the probleme
My second issue it that the app don t upload some kind of images for example whene i take a high quality photo with my phone and i upload it in the server the app keep saying failed but the photo is uploaded on the server / and whene i take a screenshot un upload it it work fine
3Q/ what are the minimun requemendation of a server to use with a taxi app
this is the MainActivity code
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
/** MAP **/
public static GoogleMap mMap;
public static Location currentLocation;
/** GOOGLE API CLIENT **/
private GoogleApiClient googleApiClient;
private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
private LocationRequest locationRequest;
private static final long UPDATE_INTERVAL = 5000, FASTEST_INTERVAL = 5000; // = 5 seconds
private LocationManager locationManager;
private String provider;
public static String amount,id_ride,position,id_driver,note_,img,comment;
public static AlertDialog alertDialog;
private static TextView title;
private static final String HTTPS = "https://";
private static final String HTTP = "http://";
private static TextView ok, time;
private static ProgressBar progressBar2;
private static CountDownTimer countDownTimer = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = MainActivity.this;
activity = this;
connectionDetector=new ConnectionDetector(context);
prefManager = new PrefManager(this);
title = (TextView) findViewById(R.id.title);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Bundle objetbundle = this.getIntent().getExtras();
String fragment_name = objetbundle.getString("fragment_name");
if(!fragment_name.equals("")){
notification = true;
if(fragment_name.equals("ridenewrider"))
selectItem(1);
else if(fragment_name.equals("ridecompleted"))
selectItem(4);
/*else if(fragment_name.equals("ridecanceledrider"))
selectItem(1);*/
}
balance = (TextView) findViewById(R.id.balance);
user_photo = (CircleImageView) findViewById(R.id.user_photo);
switch_statut = (SwitchCompat) findViewById(R.id.switch_statut);
user_name = (TextView) findViewById(R.id.user_name);
user_phone = (TextView) findViewById(R.id.user_phone);
statut_conducteur = (TextView) findViewById(R.id.statut_conducteur);
drawer_conducteur = (FrameLayout) findViewById(R.id.drawer_conducteur);
drawer_user = (LinearLayout) findViewById(R.id.drawer_user);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(MainActivity.this, mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close);
mDrawerLayout.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationViewLeft = (NavigationView) findViewById(R.id.nav_view);
mDrawerList = (RecyclerView) findViewById(R.id.rvdrawer);
mDrawerList.setLayoutManager(new LinearLayoutManager(context));
mDrawerList.setHasFixedSize(true);
setDrawer();
if (savedInstanceState == null) {
if(fragment_name.equals(""))
selectItem(0);
}
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE);
}
if(!isLocationEnabled(context))
showMessageEnabledGPS();
balance.setVisibility(View.GONE);
if (M.getStatutConducteur(context).equals("yes")) {
switch_statut.setChecked(true);
statut_conducteur.setText("enabled");
} else {
switch_statut.setChecked(false);
statut_conducteur.setText("disabled");
}
switch_statut.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(switch_statut.isChecked()) {
M.showLoadingDialog(context);
new changerStatut().execute("yes");
}else {
M.showLoadingDialog(context);
new changerStatut().execute("no");
}
}
});
if(!M.getPhoto(context).equals("")) {
Glide.with(context).load(AppConst.Server_url + "images/app_user/" + M.getPhoto(context))
.skipMemoryCache(false)
.listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
user_photo.setImageDrawable(getResources().getDrawable(R.drawable.user_profile));
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
return false;
}
})
.into(user_photo);
}else{
user_photo.setImageDrawable(getResources().getDrawable(R.drawable.user_profile));
}
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, false);
if (provider != null) {
currentLocation = locationManager.getLastKnownLocation(provider);
}
googleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
updateFCM(M.getID(context));
}
public static void setTitle(String title_){
title.setText(title_);
}
@Override
public void onDestroy() {
stopService(new Intent(context, PayPalService.class));
currentLocation = null;
super.onDestroy();
}
/** Récupération user wallet**/
public class getWallet extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
String url = AppConst.Server_url+"get_wallet.php";
StringRequest jsonObjReq = new StringRequest(Request.Method.POST,
url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
JSONObject json = new JSONObject(response);
JSONObject msg = json.getJSONObject("msg");
String etat = msg.getString("etat");
if(etat.equals("1")){
balance.setText(M.getCurrency(context)+" "+msg.getString("amount"));
}else{
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("id_user", M.getID(context));
params.put("cat_user", M.getUserCategorie(context));
return params;
}
};
AppController.getInstance().addToRequestQueue(jsonObjReq);
jsonObjReq.setRetryPolicy(new DefaultRetryPolicy(
10000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
return null;
}
@Override
protected void onPostExecute(String result) {
if (this != null) {
}
}
@Override
protected void onPreExecute() {
}
}
@Override
public void onLocationChanged(Location location) {
this.currentLocation = location;
if (currentLocation != null) {
new setCurrentLocation().execute(String.valueOf(location.getLatitude()),String.valueOf(location.getLongitude()));
}
}
/** Update driver position **/
private class setCurrentLocation extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
String url = AppConst.Server_url+"set_position.php";
final String latitude = params[0];
final String longitude = params[1];
StringRequest jsonObjReq = new StringRequest(Request.Method.POST,
url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("id_user", M.getID(context));
params.put("user_cat", M.getUserCategorie(context));
params.put("latitude", latitude);
params.put("longitude", longitude);
return params;
}
};
AppController.getInstance().addToRequestQueue(jsonObjReq);
jsonObjReq.setRetryPolicy(new DefaultRetryPolicy(
10000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
return null;
}
@Override
protected void onPostExecute(String result) {
if (this != null) {
}
}
@Override
protected void onPreExecute() {
}
}
/** Start COOGLE API Client **/
@Override
public void onStart() {
super.onStart();
if (googleApiClient != null) {
googleApiClient.connect();
}
}
@Override
public void onStop() {
super.onStop();
if (googleApiClient != null) {
googleApiClient.disconnect();
}
}
@Override
public void onConnected(@Nullable Bundle bundle) {
if (ActivityCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
// Permissions ok, we get last location
currentLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
startLocationUpdates();
}
private void startLocationUpdates() {
locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(UPDATE_INTERVAL);
locationRequest.setFastestInterval(FASTEST_INTERVAL);
if (ActivityCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
}
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
/** Change driver status **/
private class changerStatut extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
String url = AppConst.Server_url+"change_statut.php";
final String online = params[0];
StringRequest jsonObjReq = new StringRequest(Request.Method.POST,
url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
M.hideLoadingDialog();
JSONObject json = new JSONObject(response);
JSONObject msg = json.getJSONObject("msg");
String etat = msg.getString("etat");
String online = msg.getString("online");
if(etat.equals("1")){
if(online.equals("yes")) {
switch_statut.setChecked(true);
statut_conducteur.setText("enabled");
M.setStatutConducteur(online,context);
}else {
switch_statut.setChecked(false);
statut_conducteur.setText("disabled");
M.setStatutConducteur(online,context);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
M.hideLoadingDialog();
if(switch_statut.isChecked())
switch_statut.setChecked(false);
else
switch_statut.setChecked(true);
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("id_driver", M.getID(context));
params.put("online", online);
return params;
}
};
AppController.getInstance().addToRequestQueue(jsonObjReq);
jsonObjReq.setRetryPolicy(new DefaultRetryPolicy(
10000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
return null;
}
@Override
protected void onPostExecute(String result) {
//to add spacing between cards
if (this != null) {
}
}
@Override
protected void onPreExecute() {
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case LOCATION_REQUEST_CODE: {
if(!isLocationEnabled(context))
showMessageEnabledGPS();
return;
}
}
}
public void showMessageEnabledGPSClient(){
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage(context.getResources().getString(R.string.this_service_requires_the_activation_of_the_gps))
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.cancel();
}
});
final AlertDialog alert = builder.create();
alert.show();
}
public void showMessageEnabledGPS(){
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage("Activez le service GPS pour partager votre position avec les clients. Activez le GPS maintenant ?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.cancel();
}
});
final AlertDialog alert = builder.create();
alert.show();
}
private boolean isLocationEnabled(Context context){
boolean enabled = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
int mode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE,
Settings.Secure.LOCATION_MODE_OFF);
enabled = (mode != Settings.Secure.LOCATION_MODE_OFF);
}else{
LocationManager service = (LocationManager) context.getSystemService(LOCATION_SERVICE);
enabled = service.isProviderEnabled(LocationManager.GPS_PROVIDER)||service.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
return enabled;
}
and this is the Service
import android.Manifest;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.IBinder;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
public class MyService extends Service {
private LocationRequest locationRequest;
public static Location currentLocation;
private GoogleApiClient googleApiClient;
public static Context context;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (ActivityCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
}
currentLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
startLocationUpdates();
return START_STICKY;
}
private void startLocationUpdates() {
locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(5000);
locationRequest.setFastestInterval(2000);
if (ActivityCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
}
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, (LocationListener) this);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
答案1
得分: 0
在 Android O 及以后的版本中,存在对 Android 服务启动的限制。为了进行电池优化,Android 操作系统会在一段时间后终止长时间运行的后台服务或进程(详细解释请参阅此处:https://medium.com/oceanize-geeks/background-services-in-android-o-a38a7c624391 和 https://medium.com/exploring-android/exploring-background-execution-limits-on-android-oreo-ab384762a66c)。
相反,您可以使用前台服务来让您的应用在后台持续运行。前台服务要求持续显示通知,以便用户知道应用 X 正在后台执行某些工作。有关前台服务的实现,请参考 https://codinginflow.com/tutorials/android/foreground-service。
英文:
There is a limitation on Android service starting Android O. Android OS kills the long running background services/processes after some time for battery optimization (explained here https://medium.com/oceanize-geeks/background-services-in-android-o-a38a7c624391 & https://medium.com/exploring-android/exploring-background-execution-limits-on-android-oreo-ab384762a66c).
Instead you can use Foreground service to keep your app running in the background. Foreground service requires a continuous Notification to be displayed so that user will be aware that X app is doing some work in background. For Foreground service implementation you can refer https://codinginflow.com/tutorials/android/foreground-service.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论