Skip to content

Commit

Permalink
Fix(core): Fix androdi 14 compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
stonebuzz committed Oct 3, 2024
1 parent d93244c commit f0447a1
Show file tree
Hide file tree
Showing 15 changed files with 485 additions and 807 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:

# Run Instrumentation Tests in Firebase Test Lab
- name: Run Instrumentation Tests in Firebase Test Lab
run: gcloud firebase test android run --type instrumentation --app ${{ env.module_app }}/build/outputs/apk/debug/${{ env.module_app }}-debug.apk --test ${{ env.module_app }}/build/outputs/apk/androidTest/debug/${{ env.module_app }}-debug-androidTest.apk --device model=oriole,version=31,locale=en,orientation=portrait
run: gcloud firebase test android run --type instrumentation --app ${{ env.module_app }}/build/outputs/apk/debug/${{ env.module_app }}-debug.apk --test ${{ env.module_app }}/build/outputs/apk/androidTest/debug/${{ env.module_app }}-debug-androidTest.apk --device model=akita,version=34,locale=en,orientation=portrait


##########################################
Expand Down
17 changes: 5 additions & 12 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ apply plugin: 'com.android.application'
apply plugin: 'com.google.firebase.crashlytics'

android {
compileSdkVersion 34
compileSdk 34
useLibrary 'org.apache.http.legacy'

defaultConfig {
applicationId "org.glpi.inventory.agent"
minSdkVersion 21
targetSdkVersion 34

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}

testOptions {
Expand All @@ -28,19 +30,10 @@ android {
}
}

dexOptions {
preDexLibraries true
maxProcessCount 8
}

namespace 'org.glpi.inventory.agent'
lint {
abortOnError false
}

defaultConfig {
multiDexEnabled true
}
}

