xenia/app/src/main/java/space/rocketnine/xenia/XeniaService.java

135 lines
4.5 KiB
Java

package space.rocketnine.xenia;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.util.Base64;
import android.util.Log;
import android.widget.Toast;
import java.util.HashSet;
import java.util.Set;
import space.rocketnine.gmitohtml.Gmitohtml;
public class XeniaService extends Service {
private final String channelID = "space.rocketnine.xenia";
public Context context = this;
private final String channelName = "Xenia";
private final String channelDescription = "Foreground service";
private final Handler handler = new Handler();
private final long timeout = 600; // Seconds
private final Runnable shutDown = () -> {
Intent intent = new Intent(getApplicationContext(), XeniaService.class);
getApplication().stopService(intent);
int pid = android.os.Process.myPid();
android.os.Process.killProcess(pid);
};
private final Runnable checkTimeout = () -> {
if ((System.currentTimeMillis() / 1000) - Gmitohtml.lastRequestTime() >= timeout) {
Toast.makeText(getApplicationContext(), "Shutting Xenia down due to inactivity", Toast.LENGTH_LONG).show();
handler.postDelayed(shutDown, 60000);
return;
}
scheduleCheckTimeout();
};
private void scheduleCheckTimeout() {
handler.postDelayed(checkTimeout, 60000);
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = channelName;
String description = channelDescription;
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(channelID, name, importance);
channel.setDescription(description);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
@Override
public void onCreate() {
Log.d("xenia", "service oncreate");
createNotificationChannel();
Notification.Builder builder = new Notification.Builder(this);
if (Build.VERSION.SDK_INT >= 26) {
builder.setChannelId(channelID);
}
builder.setSmallIcon(R.drawable.ic_stat_name);
builder.setContentText("Xenia is running. Tap to open");
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
builder.setContentIntent(pendingIntent);
startForeground(1337, builder.build());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("xenia", "service starting");
SharedPreferences prefs = getSharedPreferences("xenia", Context.MODE_PRIVATE);
Set<String> sites = prefs.getStringSet("certs", new HashSet<String>());
for (String site : sites) {
try {
String certificate = prefs.getString("cert_" + site, "");
if (!certificate.isEmpty()) {
certificate = new String(Base64.decode(certificate, Base64.DEFAULT));
}
String privateKey = prefs.getString("key_" + site, "");
if (!privateKey.isEmpty()) {
privateKey = new String(Base64.decode(privateKey, Base64.DEFAULT));
}
Gmitohtml.setClientCertificate(site, certificate.getBytes(), privateKey.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
try {
Gmitohtml.startDaemon("127.0.0.1:1967");
} catch (Exception e) {
e.printStackTrace();
}
scheduleCheckTimeout();
// If we get killed, after returning from here, restart
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
@Override
public void onDestroy() {
Log.d("xenia", "service destroyed");
}
}