Я работаю над функционалом, чтобы получить журналы приложения и загрузить его на сервер.Мы пишем журналы в файл.
Что мне нужно сделать?
Мы использовали ткань (в настоящее время Firebase crashlystics) для отчетов о сбоях.но иногда пропускают множество сбоев.поэтому мы не можем отследить проблему клиента.Мы решили внедрить наш собственный инструмент отчетности о сбоях.Мы решили загрузить логи при запуске приложения без дальнейшей обработки.После сбоя приложения отчет о сбое будет записан в файл, и при следующем запуске приложения этот файл будет загружен на сервер.Я не хочу привязывать пользователя к таким вещам, поэтому я решил сделать это с помощью сервисов.поэтому мне нужно запустить службу, когда приложение запускается, и журналы должны быть загружены на сервер внутри службы без каких-либо проблем.Если сбой приложения после следующей строки запуска службы, служба не должна останавливаться
Что я пробовал?
Я использовал службу для загрузки журналов на сервер.Я попытался запустить службу переднего плана для класса приложения onCreate()
, служба будет работать в другом процессе, и это работает нормально, как и ожидалось.но проблема в том, что, если происходит какой-либо сбой при входе в систему (первая операция) onCreate()
, служба переднего плана не запускается, как ожидалось.Процесс службы останавливается после сбоя.
Что я хочу?
Я хочу запустить службу переднего плана или службу намерений, которая загружает журналы на сервер.и после загрузки логов он остановится.Между тем, если по какой-либо другой причине происходит сбой приложения, служба не должна останавливаться и выполнять свою задачу.
Код
Класс приложения
public void onCreate() {
startLogService()
// Other code
}
private void startLogService() {
Intent serviceIntent = new Intent(this, LogWriteService.class);
/* if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // i have tried with this also
startForegroundService(serviceIntent);
} else {
startService(serviceIntent);
}*/
bindService(serviceIntent, m_serviceConnection, BIND_AUTO_CREATE);
}
LogInActivity
public class LoginActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_initial_login);
int i = 10/0; // just for crash test
}
}
Класс LogSendService (служба Intent)
class LogSendService : IntentService("LogSendService") {
private val NOTIFICATION_ID = 12345
internal var allLogFile: File? = null
override fun onHandleIntent(intent: Intent?) {
createAndShowForegroundNotification(this, NOTIFICATION_ID, "We are gathering logs", true)
writeLogs()
}
private fun createAndShowForegroundNotification(mService: Service, notificationId: Int, message: String, isOnGoing: Boolean) {
val builder = getNotificationBuilder(mService,
"Log Service", // Channel id
NotificationManagerCompat.IMPORTANCE_LOW) //Low importance prevent visual appearance for this notification channel on top
builder.setSmallIcon(R.mipmap.home_icon)
.setContentTitle(mService.getString(R.string.app_name))
.setContentText(message)
if (isOnGoing) {
builder.setOngoing(true)
}
val notification = builder.build()
mService.startForeground(notificationId, notification)
}
private fun writeLogs() {
try {
//log write and upload process
createAndShowForegroundNotification(this, NOTIFICATION_ID, "success", false)
} catch (e: Exception) {
e.printStackTrace()
createAndShowForegroundNotification(this, NOTIFICATION_ID, e.message!!, false)
}
stopForeground(false)
stopSelf()
}
companion object {
val STATUS_FINISHED = 1
fun getNotificationBuilder(context: Context, channelId: String, importance: Int): NotificationCompat.Builder {
val builder: NotificationCompat.Builder
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
prepareChannel(context, channelId, importance)
builder = NotificationCompat.Builder(context, channelId)
} else {
builder = NotificationCompat.Builder(context)
}
return builder
}
@TargetApi(26)
private fun prepareChannel(context: Context, id: String, importance: Int) {
val appName = context.getString(R.string.app_name)
val description = "Testing Log Service"
val nm = context.getSystemService(Activity.NOTIFICATION_SERVICE) as NotificationManager
if (nm != null) {
var nChannel: NotificationChannel? = nm.getNotificationChannel(id)
if (nChannel == null) {
nChannel = NotificationChannel(id, appName, importance)
nChannel.description = description
nm.createNotificationChannel(nChannel)
}
}
}
}
}
Класс LogSendService (служба Foreground)
class LogWriteService : Service() {
private val NOTIFICATION_ID = 12345
internal var allLogFile: File? = null
override fun onBind(intent: Intent): IBinder? {
return null
}
inner class MyBinder : Binder() {
val service: LogWriteService
get() = this@LogWriteService
}
override fun onCreate() {
super.onCreate()
// startLogService();
createAndShowForegroundNotification(this, NOTIFICATION_ID, "We are gathering logs", true)
writeLogs()
}
private fun createAndShowForegroundNotification(yourService: Service, notificationId: Int, message: String, isOnGoing: Boolean) {
val builder = getNotificationBuilder(yourService,
"Log Service", // Channel id
NotificationManagerCompat.IMPORTANCE_LOW) //Low importance prevent visual appearance for this notification channel on top
builder.setSmallIcon(R.mipmap.home_icon)
.setContentTitle(yourService.getString(R.string.app_name))
.setContentText(message)
if (isOnGoing) {
builder.setOngoing(true)
}
val notification = builder.build()
yourService.startForeground(notificationId, notification)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return Service.START_STICKY
}
private fun writeLogs() {
try {
//log write and upload
} catch (e: Exception) {
e.printStackTrace()
createAndShowForegroundNotification(this, NOTIFICATION_ID, e.message!!, false)
}
stopForeground(false)
stopSelf()
}
companion object {
val STATUS_FINISHED = 1
fun getNotificationBuilder(context: Context, channelId: String, importance: Int): NotificationCompat.Builder {
val builder: NotificationCompat.Builder
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
prepareChannel(context, channelId, importance)
builder = NotificationCompat.Builder(context, channelId)
} else {
builder = NotificationCompat.Builder(context)
}
return builder
}
@TargetApi(26)
private fun prepareChannel(context: Context, id: String, importance: Int) {
val appName = context.getString(R.string.app_name)
val description = "Testing Log Service"
val nm = context.getSystemService(Activity.NOTIFICATION_SERVICE) as NotificationManager
if (nm != null) {
var nChannel: NotificationChannel? = nm.getNotificationChannel(id)
if (nChannel == null) {
nChannel = NotificationChannel(id, appName, importance)
nChannel.description = description
nm.createNotificationChannel(nChannel)
}
}
}
}
}
Может кто-нибудь предложить решение?или лучший способ сделать это?
Примечание: некоторые коды на Java, а некоторые на Kotlin