dependencies {
Expand All @@ -63,8 +56,8 @@ dependencies {

androidTestImplementation 'tools.fastlane:screengrab:2.1.1'

testImplementation 'org.mockito:mockito-core:2.18.3'
androidTestImplementation 'org.mockito:mockito-android:2.18.3'
testImplementation 'org.mockito:mockito-android:5.5.0' // Use the latest version
androidTestImplementation 'org.mockito:mockito-android:5.5.0'

implementation 'androidx.test.espresso:espresso-idling-resource:3.6.1'
implementation fileTree(dir: 'libs', include: ['*.jar'])
Expand Down
30 changes: 10 additions & 20 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:versionCode="39403"
android:versionName="">
xmlns:tools="http://schemas.android.com/tools"
android:versionCode="39413"
android:versionName="">

<!-- Permissions -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
Expand All @@ -30,9 +31,6 @@ android:versionName="">
<!-- Allows changing locales -->
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION"/>

<!-- Apps wanting to use foreground services, API 28 higher -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

<application android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:largeHeap="true" android:name="org.glpi.inventory.agent.ui.InventoryAgentApp" android:requestLegacyExternalStorage="true" android:roundIcon="@drawable/ic_launcher_round" android:theme="@style/AppTheme" android:vmSafeMode="true">

<uses-library android:name="org.apache.http.legacy" android:required="false"/>
Expand All @@ -56,12 +54,6 @@ android:versionName="">
<activity android:label="@string/app_name" android:name="org.glpi.inventory.agent.preference.GlobalParametersPreference"/>
<activity android:label="@string/app_name" android:launchMode="standard" android:name="org.glpi.inventory.agent.ui.ActivityInventoryReport" android:theme="@style/NoActionBar"/>

<service android:description="@string/agent_description" android:enabled="true" android:exported="true" android:icon="@mipmap/ic_launcher" android:label="Inventory Agent" android:name="org.glpi.inventory.agent.service.InventoryService" tools:ignore="ExportedService">
<intent-filter>
<action android:name="org.glpi.inventory.service"/>
</intent-filter>
</service>

<receiver android:enabled="true" android:exported="true" android:name="org.glpi.inventory.agent.broadcast.BootStartAgent" android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
Expand All @@ -72,21 +64,19 @@ android:versionName="">
<action android:name="android.intent.action.ACTION_SHUTDOWN"/>
</intent-filter>
</receiver>
<receiver android:exported="true" android:name="org.glpi.inventory.agent.broadcast.TimeAlarm">
<intent-filter>
<action android:name="org.glpi.inventory.agent.ALARM"/>
</intent-filter>
</receiver>

<service android:name=".broadcast.InventoryJobScheduler"
android:enabled="true"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE"/>

<activity android:name="org.glpi.inventory.agent.ui.PermissionActivity"/>
<activity android:name="org.glpi.inventory.agent.ui.ActivityListServers"/>
<activity android:exported="true" android:name="org.glpi.inventory.agent.ui.ActivityDetailServer">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>

<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>

<data android:host="glpi-project.github.io" android:pathPrefix="/android-inventory-agent/deeplink"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
Expand All @@ -96,4 +86,4 @@ android:versionName="">
<activity android:name="org.glpi.inventory.agent.ui.ActivityCategories"/>
</application>

</manifest>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -38,53 +38,16 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.preference.PreferenceManager;
import android.widget.Toast;

import org.flyve.inventory.InventoryLog;
import org.glpi.inventory.agent.service.InventoryService;
import org.glpi.inventory.agent.ui.ActivityMain;
import org.glpi.inventory.agent.utils.AgentLog;

public class BootStartAgent extends BroadcastReceiver {

TimeAlarm alarm = new TimeAlarm();

/**
* It sets an alarm after the user has finished booting
* @param context in which the receiver is running
* @param intent being received
*/
@Override
public void onReceive(Context context, Intent intent) {

String action = intent.getAction();
if(action==null) {
return;
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Intent activityIntent = new Intent(context, ActivityMain.class);
activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(activityIntent);
}

SharedPreferences customSharedPreference = PreferenceManager.getDefaultSharedPreferences(context);
if (customSharedPreference.getBoolean("boot", false)) {
try {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Intent myIntent = new Intent(context, InventoryService.class);
context.startForegroundService(myIntent);
} else {
Intent myIntent = new Intent(context, ActivityMain.class);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
}
}catch(Exception ex) {
Toast.makeText(context, ex.getMessage(), Toast.LENGTH_LONG).show();
}
}

if(customSharedPreference.getBoolean("autoStartInventory", false)){
alarm.setAlarm(context);
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/**
* ---------------------------------------------------------------------
* GLPI Android Inventory Agent
* Copyright (C) 2019 Teclib.
*
* https://glpi-project.org
*
* Based on Flyve MDM Inventory Agent For Android
* Copyright © 2018 Teclib. All rights reserved.
*
* ---------------------------------------------------------------------
*
* LICENSE
*
* This file is part of GLPI Android Inventory Agent.
*
* GLPI Android Inventory Agent is a subproject of GLPI.
*
* GLPI Android Inventory Agent is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* GLPI Android Inventory Agent is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* ---------------------------------------------------------------------
* @copyright Copyright © 2019 Teclib. All rights reserved.
* @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html
* @link https://github.com/glpi-project/android-inventory-agent
* @link https://glpi-project.org/glpi-network/
* ---------------------------------------------------------------------
*/

package org.glpi.inventory.agent.broadcast;

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.preference.PreferenceManager;
import android.provider.Settings;

import androidx.core.app.NotificationCompat;

import org.flyve.inventory.InventoryTask;
import org.glpi.inventory.agent.R;
import org.glpi.inventory.agent.schema.ServerSchema;
import org.glpi.inventory.agent.ui.ActivityMain;
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.Calendar;

@SuppressLint("SpecifyJobSchedulerIdRange")
public class InventoryJobScheduler extends JobService {

public static final int INVENTORY_JOB_ID = 4492015;
private static final String NOTIFICATION_CHANNEL_ID = "org.glpi.inventory.agent";

@Override
public boolean onStartJob(final JobParameters params) {
HandlerThread handlerThread = new HandlerThread("SomeOtherThread");
handlerThread.start();

Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable() {
@Override
public void run() {
AgentLog.d("GLPI-AGENT-JOBSCHEDULER : Run task" + Calendar.getInstance().getTime());
doInventory();
jobFinished(params, true);
}
});

return true;
}

private void doInventory() {
Context context = getApplicationContext();
AgentLog.d("GLPI-AGENT-JOBSCHEDULER : Launch inventory from JobScheduler " + Calendar.getInstance().getTime());

// check if autoStartInventory is deactivated
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
if (!sharedPreferences.getBoolean("autoStartInventory", false)) {
AgentLog.d("GLPI-AGENT-JOBSCHEDULER : The inventory will not be send, is deactivated");
return;
}

showPersistentNotification();

final InventoryTask inventory = new InventoryTask(context.getApplicationContext(), Helpers.getAgentDescription(context), true);
final HttpInventory httpInventory = new HttpInventory(context.getApplicationContext());
ArrayList<String> serverArray = new LocalPreferences(context).loadServer();
if (!serverArray.isEmpty()) {
for (final String serverName : serverArray) {
final ServerSchema model = httpInventory.setServerModel(serverName);
inventory.setTag(model.getTag());
inventory.setAssetItemtype(model.getItemtype());
inventory.getXML(new InventoryTask.OnTaskCompleted() {
@Override
public void onTaskSuccess(String data) {
ServerSchema model = httpInventory.setServerModel(serverName);
if(!model.getSerial().trim().isEmpty()) {
data = data.replaceAll("<SSN>(.*)</SSN>","<SSN>" + model.getSerial() + "</SSN>");
}
httpInventory.sendInventory(data, model, new HttpInventory.OnTaskCompleted() {
@Override
public void onTaskSuccess(String data) {
AgentLog.d("GLPI-AGENT-JOBSCHEDULER : Inventory Success");
Helpers.sendToNotificationBar(context.getApplicationContext(), context.getResources().getString(R.string.inventory_notification_sent));
//Helpers.sendAnonymousData(context.getApplicationContext(), inventory);
}

@Override
public void onTaskError(String error) {
AgentLog.d("GLPI-AGENT-JOBSCHEDULER : Inventory error");
Helpers.sendToNotificationBar(context.getApplicationContext(), context.getResources().getString(R.string.inventory_notification_fail));
AgentLog.e(error);
}
});
}

@Override
public void onTaskError(Throwable error) {
AgentLog.e(error.getMessage());
Helpers.sendToNotificationBar(context, context.getResources().getString(R.string.inventory_notification_fail));
}
});
}
} else {
AgentLog.d("GLPI-AGENT-JOBSCHEDULER : " + context.getResources().getString(R.string.inventory_no_server));
}
}

@Override
public boolean onStopJob(final JobParameters params) {
AgentLog.d("GLPI-AGENT-JOBSCHEDULER : onStopJob() was called");
return true;
}

private void showPersistentNotification() {
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

// create channel if needed
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel chan = null;
chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, getString(R.string.app_is_running), NotificationManager.IMPORTANCE_DEFAULT);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
manager.createNotificationChannel(chan);
}

// create intent to redirect to notification to settings
Intent notificationIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationIntent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
notificationIntent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
notificationIntent.putExtra(Settings.EXTRA_CHANNEL_ID, NOTIFICATION_CHANNEL_ID);
notificationIntent.putExtra("app_package", getPackageName());
notificationIntent.putExtra("app_uid", getApplicationInfo().uid);
notificationIntent.putExtra("android.provider.extra.APP_PACKAGE", getPackageName());
} else {
notificationIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
notificationIntent.setData(Uri.parse("package:" + getPackageName()));
}
PendingIntent notificationPendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);


Intent appIntent = new Intent(this, ActivityMain.class);
appIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent appIntentRedirect = PendingIntent.getActivity(this, 0, appIntent, PendingIntent.FLAG_IMMUTABLE);

// create notification
NotificationCompat.Builder notification = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
notification.setOngoing(false);
notification.setSmallIcon(R.drawable.ic_stat);
notification.setContentTitle(getString(R.string.app_is_running));
notification.setContentText(getString(R.string.agent_description));
notification.setCategory(Notification.CATEGORY_EVENT);
notification.setPriority(NotificationCompat.PRIORITY_DEFAULT);
notification.setStyle(new NotificationCompat.BigTextStyle().bigText(getString(R.string.app_is_running_extend)));
notification.setContentIntent(appIntentRedirect);
notification.addAction(R.drawable.ic_stat, getString(R.string.disable_notification), notificationPendingIntent);

// notify
manager.notify(1, notification.build());
}
}
Loading

0 comments on commit f0447a1

Please sign in to comment.