PDA

View Full Version : ترکیب BroadcastReceiver و JobService برای دریافت اطلاعات از اینترنت در پس زمینه



kolibri
جمعه 04 خرداد 1397, 13:53 عصر
سلام؛
من نیاز دارم در پس زمینه، طی دوره زمانی مشخص و با اطلاع از اتصال به شبکه اینترنت، یک سری اطلاعات رو از سورس دریافت کنم. مشکلی که من دارم، نا آشنا بودن با این تکنولوژی ها و تازه کار بودن من در جاوا و اندروید هست.


BroadcastReceiver همونطور که می دونید، برای آگاهی از بعضی رویدادها در سیستم هست و من از این برای اطلاع از متصل بودن به نت استفاده کردم، به محض اینکه نت (Mobile Data/WiFi) متصل باشه، کلاس زیر شروع به کار می کنه:



public class NetworkChangeReceiver extends BroadcastReceiver {
private Context mContext;
private JobScheduler mJobScheduler;

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

boolean isVisible = AppController.isActivityVisible();// Check if Log.i("Activity is Visible ", "Is activity visible : " + isVisible);

// If it is visible then trigger the task else do nothing
ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager
.getActiveNetworkInfo();

// Check internet connection and accrding to state change the // text of activity by calling method if (networkInfo != null && networkInfo.isConnected()) {
mContext = context;
mJobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SER VICE);
JobInfo.Builder builder = new JobInfo.Builder(1,
new ComponentName(MainActivity.PACKAGE_NAME, Job.class.getName()));

builder.setPeriodic(3000);
builder.build();
if (mJobScheduler.schedule(builder.build()) == JobScheduler.RESULT_FAILURE) {
//If something goes wrong Log.i("mJobScheduler", "If something goes wrong ");
}
} else {
}
} catch (Exception e) {
e.printStackTrace();
}

}
}



مزیت اینه که وقت نت قطع شد، می تونم پس زمینه رو هم متوقف کنم تا مشکلی پیش نیاد. اما این کلاس JobService من هست که برای تست هست:



public class Job extends JobService {
private static final String TAG = "SyncService";
@Override
public boolean onStartJob(JobParameters params) {
// fake work
Log.i(TAG, "on start job: " + params.getJobId());
return true;
}
@Override
public boolean onStopJob(JobParameters params) {
return true;
}
}



من در اینجا شیئی از Job.Class ساختم و اون رو شروع هم کردم، اما این کلاس عکس العملی نداره و اجرا نمیشه (کلاس NetworkChangeReceiver به خوبی کار می کند):



if (networkInfo != null && networkInfo.isConnected()) {
mContext = context;
mJobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SER VICE);
JobInfo.Builder builder = new JobInfo.Builder(1,
new ComponentName(MainActivity.PACKAGE_NAME, Job.class.getName()));

builder.setPeriodic(3000);
builder.build();
if (mJobScheduler.schedule(builder.build()) == JobScheduler.RESULT_FAILURE) {
//If something goes wrong
Log.i("mJobScheduler", "If something goes wrong ");
}
} else {
}



حالا سوال من این هست:
1. چطور کلاس Job رو صدا بزنم؟
2. چطور زمانبندی ایجاد کنم؟ مثلا هر ساعت یکبار اجرا شود.

با تشکر

kolibri
شنبه 05 خرداد 1397, 10:47 صبح
سلام؛
اگر با سرویس ها یا Intent Service هم کسی راه حلی برای این کار داره، ممنون میشم به اشتراک بگذاره.

kolibri
چهارشنبه 09 خرداد 1397, 11:55 صبح
سلام مجدد؛
خب دوستان چون با Job نتونستم کارم رو پیش ببرم (هر چند گویا خیلی خوبه)، دست به دامان سرویس شدم. کدها به زیر تغییر کرده:
کلاس NetworkChangeReceiver


public class NetworkChangeReceiver extends BroadcastReceiver {
private Context mContext;

@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onReceive(final Context context, final Intent intent) {
try {

boolean isVisible = AppController.isActivityVisible();// Check if
Log.i("Activity is Visible ", "Is activity visible : " + isVisible);

// If it is visible then trigger the task else do nothing

ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager
.getActiveNetworkInfo();

// Check internet connection and accrding to state change the
// text of activity by calling method
if (networkInfo != null && networkInfo.isConnected()) {
Intent intent2 = new Intent(context, MyService.class);
context.startService(intent2);
} else {
Intent intent2 = new Intent(context, MyService.class);
context.stopService(intent2);
}
} catch (Exception e) {
e.printStackTrace();
}

}
}



و سرویس:


public class MyService extends Service {
AlarmManager alarm_manager;
PendingIntent pi;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//TODO do something useful
NextUpdate(intent);
return Service.START_STICKY;
}

@Override
public void onDestroy() {
super.onDestroy();
alarm_manager.cancel(pi);
stopSelf();
}

@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}

private void NextUpdate(Intent intent) {
alarm_manager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Calendar cur_cal = Calendar.getInstance();
pi = PendingIntent.getService(this, 0, new Intent(this, MyService.class), 0);
alarm_manager.setRepeating(AlarmManager.RTC_WAKEUP , cur_cal.getTimeInMillis(), 6000, pi);
ConnectivityManager connectivityManager = (ConnectivityManager) this
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager
.getActiveNetworkInfo();
Toast.makeText(this,"i dont have net", Toast.LENGTH_LONG).show();
}
}



اما مشکلات:
اگر سرویس رو در حالی که برنامه باز هست اجرا کنم، بعد از بسته شدن برنامه هم به فعالیت خودش ادامه میده. اما با قطع/وصل شدن ارتباط دیتا وقتی که برنامه بسته هست تغییری در روند سرویس به واسطه کلاس NetworkChangeReceiver ایجاد نمیشه (هم سرویس و هم این کلاس رجیستر شدن در منیفست).
حالا مشکل از چی هست؟!