【问题标题】:how to keep app running in background to send timely notifications?如何让应用程序在后台运行以及时发送通知?
【发布时间】:2016-04-12 13:03:15
【问题描述】:

我正在开发一个应用程序,当用户移动超过 300 米或如果没有移动则在 2 小时后发送通知。

但是,问题是当我将时间更改为 2 分钟时,它似乎正在工作,但是当我将时间更改为 2 小时时,它不会向我发送通知。可能是应用程序进入睡眠模式?我不知道,即使距离发生变化,它也不会发送通知。

这是我的通知发送代码,TrackMe.Java

package miniandroid.com.services;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.IBinder;

import miniandroid.com.activities.MainActivity;


public class TrackMeService extends Service {

    public int onStartCommand(Intent intent, int flags, int startId) {
        Handler handler = new Handler();
        handler.postDelayed(new Runnable(){
            public void run(){

        SharedPreferences prefs = getSharedPreferences("emood_veriif", MODE_PRIVATE);       
          String mapfirst = prefs.getString("MapFirst", "");
          String mapsecond = prefs.getString("MapSecond", "");
          if (mapfirst != mapsecond){
              NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                Notification mnotify = new Notification();
                Context context = getApplicationContext();
                Intent intent = new Intent(context,MainActivity.class);
                PendingIntent pending = PendingIntent.getActivity(context, 0, intent, 0);
                Notification.Builder builder = new Notification.Builder(context);
                builder.setDefaults(Notification.DEFAULT_SOUND);
                builder.setAutoCancel(false);
                builder.setTicker("This is important. You have unanswered questions in Smood App.");
                builder.setContentTitle("sMood");
                builder.setContentText("Please describe your mood at this location.");
                builder.setSmallIcon(android.R.drawable.stat_notify_more);
                builder.setContentIntent(pending);
                builder.setOngoing(true);
                builder.setNumber(100);
                builder.build();
              mnotify= builder.getNotification();
              nm.notify(11,mnotify);
            SharedPreferences prefsy = getSharedPreferences("emood_veriif", MODE_PRIVATE);
            SharedPreferences.Editor editor = prefsy.edit();
            editor.putString("MapSecond", mapfirst);
            editor.commit();
          }
          else{

          }

            }
        }, 1);


    return super.onStartCommand(intent, flags, startId);

    }


    public void onDestroy() {

    super.onDestroy();
    }


    public IBinder onBind(Intent arg0) {

    return null;
    }


}

这是定位服务的代码,LocationService.Java

package miniandroid.com.services;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

import miniandroid.com.helpers.UserPreference;

public class LocationService extends Service {
    public static final String BROADCAST_ACTION = "Hello World";
    //private static final int TIME_DIFF = 1000 * 60 * 2; // 2 minutes
    private static final int TIME_DIFF = 1000 * 60 * 60 * 2;  //2 hours
    private static final int DISTANCE_DIFF = 300;
    public LocationManager locationManager;
    public MyLocationListener listener;
    public Location previousBestLocation = null;

    Intent intent;
    int counter = 0;

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

    @Override
    public void onStart(Intent intent, int startId) {
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        listener = new MyLocationListener();
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
    }

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

    protected boolean isBetterLocation(Location location, Location currentBestLocation) {
        if (currentBestLocation == null) {
            // A new location is always better than no location
            return true;
        }

        // Check whether the new location fix is newer or older
        long timeDelta = location.getTime() - currentBestLocation.getTime();
        float distanceDelta = location.distanceTo(currentBestLocation);


        boolean isSignificantlyNewer = timeDelta > TIME_DIFF;

        Log.d("MyLocationListener","onLocationChanged: Time Delta: "+ timeDelta+" Distance Delta: "+distanceDelta);

        // If it's been more than two minutes since the current location, use the new location
        // because the user has likely moved
        if (isSignificantlyNewer) {

            Log.d("MyLocationListener","onLocationChanged: Time Delta: is appropriate should show notification Time Delta: "+timeDelta);
            return true;
            // If the new location is more than two minutes older, it must be worse
        }


        if(distanceDelta > DISTANCE_DIFF)
        {
            Log.d("MyLocationListener","onLocationChanged: Distance Delta: is appropriate should show notification Distance Delta: "+distanceDelta);
            return true;
        }
        return false;
    }

    /**
     * Checks whether two providers are the same
     */
    private boolean isSameProvider(String provider1, String provider2) {
        if (provider1 == null) {
            return provider2 == null;
        }
        return provider1.equals(provider2);
    }

    @Override
    public void onDestroy() {
        // handler.removeCallbacks(sendUpdatesToUI);
        super.onDestroy();
        Log.v("STOP_SERVICE", "DONE");
        locationManager.removeUpdates(listener);
    }

    public static Thread performOnBackgroundThread(final Runnable runnable) {
        final Thread t = new Thread() {
            @Override
            public void run() {
                try {
                    runnable.run();
                } finally {

                }
            }
        };
        t.start();
        return t;
    }


    public class MyLocationListener implements LocationListener {

        public void onLocationChanged(final Location loc) {
            if (isBetterLocation(loc, previousBestLocation)) {
                previousBestLocation = loc;
                startService(new Intent(LocationService.this,TrackMeService.class));
            }
        }

        public void onProviderDisabled(String provider) {
            Toast.makeText(getApplicationContext(), "Gps Disabled", Toast.LENGTH_SHORT).show();
        }


        public void onProviderEnabled(String provider) {
            Toast.makeText(getApplicationContext(), "Gps Enabled", Toast.LENGTH_SHORT).show();
        }


        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

    }
}

另一个类 location.java 正在使用 lat-lng 确定位置,并将其地理编码为 getAdress,但是,我只使用 lat-lng。 我将其设置为每两分钟和 10 米变化后获取位置。可以吗?

// How many Geocoder should return our GPSTracker
    int geocoderMaxResults = 1;

    // The minimum distance to change updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters

    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 2; // 2 minutes

非常感谢任何排序帮助。 谢谢。

【问题讨论】:

    标签: java android


    【解决方案1】:

    要让应用在未运行时仍能收到通知,请尝试添加 WAKE_LOCK 权限:

    <uses-permission android:name="android.permission.WAKE_LOCK" />
    

    【讨论】:

    • 它会让手机只为那个应用程序唤醒吗?
    • 是的,所以如果你真的需要就添加
    • 你好兄弟,我补充了,但它不会让我的手机屏幕熄灭,是不是它只使用cpu,屏幕不保持清醒,它仍然向我发送通知?
    • 试试吧兄弟:D 实际上我只是使用模拟器进行测试并且屏幕没有关闭,所以我不知道。但我认为它可以在屏幕关闭时收到通知
    【解决方案2】:

    您可能应该使用前台服务。 http://developer.android.com/guide/components/services.html#Foreground

    前台服务不会被操作系统杀死。

    另外请增加位置更新的最短时间,否则应用程序甚至会在这 2 小时之前耗尽电池;)我看到您将 0 作为 minTime 和 minDistance 发送到 requestLocationUpdates locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener); 。

    【讨论】:

    • 哦,好的。让我挖掘前台服务。感谢您的提示,获取更新的正确时间和距离是多少?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-18
    • 1970-01-01
    相关资源
    最近更新 更多