Commit cde130f7 authored by Teclib's avatar Teclib

refactor(core): refactor job scheduler

Signed-off-by: default avatarTeclib <skita@teclib.com>
parent f66e560f
......@@ -45,6 +45,9 @@ android {
dependencies {
implementation "androidx.work:work-runtime:2.2.0"
implementation 'info.hoang8f:fbutton:1.0.5'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
......
......@@ -84,28 +84,28 @@
android:launchMode="standard"
android:theme="@style/NoActionBar" />
<service
android:name="org.glpi.inventory.agent.service.InventoryService"
android:description="@string/agent_description"
android:enabled="true"
android:icon="@mipmap/ic_launcher"
android:label="Inventory Agent"
tools:ignore="ExportedService">
<intent-filter>
<action android:name="org.glpi.inventory.service" />
</intent-filter>
</service>
<receiver android:name="org.glpi.inventory.agent.broadcast.BootStartAgent">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name="org.glpi.inventory.agent.broadcast.TimeAlarm">
<intent-filter>
<action android:name="org.glpi.inventory.agent.ALARM" />
</intent-filter>
</receiver>
<!--<service
android:name="org.glpi.inventory.agent.service.InventoryService"
android:description="@string/agent_description"
android:enabled="true"
android:icon="@mipmap/ic_launcher"
android:label="Inventory Agent"
tools:ignore="ExportedService">
<intent-filter>
<action android:name="org.glpi.inventory.service" />
</intent-filter>
</service>-->
<receiver android:name="org.glpi.inventory.agent.broadcast.BootStartAgent">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<!--<receiver android:name="org.glpi.inventory.agent.broadcast.TimeAlarm">
<intent-filter>
<action android:name="org.glpi.inventory.agent.ALARM" />
</intent-filter>
</receiver>-->
<activity android:name="org.glpi.inventory.agent.ui.PermissionActivity" />
<activity android:name="org.glpi.inventory.agent.ui.ActivityListServers" />
......
......@@ -66,21 +66,13 @@ public class BootStartAgent extends BroadcastReceiver {
if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
SharedPreferences customSharedPreference = PreferenceManager.getDefaultSharedPreferences(context);
if (customSharedPreference.getBoolean("boot", false)) {
AgentLog.d("Need to start app on StartUp");
AgentLog.d("BOOT -> Need to start app on StartUp");
Intent myIntent = new Intent(context, ActivityMain.class);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
}else{
AgentLog.d("No need to start app on StartUp");
AgentLog.d("BOOT -> No need to start app on StartUp");
}
if(customSharedPreference.getBoolean("autoStartInventory", false)){
AgentLog.d("Need to start service schedule inventory");
alarm.setAlarm(context);
}else{
AgentLog.d("No need to start service schedule inventory");
}
}
}
}
......@@ -70,7 +70,7 @@ public class HomeModel implements Home.Model {
// class name because we want a specific service implementation that
// we know will be running in our own process (and thus won't be
// supporting component replacement by other applications).
InventoryService inventoryService = new InventoryService();
/*InventoryService inventoryService = new InventoryService();
Intent mServiceIntent = new Intent(activity, inventoryService.getClass());
ComponentName result;
......@@ -88,7 +88,7 @@ public class HomeModel implements Home.Model {
}
} else {
AgentLog.log(this, " Agent already started ", Log.ERROR);
}
}*/
}
/**
......
......@@ -44,25 +44,36 @@ import android.widget.ListView;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import org.flyve.inventory.InventoryLog;
import org.glpi.inventory.agent.R;
import org.glpi.inventory.agent.adapter.DrawerAdapter;
import org.glpi.inventory.agent.service.SendInventoryWorker;
import org.glpi.inventory.agent.ui.FragmentAbout;
import org.glpi.inventory.agent.ui.FragmentHelp;
import org.glpi.inventory.agent.ui.FragmentHome;
import org.glpi.inventory.agent.utils.AgentLog;
import org.glpi.inventory.agent.utils.LocalStorage;
import androidx.appcompat.widget.Toolbar;
import androidx.work.BackoffPolicy;
import androidx.work.Constraints;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.NetworkType;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class MainModel implements Main.Model {
private Main.Presenter presenter;
private ArrayList<HashMap<String, String>> arrDrawer;
public static final String TAG_MY_WORK = "inventory_scheduled";
public MainModel(Main.Presenter presenter) {
this.presenter = presenter;
......@@ -70,31 +81,46 @@ public class MainModel implements Main.Model {
@Override
public void setupInventoryAlarm(Context context) {
LocalStorage cache = new LocalStorage(context);
if (cache.getDataBoolean("changeSchedule")) {
Calendar calendar = Calendar.getInstance();
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
String timeInventory = sharedPreferences.getString("timeInventory", "day");
boolean autoStartInventory = sharedPreferences.getBoolean("autoStartInventory", false);
if(!autoStartInventory) {
InventoryLog.d("WORKER -> schedule inventory is disable -> cancel worker if exist");
WorkManager.getInstance(context).cancelAllWorkByTag(TAG_MY_WORK);
return;
}
//day configuration
int interval = 1;
int backOffDelay = 2;
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
String timeInventory = sharedPreferences.getString("timeInventory", "week");
// week by default
if (timeInventory != null && timeInventory.equalsIgnoreCase("week")) {
backOffDelay = 5;
interval = 7;
}
// week by default
if (timeInventory.equalsIgnoreCase("week")) {
calendar.add(Calendar.DATE, 7);
}
// month
if (timeInventory != null && timeInventory.equalsIgnoreCase("month")) {
backOffDelay = 5;
interval = 3;
}
if (timeInventory.equalsIgnoreCase("day")) {
calendar.add(Calendar.DATE, 1);
}
InventoryLog.d("WORKER -> configure worker for "+timeInventory+" interval");
if (timeInventory.equalsIgnoreCase("month")) {
calendar.add(Calendar.DATE, 30);
}
Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.build();
long dateTime = calendar.getTime().getTime();
PeriodicWorkRequest saveRequest =
new PeriodicWorkRequest.Builder(SendInventoryWorker.class, interval, TimeUnit.DAYS)
.setConstraints(constraints)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, backOffDelay, TimeUnit.HOURS) //retry every 2 hours
.build();
cache.setDataLong("data", dateTime);
cache.setDataBoolean("changeSchedule", false);
}
WorkManager.getInstance(context).enqueueUniquePeriodicWork(TAG_MY_WORK, ExistingPeriodicWorkPolicy.REPLACE,saveRequest);
}
public void loadFragment(FragmentManager fragmentManager, Toolbar toolbar, Map<String, String> menuItem) {
......
......@@ -35,6 +35,8 @@
package org.glpi.inventory.agent.preference;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
......@@ -55,6 +57,11 @@ public class GlobalParametersPreference extends PreferenceActivity implements Sh
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//remove notification if exist
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancel(121);
addPreferencesFromResource(R.xml.global_parameters);
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();
......@@ -75,5 +82,9 @@ public class GlobalParametersPreference extends PreferenceActivity implements Sh
AgentLog.d("Preference "+ s +" changed -> " + sharedPreferences.getBoolean(s, false));
}
if ("notif".equals(s)) {
AgentLog.d("Preference "+ s +" changed -> " + sharedPreferences.getBoolean(s, false));
}
}
}
......@@ -81,7 +81,10 @@ public class InventoryParametersPreference extends PreferenceActivity
}
if("autoStartInventory".equals(s)){
Intent intent = new Intent("autoStartInventory");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
AgentLog.d("Preference "+ s +" changed -> " + sharedPreferences.getBoolean(s, false));
}
}
}
package org.glpi.inventory.agent.service;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import org.flyve.inventory.InventoryLog;
import org.flyve.inventory.InventoryTask;
import org.glpi.inventory.agent.R;
import org.glpi.inventory.agent.schema.ServerSchema;
import org.glpi.inventory.agent.utils.AgentLog;
import org.glpi.inventory.agent.utils.Helpers;
import org.glpi.inventory.agent.utils.HttpInventory;
import org.glpi.inventory.agent.utils.LocalPreferences;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
public class SendInventoryWorker extends Worker {
private ArrayList<String> msgError = new ArrayList<>();
private boolean errorOnSendInventory;
private boolean errorOnInventory;
/**
* @param appContext The application {@link Context}
* @param workerParams Parameters to setup the internal state of this worker
*/
public SendInventoryWorker(@NonNull Context appContext, @NonNull WorkerParameters workerParams) {
super(appContext, workerParams);
}
@NonNull
@Override
public Result doWork() {
InventoryLog.d("WORKER -> start inventory");
errorOnInventory = false;
errorOnSendInventory = false;
final Context context = getApplicationContext();
final InventoryTask inventory = new InventoryTask(context.getApplicationContext(), Helpers.getAgentDescription(context), true);
final HttpInventory httpInventory = new HttpInventory(context.getApplicationContext());
final ArrayList<String> serverArray = new LocalPreferences(context).loadServer();
final CountDownLatch countDownLatch = new CountDownLatch(1);
//if server are stored
if (!serverArray.isEmpty()) {
//first step try to load inventory
inventory.getXML(new InventoryTask.OnTaskCompleted() {
@Override
public void onTaskSuccess(String data) {
InventoryLog.d("WORKER -> Inventory completed");
for (String serverName : serverArray) {
final ServerSchema model = httpInventory.setServerModel(serverName);
httpInventory.sendInventory(data, model, new HttpInventory.OnTaskCompleted() {
@Override
public void onTaskSuccess(String data) {
InventoryLog.d("WORKER -> Inventory send");
countDownLatch.countDown();
}
@Override
public void onTaskError(String error) {
InventoryLog.d("WORKER -> Inventory not send");
InventoryLog.d("WORKER -> error : " + error);
msgError.add(error);
errorOnSendInventory = true;
countDownLatch.countDown();
}
});
}
}
@Override
public void onTaskError(Throwable error) {
InventoryLog.d("WORKER -> Inventory error");
InventoryLog.d("WORKER -> error : " + error.getMessage());
AgentLog.e(error.getMessage());
Helpers.sendToNotificationBar(context, context.getResources().getString(R.string.inventory_notification_fail));
errorOnInventory = true;
countDownLatch.countDown();
}
});
}else{
InventoryLog.d("WORKER -> Inventory no server");
Helpers.sendToNotificationBar(context.getApplicationContext(), context.getResources().getString(R.string.no_servers_added));
errorOnInventory =true;
countDownLatch.countDown();
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
Result taskResult;
if(errorOnInventory){
InventoryLog.d("WORKER -> failure");
taskResult = Result.failure();
}else{
if(errorOnSendInventory){
String[] mStringArray = new String[msgError.size()];
mStringArray = msgError.toArray(mStringArray);
for (String s : mStringArray) {
Helpers.sendToNotificationBar(context.getApplicationContext(), s);
}
InventoryLog.d("WORKER -> need to be retry");
taskResult = Result.retry();
}else{
InventoryLog.d("WORKER -> is success");
Helpers.sendToNotificationBar(context.getApplicationContext(), context.getResources().getString(R.string.inventory_notification_sent));
taskResult = Result.success();
}
}
return taskResult;
}
}
......@@ -239,6 +239,10 @@ public class ActivityDetailServer extends AppCompatActivity implements DetailSer
SharedPreferences customSharedPreference = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor = customSharedPreference.edit();
editor.putString("timeInventory", extra_Data.getString("ANDROID_FREQUENCY"));
//send broadcast message
Intent intent = new Intent("timeAlarmChanged");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
editor.putBoolean("autoStartInventory", true);
editor.apply();
}
......@@ -249,7 +253,6 @@ public class ActivityDetailServer extends AppCompatActivity implements DetailSer
SharedPreferences.Editor editor = customSharedPreference.edit();
editor.putBoolean("boot", true);
editor.apply();
}
} catch (Exception ex) {
AgentLog.e(getApplicationContext().getResources().getString(R.string.bad_qr_code_format));
......
......@@ -40,17 +40,14 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
......@@ -61,7 +58,6 @@ import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import org.glpi.inventory.agent.R;
......@@ -69,7 +65,6 @@ import org.glpi.inventory.agent.core.main.Main;
import org.glpi.inventory.agent.core.main.MainPresenter;
import org.glpi.inventory.agent.preference.GlobalParametersPreference;
import org.glpi.inventory.agent.preference.InventoryParametersPreference;
import org.glpi.inventory.agent.service.InventoryService;
import org.glpi.inventory.agent.utils.Helpers;
import org.glpi.inventory.agent.utils.LocalPreferences;
import org.glpi.inventory.agent.utils.LocalStorage;
......@@ -78,16 +73,15 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import io.fabric.sdk.android.Fabric;
public class ActivityMain extends AppCompatActivity
implements Main.View, SharedPreferences.OnSharedPreferenceChangeListener {
implements Main.View{
private Main.Presenter presenter;
private DrawerLayout drawerLayout;
private FragmentManager fragmentManager;
private Toolbar toolbar;
private SharedPreferences sharedPreferences;
//private SharedPreferences sharedPreferences;
private FloatingActionButton mainFab;
private FloatingActionButton btn_settings;
private FloatingActionButton btn_scheduler;
......@@ -95,7 +89,7 @@ public class ActivityMain extends AppCompatActivity
private Animation fab_open, fab_close, fab_clock, fab_anticlock;
private TextView textview_settings, textview_scheduler;
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
/*private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String strTime = intent.getStringExtra("time");
......@@ -105,12 +99,11 @@ public class ActivityMain extends AppCompatActivity
toolbar.setSubtitle("");
}
}
};
};*/
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
new LocalStorage(context).setDataBoolean("changeSchedule", true);
presenter.setupInventoryAlarm(ActivityMain.this);
}
};
......@@ -119,19 +112,18 @@ public class ActivityMain extends AppCompatActivity
@Override
protected void onResume() {
super.onResume();
registerReceiver(broadcastReceiver,new IntentFilter(InventoryService.TIMER_RECEIVER));
//registerReceiver(broadcastReceiver,new IntentFilter(InventoryService.TIMER_RECEIVER));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(broadcastReceiver);
//unregisterReceiver(broadcastReceiver);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Fabric.with(this, new Crashlytics());
setContentView(R.layout.activity_main);
ActivityCompat.requestPermissions(ActivityMain.this,
......@@ -160,8 +152,8 @@ public class ActivityMain extends AppCompatActivity
toolbar = findViewById(R.id.toolbar);
// setup shared preference
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
//sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
//sharedPreferences.registerOnSharedPreferenceChangeListener(this);
presenter = new MainPresenter(this);
Map<String, String> menuItem = presenter.setupDrawer(ActivityMain.this, lst);
......@@ -182,8 +174,6 @@ public class ActivityMain extends AppCompatActivity
}
});
presenter.setupInventoryAlarm(ActivityMain.this);
setSupportActionBar(toolbar);
toolbar.setTitle(R.string.app_name);
......@@ -192,9 +182,15 @@ public class ActivityMain extends AppCompatActivity
drawerLayout.setDrawerListener(mDrawerToggle);
mDrawerToggle.syncState();
//register to scheduled change
IntentFilter timeAlarmChanged = new IntentFilter("timeAlarmChanged");
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, timeAlarmChanged);
//register to auto start change
IntentFilter autoStartInventory = new IntentFilter("autoStartInventory");
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, autoStartInventory);
//FloatActionButton
mainFab = findViewById(R.id.fab);
btn_settings = findViewById(R.id.btn_settings);
......@@ -284,8 +280,8 @@ public class ActivityMain extends AppCompatActivity
@Override
protected void onDestroy() {
super.onDestroy();
sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
//sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
//LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
}
@Override
......@@ -293,7 +289,7 @@ public class ActivityMain extends AppCompatActivity
Helpers.snackClose(ActivityMain.this, message, getString(R.string.permission_snack_ok), true);
}
@Override
/*@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals("autoStartInventory")) {
if (!sharedPreferences.getBoolean("autoStartInventory", false)) {
......@@ -304,7 +300,7 @@ public class ActivityMain extends AppCompatActivity
}
}
}
}
}*/
@Override
public void onBackPressed() {
......
......@@ -56,11 +56,14 @@ import android.widget.Toast;
import com.google.android.material.snackbar.Snackbar;
import org.flyve.inventory.InventoryLog;
import org.flyve.inventory.InventoryTask;
import org.glpi.inventory.agent.R;
import org.glpi.inventory.agent.preference.GlobalParametersPreference;
import org.glpi.inventory.agent.ui.ActivityMain;
import java.io.File;
import java.util.concurrent.atomic.AtomicInteger;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
......@@ -147,37 +150,55 @@ public class Helpers {
}
public static void sendToNotificationBar(Context context, String message) {
Intent resultIntent = new Intent(context, ActivityMain.class);
resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent piResult = PendingIntent.getActivity(context, 0, resultIntent, PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher))
.setContentTitle(context.getResources().getString(R.string.app_name))
.setContentText(message)
.setSound(defaultSoundUri)
.setAutoCancel(true)
.setContentIntent(piResult)
.setPriority(Notification.PRIORITY_HIGH);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {