programing tip

항상 백그라운드에서 서비스를 실행하는 방법은 무엇입니까?

itbloger 2020. 10. 25. 11:43
반응형

항상 백그라운드에서 서비스를 실행하는 방법은 무엇입니까?


기본 제공 SMS 앱과 유사한 앱을 만드는 중입니다.

내가 필요한 것:

  • 항상 백그라운드에서 실행되는 서비스
  • 5 분마다 서비스는 장치의 현재 위치를 확인하고 웹 서비스를 호출합니다.
  • 특정 기준이 충족되면 서비스에서 알림을 생성해야합니다 (SMS 앱처럼).
  • 알림을 클릭하면 사용자가 앱으로 이동합니다 (SMS 앱처럼).
  • 앱이 설치되면 서비스를 시작해야합니다
  • 장치가 재부팅되면 서비스가 시작되어야합니다.

내가 시도한 것 : -Android가
서비스를 종료 할 때까지 정상적으로 작동하는 일반 서비스 실행
-AlarmManager를 사용하여 5 분을 만듭니다. 서비스에 대한 간격 호출. 그러나 나는이 일을 할 수 없었다.


항상 백그라운드에서 실행되는 서비스

이것은 당신이 발견했듯이 실제 용어의 의미에서 불가능합니다 . 디자인나쁘다 .

5 분마다 서비스는 장치의 현재 위치를 확인하고 웹 서비스를 호출합니다.

사용 AlarmManager.

AlarmManager를 사용하여 5 분을 만듭니다. 서비스에 대한 간격 호출. 그러나 나는이 일을 할 수 없었다.

다음은 전체 웹 서비스 작업을 수행하는 동안 깨어있을 수 있도록 사용 방법과 함께 사용 방법을 보여주는 샘플 프로젝트WakefulIntentService 입니다.

계속해서 문제가 발생 AlarmManager하면 슬픔을 느끼는 특정 상황에 대해 새로운 질문 을여십시오.


내 앱 중 하나가 매우 유사한 작업을합니다. 주어진 기간 후에 서비스를 깨우려면postDelayed()

핸들러 필드가 있습니다.

private final Handler handler = new Handler();

그리고 재충전 Runnable

private final Runnable refresher = new Runnable() {
  public void run() {
    // some action
  }
};

실행 파일에서 알림을 실행할 수 있습니다.

서비스 구축시, 각 실행 후 다음과 같이 시작합니다.

handler.postDelayed(refresher, /* some delay in ms*/);

에서 onDestroy()포스트를 제거

handler.removeCallbacks(refresher);

부팅시 서비스를 시작하려면 자동 시작이 필요합니다. 이것은 당신의 매니페스트에 들어갑니다

<receiver android:name="com.example.ServiceAutoStarter">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
  </receiver>

그리고 ServiceAutoStarter다음과 같이 보입니다 :

public class ServiceAutoStarter extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
    context.startService(new Intent(context, UpdateService.class));
  }
}

OS가 서비스를 종료하지 못하도록하는 것은 까다 롭습니다. 또한 응용 프로그램에 RuntimeException및 충돌이 있거나 논리가 중단 될 수 있습니다.

제 경우에는 항상 화면의 서비스를 BroadcastReceiver. 따라서 업데이트 체인이 중단되면 사용자가 휴대 전화를 사용할 때 부활됩니다.

서비스에서 :

private BroadcastReceiver screenOnReceiver; 

귀하의 서비스 onCreate()

screenOnReceiver = new BroadcastReceiver() {

  @Override
  public void onReceive(Context context, Intent intent) {
    // Some action
  }
};

registerReceiver(screenOnReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));

그런 다음에 서비스 등록 해제 onDestroy()

unregisterReceiver(screenOnReceiver);

간단한 구현으로이를 수행 할 수 있습니다.

public class LocationTrace extends Service implements LocationListener{

