Форум программистов, компьютерный форум, киберфорум
Программирование Android
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.83/65: Рейтинг темы: голосов - 65, средняя оценка - 4.83
12 / 10 / 5
Регистрация: 27.08.2015
Сообщений: 236
1

Неубиваемый Service Android

25.10.2016, 12:11. Показов 12196. Ответов 31
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день.
В общем хочу написать приложение, которое мониторит заряд батареи и в случае определенного уровня заряда, присылает notification пользователю.
Проблема состоит в том, что мой "неубиваемый" сервис, получился убиваемым. Т.е. не работает ни после перезагрузки, ни после закрытия приложения.
Вот основной код:

AndroidManifest.xml:

Кликните здесь для просмотра всего текста

XML
1
2
3
4
5
6
7
8
9
10
11
 <service
        android:name=".NotificationService"
        android:enabled="true"
        android:exported="true"
        android:process=":AlarmBattery"/>
 
    <receiver android:name="ardel.batteryalarm.BootReceiver">
        <intent-filter>
            <action android:name = "android.intent.action.BOOT_COMPLETED"/>
        </intent-filter>
    </receiver>



BootReceiver.java
Кликните здесь для просмотра всего текста

Java
1
2
3
4
5
6
7
8
9
public class BootReceiver extends BroadcastReceiver {
public BootReceiver() {}
 
@Override
public void onReceive(Context context, Intent intent) {
    Intent serviceIntent = new Intent(context, NotificationService.class);
    context.startService(serviceIntent);
}
}


MainActivity.java(основная часть кода):
Кликните здесь для просмотра всего текста

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
protected void onCreate(Bundle savedInstanceState) {
 
    intentService = new Intent(this,NotificationService.class);
    registerReceiver(this.mBatInfoReceiver, new    IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}
 
private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context c, Intent intent) {
        int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
        if (level <= 50) {
            notification(level);
        }
        int voltage = intent.getIntExtra("voltage", 0);
        int temperature = intent.getIntExtra("temperature", 0);
        int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
        boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                status == BatteryManager.BATTERY_STATUS_FULL;
        batteryLevel.setText("Battery Status: " + String.valueOf(level) + "% " + isCharging);
        voltageLevel.setText("Battery Voltage: " + String.valueOf(voltage));
        double temps = (double)temperature / 10;
        temperatureLevel.setText("Battery Temperature: " + String.valueOf(temps));
 
    }
};
 
private void notification(int level) {
        startService(intentService);
}
 
@Override
    protected void onStop()
    {
        unregisterReceiver(mBatInfoReceiver);
        super.onStop();
    }


NotificationService.java:
Кликните здесь для просмотра всего текста

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class NotificationService extends Service {
NotificationManager manager;
private static final int NOTIFY_ID = 101;
 
@Override
public void onCreate() {
    super.onCreate();
    manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    setNotification();
 
}
 
private void setNotification() {
    Context context = getApplicationContext();
 
    Intent notificationIntent = new Intent(context, MainActivity.class);
    PendingIntent contentIntent = PendingIntent.getActivity(context,
            0, notificationIntent,
            PendingIntent.FLAG_CANCEL_CURRENT);
 
    Resources res = context.getResources();
    Notification.Builder builder = new Notification.Builder(context);
 
    builder.setContentIntent(contentIntent)
            .setSmallIcon(R.drawable.battery)  
            .setTicker("Msg")
            .setWhen(System.currentTimeMillis())
            .setAutoCancel(true)
 
            .setContentTitle("Msg1")
 
            .setContentText("Msg2а");
 
    Notification notification = builder.build();
 
    NotificationManager notificationManager = (NotificationManager) context
            .getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(NOTIFY_ID, notification);
}
 
public IBinder onBind(Intent arg0) {
    return null;
}
}


Буду очень-очень благодарен любой помощи
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.10.2016, 12:11
Ответы с готовыми решениями:

Android и Web Service
Написал веб сервис который формирует массив из трех значений, нужно написать андроид приложение,...

Таймер, AlarmManager и Service на Android
Добрый вечер. Я уже создавал тем(ы) про таймер. И мне очень здорово помогли разобраться с...

Android Service, работающий даже после выключения пользователем приложения
Столкнулся со следующей проблемой: нужно чтобы Service работал даже после выключения пользователем...

[android] Нет пункта Android Service
Всем привет! Пробую создать сервис для андроида на delphi XE7. В хелпе сказано добавить так: File...

