即使应用程序在后台,我也需要连续向服务器发送数据(比如每 x 秒或分钟后)。我知道服务是最好的选择。因为我从未尝试过这种情况,有没有关于如何制作的方便示例来自服务的 Web 服务调用,然后在传递对活动的响应(无论数据是否成功)之后。任何方法或其他方式来实现这一点。任何帮助表示赞赏。
问问题
3072 次
2 回答
0
首先在mainactivity中添加:
AlarmManager alarmManager;
PendingIntent pendingIntent;
Calendar calendar;
Intent alarm;
final int SDK_INT = Build.VERSION.SDK_INT;
calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarm = new Intent(this, TestForecastService.class);
pendingIntent = PendingIntent.getService(this, 0, alarm, 0);
if (SDK_INT < Build.VERSION_CODES.KITKAT) {
alarmManager.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+10000, pendingIntent);
Log.d("lowerMF","hahah");
}
else if (Build.VERSION_CODES.KITKAT <= SDK_INT && SDK_INT < Build.VERSION_CODES.M) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+10000,pendingIntent);
Log.d("kitkatMF","hahah");
}
else if (SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+10000,pendingIntent);
Log.d("marshmallowMF","hahah");
}
现在,TestForecastService: 你可以在其中定义你的工作:
public class TestForecastService extends IntentService {
Context context;
PowerManager powerManager;
PowerManager.WakeLock wakeLock;
final int SDK_INT = Build.VERSION.SDK_INT;
AlarmManager alarmManager;
PendingIntent pendingIntent;
Intent alarm;
public TestForecastService() {
super("");
}
@Override
protected void onHandleIntent(Intent intent) {
powerManager = (PowerManager) getSystemService(POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "FCFCFCFC");
wakeLock.acquire();
sendDATA(city);
}
private void sendDATA(String city) {
try {
......DO YOUR DATA SENDING WORK.........
} catch (Exception e) {
Log.v("fserviceerror","erre");
}
reSETALARAM();
wakeLock.release();
}
private void reSETALARAM() {
alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarm = new Intent(this,TestForecastService.class);
pendingIntent = PendingIntent.getService(this, 0, alarm, 0);
if (SDK_INT < Build.VERSION_CODES.KITKAT) {
alarmManager.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+10000, pendingIntent);
Log.d("lowerFS","hahah");
}
else if (Build.VERSION_CODES.KITKAT <= SDK_INT && SDK_INT < Build.VERSION_CODES.M) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+10000,pendingIntent);
Log.d("kitkatFS","hahah");
}
else if (SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+10000,pendingIntent);
Log.d("marshmallowFS","hahah");
}
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
现在,让 BrodcastReceiver 类在设备重新启动时运行您的服务:
public class Auto extends BroadcastReceiver {
final int SDK_INT = Build.VERSION.SDK_INT;
@Override
public void onReceive(Context ctx, Intent intent) {
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")){
AlarmManager alarmMgr = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
Intent intent1 = new Intent(ctx, TestForecastService.class);
PendingIntent alarmIntent = PendingIntent.getService(ctx, 0, intent1, 0);
if (SDK_INT < Build.VERSION_CODES.KITKAT) {
alarmMgr.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+10000, alarmIntent);
Log.d("lowerFB","hahah");
}
else if (Build.VERSION_CODES.KITKAT <= SDK_INT && SDK_INT < Build.VERSION_CODES.M) {
alarmMgr.setExact(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+10000,alarmIntent);
Log.d("kitkatFB","hahah");
}
else if (SDK_INT >= Build.VERSION_CODES.M) {
alarmMgr.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+10000,alarmIntent);
Log.d("marshmallowFB","hahah");
}
}
}
}
最后,在 Manifest 文件中添加:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<service android:name=".TestForecastService" android:exported="true" android:enabled="true"/>
<receiver android:name=".Auto" android:exported="true" android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
于 2016-12-09T13:23:25.783 回答
0
import com.google.android.gms.gcm.GcmTaskService;
import com.google.android.gms.gcm.TaskParams;
import android.content.Context;
import android.content.SharedPreferences;
import android.location.Address;
import android.location.Geocoder;
import android.net.ConnectivityManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.gcm.GcmNetworkManager;
import com.google.android.gms.gcm.OneoffTask;
import com.google.android.gms.gcm.PeriodicTask;
import com.google.android.gms.gcm.Task;
import java.util.List;
import java.util.Locale;
/**
* Created by MAYURKUMAR TERAIYA on 20-09-2017.
*/
public class GCMServiceTracking extends GcmTaskService {
private static final String TAG = GCMServiceTracking.class.getSimpleName();
public static final String GCM_ONEOFF_TAG = "oneoff|[0,0]";
public static final String GCM_REPEAT_TAG = "repeat|[7200,1800]";
@Override
public void onInitializeTasks() {
//called when app is updated to a new version, reinstalled etc.
//you have to schedule your repeating tasks again
super.onInitializeTasks();
}
@Override
public int onRunTask(TaskParams taskParams) {
//do some stuff (mostly network) - executed in background thread (async)
//Toast.makeText(getApplicationContext(), "Service Executed",
Toast.LENGTH_SHORT).show();
//obtain your data
Bundle extras = taskParams.getExtras();
Handler h = new Handler(getMainLooper());
Log.v(TAG, "onRunTask");
if (taskParams.getTag().equals(GCM_ONEOFF_TAG)) {
h.post(new Runnable() {
@Override
public void run() {
//Toast.makeText(GCMServiceTracking.this, "ONEOFF executed",
Toast.LENGTH_SHORT).show();
}
});
} else if (taskParams.getTag().equals(GCM_REPEAT_TAG)) {
h.post(new Runnable() {
@Override
public void run() {
//Toast.makeText(GCMServiceTracking.this, "REPEATING executed",
Toast.LENGTH_SHORT).show();
gpsTracker = new GPSTracker(GCMServiceTracking.this);
Toast.makeText(getApplicationContext(), "Data Syncing.",
Toast.LENGTH_SHORT).show();
}
});
}
return GcmNetworkManager.RESULT_SUCCESS;
}
public static void scheduleOneOff(Context context) {
//in this method, single OneOff task is scheduled (the target service
that will be called is MyTaskService.class)
Bundle data = new Bundle();
data.putString("some key", "some budle data");
try {
OneoffTask oneoff = new OneoffTask.Builder()
//specify target service - must extend GcmTaskService
.setService(GCMServiceTracking.class)
//tag that is unique to this task (can be used to cancel task)
.setTag(GCM_ONEOFF_TAG)
//executed between 0 - 10s from now
.setExecutionWindow(10, 10)
//set required network state, this line is optional
.setRequiredNetwork(Task.NETWORK_STATE_ANY)
//request that charging must be connected, this line is optional
.setRequiresCharging(false)
//set some data we want to pass to our task
.setExtras(data)
//if another task with same tag is already scheduled, replace it
with this task
.setUpdateCurrent(true)
.build();
GcmNetworkManager.getInstance(context).schedule(oneoff);
Log.v(TAG, "oneoff task scheduled");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void scheduleRepeat(Context context) {
//in this method, single Repeating task is scheduled (the target service
that will be called is MyTaskService.class)
try {
PeriodicTask periodic = new PeriodicTask.Builder()
//specify target service - must extend GcmTaskService
.setService(GCMServiceTracking.class)
//repeat every 60 seconds
.setPeriod(300)
//specify how much earlier the task can be executed (in seconds)
.setFlex(30)
//tag that is unique to this task (can be used to cancel task)
.setTag(GCM_REPEAT_TAG)
//whether the task persists after device reboot
.setPersisted(true)
//if another task with same tag is already scheduled, replace it
with this task
.setUpdateCurrent(true)
//set required network state, this line is optional
.setRequiredNetwork(Task.NETWORK_STATE_ANY)
//request that charging must be connected, this line is optional
.setRequiresCharging(false)
.build();
GcmNetworkManager.getInstance(context).schedule(periodic);
Log.v(TAG, "repeating task scheduled");
} catch (Exception e) {
Log.e(TAG, "scheduling failed");
e.printStackTrace();
}
}
public static void cancelOneOff(Context context) {
GcmNetworkManager
.getInstance(context)
.cancelTask(GCM_ONEOFF_TAG, GCMServiceTracking.class);
}
public static void cancelRepeat(Context context) {
GcmNetworkManager
.getInstance(context)
.cancelTask(GCM_REPEAT_TAG, GCMServiceTracking.class);
}
public static void cancelAll(Context context) {
GcmNetworkManager
.getInstance(context)
.cancelAllTasks(GCMServiceTracking.class);
}
// CODE FOR START BACKGROUND TASK
GoogleApiAvailability api = GoogleApiAvailability.getInstance();
Int errorCheck = api.isGooglePlayServicesAvailable(LoginActivity.this);
if(errorCheck == ConnectionResult.SUCCESS) {
//google play services available, hooray
} else if(api.isUserResolvableError(errorCheck)) {
//GPS_REQUEST_CODE = 1000, and is used in onActivityResult
api.showErrorDialogFragment(LoginActivity.this, errorCheck,
GPS_REQUEST_CODE);
//stop our activity initialization code
return;
} else {
//GPS not available, user cannot resolve this error
//todo: somehow inform user or fallback to different
method
//stop our activity initialization code
return;
}
GCMServiceTracking.scheduleRepeat(LoginActivity.this);
GRADLE FILE
compile 'com.google.android.gms:play-services:8.3.0'
MENIFEST FILE
<service
android:name=".services.GCMServiceTracking"
android:exported="true"
android:permission="com.google.android.gms.permission.BIND_NETWORK_TASK_SERVIC>
<intent-filter>
<action android:name="com.google.android.gms.gcm.ACTION_TASK_READY"/>
</intent-filter>
</service>
于 2017-09-21T06:44:55.533 回答