    // The minimum distance to change Updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
    private static final int TWO_MINUTES = 100 * 10;

    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1000 * 10; // 30 seconds

    private Context context;

    double latitude;
    double longitude;

    Location location = null;
    boolean isGPSEnabled = false;
    boolean isNetworkEnabled = false;
    protected LocationManager locationManager;


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        this.context = this;
        get_current_location();
//      Toast.makeText(context, "Lat"+latitude+"long"+longitude,Toast.LENGTH_SHORT).show();
        return START_STICKY;
    }


    @Override
    public void onLocationChanged(Location location) {
        if((location != null) && (location.getLatitude() != 0) && (location.getLongitude() != 0)){

            latitude = location.getLatitude();
            longitude = location.getLongitude();

            if (!Utils.getuserid(context).equalsIgnoreCase("")) {
                Double[] arr = { location.getLatitude(), location.getLongitude() };

               // DO ASYNCTASK
            }
        }

    }


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

    }

    @Override
    public void onProviderEnabled(String provider) {

    }

    @Override
    public void onProviderDisabled(String provider) {

    }

    /*
    *  Get Current Location
    */
    public Location get_current_location(){

        locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

        isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

        isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if(!isGPSEnabled && !isNetworkEnabled){



        }else{
            if (isGPSEnabled) {

                if (location == null) {
                    locationManager.requestLocationUpdates(
                            LocationManager.GPS_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

                    if (locationManager != null) {
                        location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                        if (location != null) {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
        //                  Toast.makeText(context, "Latgps"+latitude+"long"+longitude,Toast.LENGTH_SHORT).show();
                        }
                    }
                }
            }
            if (isNetworkEnabled) {

                locationManager.requestLocationUpdates(
                        LocationManager.NETWORK_PROVIDER,
                        MIN_TIME_BW_UPDATES,
                        MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

                if (locationManager != null) {

                    if (location != null) {
                        latitude = location.getLatitude();
                        longitude = location.getLongitude();
        //              Toast.makeText(context, "Latgps1"+latitude+"long"+longitude,Toast.LENGTH_SHORT).show();
                    }
                }
            }
        }

        return location;
    }


    public double getLatitude() {
        if(location != null){
            latitude = location.getLatitude();
        }
        return latitude;
    }

    public double getLongitude() {
         if(location != null){
             longitude = location.getLongitude();
         }

        return longitude;
    }


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

    @Override
    public void onDestroy() {
        if(locationManager != null){
            locationManager.removeUpdates(this);
        }
        super.onDestroy();
    }

}

다음과 같이 서비스를 시작할 수 있습니다.

/*--Start Service--*/
startService(new Intent(Splash.this, LocationTrace.class));

매니페스트에서 :

 <service android:name=".LocationTrace">
            <intent-filter android:priority="1000">
                <action android:name="android.location.PROVIDERS_CHANGED"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
  </service>

다음 세 단계를 통해 대부분의 Android 기기를 5 분마다 깨울 수 있습니다.

1. 다른 API에 대한 대체 AlarmManager를 설정합니다.

AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(getApplicationContext(), OwnReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, i, 0);

if (Build.VERSION.SDK_INT >= 23) {
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
}
else if (Build.VERSION.SDK_INT >= 19) {
am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
} else {
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
}

2. 고유 한 정적 BroadcastReceiver를 빌드합니다.

public static class OwnReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

       //do all of your jobs here

        AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent i = new Intent(context, OwnReceiver.class);
        PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);

        if (Build.VERSION.SDK_INT >= 23) {
            am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
        }
        else if (Build.VERSION.SDK_INT >= 19) {
            am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
        } else {
            am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
        }
    }
}

추가 3. <receiver>합니다 AndroidManifest.xml:

<receiver android:name=".OwnReceiver"  />

참고 URL : https://stackoverflow.com/questions/2566350/how-to-always-run-a-service-in-the-background

반응형