31
12 / 10 / 5
Регистрация: 27.08.2015
Сообщений: 236
28.10.2016, 16:37  [ТС] 21
Author24 — интернет-сервис помощи студентам
shavuz, до сих пор борюсь с этой проблемой.
Уже переписал сервис пару раз, но результат пока не очень:

Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public class NotificationService extends Service {
 
    private NotificationManager notificationManager;
    public static final int DEFAULT_NOTIFICATION_ID = 101;
 
    @Override
    public void onCreate() {
        super.onCreate();
        notificationManager = (NotificationManager) this.getSystemService(NOTIFICATION_SERVICE);
        this.registerReceiver(this.mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
 
    }
 
 
    public int onStartCommand(Intent intent, int flags, int startId) {
 
        return START_STICKY;
 
    }
 
        BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
 
                int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
                int chargeState = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
 
                int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
                boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                        status == BatteryManager.BATTERY_STATUS_FULL;
 
                switch (chargeState) {
                    case BatteryManager.BATTERY_STATUS_CHARGING:
 
                        if (isCharging) {
 
                            NotificationCompat.Builder builder = new NotificationCompat.Builder(NotificationService.this)
                                    .setContentTitle("Charging...")
                                    .setContentText("Battery level is: " + Integer.toString(level))
                                    .setSmallIcon(android.R.drawable.stat_notify_chat);
 
                            Notification notification = builder.build();
                            notification.defaults |= Notification.DEFAULT_VIBRATE;
                            notification.defaults |= Notification.DEFAULT_SOUND;
 
                            startForeground(DEFAULT_NOTIFICATION_ID, notification);
 
                        }
                        break;
 
                    case BatteryManager.BATTERY_STATUS_FULL:
 
                        break;
                    case BatteryManager.BATTERY_STATUS_DISCHARGING:
 
                        break;
                }
 
            }
        };
 
 
       @Override
        public void onDestroy () {
            super.onDestroy();
 
            notificationManager.cancel(DEFAULT_NOTIFICATION_ID);
            this.unregisterReceiver(this.mBatteryInfoReceiver);
 
            //Disabling service
            stopSelf();
        }
 
 
    public IBinder onBind(Intent intent) {
        return null;
    }
 
 
 
}


StackOverflow особо не помог. Только посоветовали вот эту статью. Еще пользовался , который якобы работает, но тоже безрезультатно. Я уже не знаю что еще можно сделать...
0
114 / 120 / 26
Регистрация: 29.01.2014
Сообщений: 609
28.10.2016, 17:20 22
уберите стопитселф. позже попробую сам написать.
0
12 / 10 / 5
Регистрация: 27.08.2015
Сообщений: 236
28.10.2016, 17:22  [ТС] 23
shavuz, тоже не помогло.
0
114 / 120 / 26
Регистрация: 29.01.2014
Сообщений: 609
28.10.2016, 18:19 24
щас пробую

Добавлено через 53 минуты
так.. вещи о которых забыли. прописать в манифесте разрешения и сервис
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.batteryservice">
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
 
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <service
            android:name=".BatteryService"
            android:label="@string/app_name">
        </service>
        <receiver android:name=".RestartReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
    </application>
 
</manifest>

вот остальной проект. вроде работает:классы мейн, сервис и ресивер перезагрузки:
ресивер батарейки в сервисе
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package com.batteryservice;
 
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
 
public class MainActivity extends AppCompatActivity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(this, BatteryService.class);
        startService(intent);
    }
}
 
 
package com.batteryservice;
 
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
 
public class RestartReceiver extends BroadcastReceiver
{
    public static final String LOG_TAG = RestartReceiver.class.getSimpleName();
    @Override
    public void onReceive(Context context, Intent intent)
    {
        Log.i(LOG_TAG, "Receiver BOOT_COMPLETED");
        Intent i = new Intent(context, BatteryService.class);
        context.startService(i);
    }
}
package com.batteryservice;
 
import android.app.Notification;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
 
 
public class BatteryService extends Service
{
    private static final int DEFAULT_NOTIFICATION_ID = 101;
 
    @Override
    public void onCreate()
    {
        super.onCreate();
        this.registerReceiver(this.mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
    }
 
    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        return START_STICKY;
    }
 
    @Nullable
    @Override
    public IBinder onBind(Intent intent)
    {
        return null;
    }
 
    BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver()
    {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
            int chargeState = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
 
            int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
            boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                    status == BatteryManager.BATTERY_STATUS_FULL;
 
 
            switch (chargeState)
            {
                case BatteryManager.BATTERY_STATUS_CHARGING:
 
                    if (isCharging)
                    {
 
                        NotificationCompat.Builder builder = new NotificationCompat.Builder(BatteryService.this)
                                .setContentTitle("Charging...")
                                .setContentText("Battery level is: " + Integer.toString(level))
                                .setSmallIcon(android.R.drawable.stat_notify_chat);
 
                        Notification notification = builder.build();
                        notification.defaults |= Notification.DEFAULT_VIBRATE;
                        notification.defaults |= Notification.DEFAULT_SOUND;
                        startForeground(DEFAULT_NOTIFICATION_ID, notification);
 
                    }
                    break;
 
                case BatteryManager.BATTERY_STATUS_FULL:
 
                    break;
                case BatteryManager.BATTERY_STATUS_DISCHARGING:
                    break;
            }
        }
    };
 
    @Override
    public void onDestroy()
    {
        super.onDestroy();
        this.unregisterReceiver(this.mBatteryInfoReceiver);
    }
 
}
обратите внимание что у вас посылаются пушки только когда заряжается.
0
Автор FAQ
Автор FAQ
200 / 199 / 21
Регистрация: 11.06.2010
Сообщений: 1,024
28.10.2016, 20:11 25
Очевидность, если ваш сервис убивают, значит при убийстве вам нужен запрос на воскрешение, для этого есть 2 метода:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
    public void onDestroy()
    {
        super.onDestroy();
        this.unregisterReceiver(this.mBatteryInfoReceiver);
        // перезапуск сервиса
    }
 
@Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
       // перезапуск сервиса
    }
Добавлено через 52 секунды
И еще я бы добавил вот такую строчку в декларацию ресивера:
XML
1
 <action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
0
114 / 120 / 26
Регистрация: 29.01.2014
Сообщений: 609
28.10.2016, 20:57 26
REALIST07, не могли бы показать пример такого сервиса который презапускается через ондестрой?
0
12 / 10 / 5
Регистрация: 27.08.2015
Сообщений: 236
28.10.2016, 21:41  [ТС] 27
REALIST07, в декларацию ресивера уже добавил
XML
1
2
3
<action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.QUICKBOOT_POWERON" />
                <action android:name="android.intent.action.REBOOT"/>
Спасибо, как раз сегодня вечером начал копать в направлении данных методов.
shavuz, тоже большое спасибо за потраченное время, у меня получился код, почти один в один с вашим (только в манифесте больше всего расписано)
0
114 / 120 / 26
Регистрация: 29.01.2014
Сообщений: 609
28.10.2016, 22:09 28
XML
1
2
      <action android:name="android.intent.action.QUICKBOOT_POWERON" />
                <action android:name="android.intent.action.REBOOT"/>
мне кажется что эти два лишние, буткомплитед их покрывает
0
12 / 10 / 5
Регистрация: 27.08.2015
Сообщений: 236
28.10.2016, 22:32  [ТС] 29
REALIST07, т.е. нужно сделать что-то типа такого?:

Java
1
2
3
4
5
6
7
8
9
10
@Override
        public void onDestroy () {
            super.onDestroy();
 
            notificationManager.cancel(DEFAULT_NOTIFICATION_ID);
            this.unregisterReceiver(this.mBatteryInfoReceiver);
 
           Intent restartService = new Intent(this,getClass());
           startService(restartService);
        }
0
90 / 89 / 23
Регистрация: 08.07.2014
Сообщений: 548
29.10.2016, 13:54 30
Я дико извиняюсь, что вклиниваюсь в вашу увлекательную беседу, просто хотелось бы заметить, что вызов метода onDestroy() отнюдь не гарантируется при остановке сервиса.
0
114 / 120 / 26
Регистрация: 29.01.2014
Сообщений: 609
29.10.2016, 15:55 31
korshun84, я по этому и просил пример
0
Автор FAQ
Автор FAQ
200 / 199 / 21
Регистрация: 11.06.2010
Сообщений: 1,024
29.10.2016, 18:05 32
korshun84, именно поэтому 2 метода, если система прихлопнет его,то обязательно сообщит об этом в onTaskRemoved
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
    public void onDestroy()
    {
        super.onDestroy();
        this.unregisterReceiver(this.mBatteryInfoReceiver);
        // перезапуск сервиса
       startService(new Intent(context, Service.class));
    }
 
@Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        // перезапуск сервиса
        startService(new Intent(context, Service.class));
    }
0
29.10.2016, 18:05
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.10.2016, 18:05
Помогаю со студенческими работами здесь

A Windows service with the name MySQL already exists. Please uninstall this service correctly or choose a different name for the new service.
Не знаю что делать дальше

Создание Android Service (background application) на Qt (QML)
Доброго времени суток, друзья. Помогите разобраться с проблемой. Есть рабочее приложение для...

Авторизация в RestFull Service через Android app
Здравствуйте. Есть простой RestFull Service на Spring MVC + Spring Security + Jersey. Написал...

Олицетворение (impersonating) системных учетных записей (NETWORK SERVICE, LOCAL SERVICE и пр.)
Возникла необходимость олицетворения потоком произвольной учетной записи, в т.ч. и системной....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
32
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru