Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

Программирование Android

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.64
bt1024
0 / 0 / 0
Регистрация: 22.10.2012
Сообщений: 31
#1

Написать программу, в которой основную работу производит сервис - Программирование Android

07.01.2014, 00:29. Просмотров 1840. Ответов 13
Метки нет (Все метки)

Здравствуйте.
Возникла задача написать программу в которой основную работу производит сервис. Также требуется Activity для настройки параметров сервиса.
Создал проект с Activity, тут же создал сервис (во всех методах заглушки). Работает.

Собственно не понятно куда писать код самого сервиса. Функция onStartCommand() сказано должна возвращать тип инт (для меня это START_STICKY, что бы ОС запускало сервис в случае сбоев или нехватки памяти). Код START_STICKY будет возвращен системе после отработки функции onStartCommand().
(1) То есть в этой функции нельзя писать длительно исполняющийся код?

(2) Тогда как поступить? У меня только одна идея, в onStartCommand() запустить второй поток и уже писать всё в нем (назовём его исполняющим). Правильно? Тогда как не создавать другие потоки (мне нужен один) при повторных запусках onStartCommand()?

(3) Если в исполняющем потоке надо работать с интернет, все вызовы опять надо заворачивать в AsyncTask?

(4) как тогда из Activity передать данные (настройки работы) в исполняющий поток? В сервис через Bind, а из сервиса в исполняющий поток через handle?

Мои размышления верные? Так и делают или есть более правильные подходы?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.01.2014, 00:29
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Написать программу, в которой основную работу производит сервис (Программирование Android):

Написать программу которая производит сортировку алгоритма - C++
Написать программу которая производит сортировку алгоритма:сортировка пузырьком, сортировка перемешиванием, быстрая сортировка.

Написать перегруженные функции и основную программу, которая их вызывает - C++
Написать перегруженные функции и основную программу, которая их вызывает. а) для массива целых чисел находит количество нечетных...

Написать перегруженные функции и основную программу, которая их вызывает - C++
Написать перегруженные функции и основную программу, которая их вызывает. а) для сложения вещественных чисел; б) для сложения...

Написать перегруженные функции и основную программу, которая их вызывает.В С++ - C++
Задание: а) для вычитания десятичных дробей; б) для вычитания обыкновенных дробей.

Написать перегруженные функции и основную программу, которая их вызывает - C#
Написать перегруженные функции и основную программу, которая их вызывает. а)для сложения вещественных чисел; б) для сложения...

Написать программу, которые производит подсчет суммы элементов вектора, больших числа 7 - MathCAD
с помощью средств программирования в mathcad написать программу, которые производит подсчет суммы элементов вектора, больших числа 7

13
korsaj
148 / 117 / 9
Регистрация: 16.08.2013
Сообщений: 514
07.01.2014, 00:47 #2
http://startandroid.ru/ru/uroki/vse-...oj-primer.html
С этого урока и дальше.
0
angryrobot
Командир зеленых роботов
348 / 285 / 53
Регистрация: 08.10.2013
Сообщений: 564
07.01.2014, 10:43 #3
Цитата Сообщение от bt1024 Посмотреть сообщение
(1) То есть в этой функции нельзя писать длительно исполняющийся код?
Нельзя, но если очень хочется писать именно там, то можно быстренько стартовать новый поток который сделает всю работу.
Цитата Сообщение от bt1024 Посмотреть сообщение
Тогда как поступить?
Можно сделать так как написали вы, или использовать класс IntentService:

Java
1
2
3
4
5
6
7
8
9
10
11
12
public class MySrv extends IntentService {
 
  public MySrv() {
      super("MyThreadName");
      setIntentRedelivery(true);
  }
 
  @Override
  protected void onHandleIntent(Intent intent) {
      System.out.println("Hello from " + Thread.currentThread());
  }
}
Теперь когда вы стартуете сервис при помощи startService, каждый раз вызывается метод onHandleIntent в который передается ваш интент. И при это код выполняется в одном и том же отдельном потоке (см лог):

01-07 10:35:07.615: I/System.out(17408): Hello from Thread[IntentService[MyThreadName],5,main]
01-07 10:35:07.735: I/System.out(17408): Hello from Thread[IntentService[MyThreadName],5,main]
01-07 10:35:07.845: I/System.out(17408): Hello from Thread[IntentService[MyThreadName],5,main]
01-07 10:35:07.975: I/System.out(17408): Hello from Thread[IntentService[MyThreadName],5,main]


(3) Если в исполняющем потоке надо работать с интернет, все вызовы опять надо заворачивать в AsyncTask?
Работать с интернетом можно в любом потоке кроме главного.

как тогда из Activity передать данные (настройки работы) в исполняющий поток?
Да через тот же самый интент например. Способов множество, ведь все потоки находятся в пределах одного процесса, а значит у них общая память с которой все они могут равноправно работать.

В сервис через Bind, а из сервиса в исполняющий поток через handle?
Если нужно передать данные из сервиса в активити я обычно использую Handler, но есть и другие варианты, например через вызов метода sendBroadcast() в сервисе. А в активити настроен бродкаст ресивер который ловит интенты отсылаемые сервисом.
0
bt1024
0 / 0 / 0
Регистрация: 22.10.2012
Сообщений: 31
07.01.2014, 16:50  [ТС] #4
Спасибо, перевариваю инфу..

Добавлено через 15 минут
Цитата Сообщение от angryrobot Посмотреть сообщение
Нельзя, но если очень хочется писать именно там, то можно быстренько стартовать новый поток который сделает всю работу.
Стоп, а где ещё можно писать? Мне не важно где писать код сервиса, лишь бы он работал так как надо мне, а не так как задумали разрабы андроида (капец, сервис есть, а исполняющего потока нет).
Или то и был намек на IntentService?
0
korsaj
148 / 117 / 9
Регистрация: 16.08.2013
Сообщений: 514
07.01.2014, 17:48 #5
Прочтите внимательно уроки что я вам предложил, в них все расписано.
0
bt1024
0 / 0 / 0
Регистрация: 22.10.2012
Сообщений: 31
08.01.2014, 02:00  [ТС] #6
Цитата Сообщение от korsaj Посмотреть сообщение
Прочтите внимательно уроки что я вам предложил, в них все расписано.
прочитаны они, всё равно остались вопросы, потому и создал тему. Примеры безусловно хороши, но они не ложатся на мою программу, а переложить на мою ситуацию сходу не вышло.

Мне надо создать приложение в меню которого можно настраивать параметры. Здесь же есть сервис, который эти параметры читает, а приложение сообщает сервису о изменении настроек. Сервис перечитывает параметры и работает дальше. Всё это пишется как одна программа, Active и отдельно сервис в котором есть BroadcastReceiver. Вся программа будет в классе сервиса в том числе переменные. BroadcastReceiver устанавливает переменную статуса соединения (wifi, mobile, none, etc) далее уже в другом потоке который будет создан скорее всего в OnCreate() надо работать со всем этим. Работа будет в виде, если есть связь, что-то делаем, юзайем инет. Когда всё сделали, надо как то этот поток остановить или приостановить. Из спячки этот поток надо выводить или если пришло нужное сообщение от BroadcastReceiver или пришло сообщение с сети (тут пока не ясно, от сервера, в общем случае от другого компа).
0
angryrobot
Командир зеленых роботов
348 / 285 / 53
Регистрация: 08.10.2013
Сообщений: 564
08.01.2014, 10:55 #7
Цитата Сообщение от bt1024 Посмотреть сообщение
Стоп, а где ещё можно писать?
Если ваш сервис это часть вашего приложения (выполняется в том же процессе) то где угодно :-)
Вы можете создать внутри сервиса любой public метод и вызывать его откуда угодно. Нужно только получить ссылку на ваш сервис.
Цитата Сообщение от bt1024 Посмотреть сообщение
капец, сервис есть, а исполняющего потока нет
Когда я начинал изучать андроид мне тоже показалось это дикостью, но об этом нюансе несколько раз упоминается в гугловской документации.
0
bt1024
0 / 0 / 0
Регистрация: 22.10.2012
Сообщений: 31
08.01.2014, 13:22  [ТС] #8
Написал BroadcastReceiver что бы получать сообщения о подключениях. Было куча ошибок пока не вывел класс в отдельный файл. Если встраиваю этот класс в класс сервиса, андроид не может найти класс ресивера, он почему то ищет именно файл. Пытался подставить в манифесте путь
XML
1
2
3
4
5
6
<receiver android:name=".FService.ConnectivityReceiver">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
            </intent-filter>
        </receiver>
где FService это класс сервиса, ConnectivityReceiver - внутрений класс реализующий приемник.
Андроид ругается, всё равно ищет файл ConnectivityReceiver.java. Как эту проблему преодолеть? Мне желательно сделать его внутренним.

Добавлено через 7 минут
Цитата Сообщение от angryrobot Посмотреть сообщение
Если ваш сервис это часть вашего приложения (выполняется в том же процессе) то где угодно :-)
Вы можете создать внутри сервиса любой public метод и вызывать его откуда угодно. Нужно только получить ссылку на ваш сервис.
А как ссылку получить? Через package и имя класса?

Когда я начинал изучать андроид мне тоже показалось это дикостью, но об этом нюансе несколько раз упоминается в гугловской документации.
Тут можно много ругать их за это, типа видели кривость но всё равно сделали. Почему мне пока не ясно, но истинные причины их философии пока не важны, ибо работать надо
0
angryrobot
Командир зеленых роботов
348 / 285 / 53
Регистрация: 08.10.2013
Сообщений: 564
08.01.2014, 13:41 #9
Цитата Сообщение от bt1024 Посмотреть сообщение
Как эту проблему преодолеть? Мне желательно сделать его внутренним.
Как-то вот так примерно:
Java
1
2
3
4
5
6
7
8
9
10
      BroadcastReceiver br = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            //Ваш код здесь
        }
      };
      IntentFilter intFilter = new IntentFilter();
      intFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
      intFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
      registerReceiver(br, intFilter);
Цитата Сообщение от bt1024 Посмотреть сообщение
А как ссылку получить?
Есть несколько способов, гугловская документация рекомендует делать это так (первые два куска кода в статье). Или можно сделать по-деревенски: в сервисе объявить статическое поле и в момент создания сервиса писать туда this. А потом откуда угодно обращаться к нему.
0
bt1024
0 / 0 / 0
Регистрация: 22.10.2012
Сообщений: 31
08.01.2014, 14:38  [ТС] #10
Цитата Сообщение от angryrobot Посмотреть сообщение
Как-то вот так примерно:
Да пробовал так вчера,

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
NetStateReceiver = new BroadcastReceiver(){
    @Override
    public void onReceive(Context context, Intent intent )
    {
        NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
        if(null != info){
        String stateString = info.toString().replace(',', '\n');
        Toast toast = Toast.makeText(context, stateString, Toast.LENGTH_LONG);
        toast.setGravity(Gravity.CENTER, 0, 0); 
        toast.show();
    }
    }
};
IntentFilter intFilter = new IntentFilter();
intFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
intFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
registerReceiver(NetStateReceiver, intFilter);
Не пойму имя чего регистрировать в манифесте в этом случае? Ругается на всё.
Added: Оказывается ничего не надо . Заработало!
0
korsaj
148 / 117 / 9
Регистрация: 16.08.2013
Сообщений: 514
08.01.2014, 17:30 #11
Ничего вы не читали! Все в указанных мною уроках подробно описано.
0
bt1024
0 / 0 / 0
Регистрация: 22.10.2012
Сообщений: 31
09.01.2014, 21:12  [ТС] #12
Есть метод onReceive BroadcastReceiver-а, в нем я хочу запустить поток.
Написал отдельный Runnable класс.., вообщем для примера:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public WorkTask task; // Runnable class
public Thread r;
 
В 
onCreate(..){
    task = new WorkTask();
    r = new Thread(task);
}
 
@Override
public void onReceive(Context context, Intent intent ){
...
    r.start();
...
}
Получаю ошибку java.lang.RuntimeException: Error receiving broadcast Intent { act=android.net.wifi.WIFI_STATE_CHANGED flg=0x10000010 (has extras) } in com.site.app.FService$1@415dd540
Почему я получаю такую ошибку? Специально сделал отдельный поток, с onReceive() это ни как не связано. Переделал с Handle, тоже самое.
0
Slon747
59 / 37 / 1
Регистрация: 24.08.2013
Сообщений: 438
09.01.2014, 23:12 #13
Цитата Сообщение от bt1024 Посмотреть сообщение
Получаю ошибку java.lang.RuntimeException: Error receiving broadcast Intent { act=android.net.wifi.WIFI_STATE_CHANGED flg=0x10000010 (has extras) } in com.site.app.FService$1@415dd540
Почему я получаю такую ошибку? Специально сделал отдельный поток, с onReceive() это ни как не связано. Переделал с Handle, тоже самое.
Может потому, что должно быть не "android.net.wifi.STATE_CHANGED", а "android.net.wifi.STATE_CHANGE"?
0
bt1024
0 / 0 / 0
Регистрация: 22.10.2012
Сообщений: 31
10.01.2014, 14:26  [ТС] #14
Цитата Сообщение от Slon747 Посмотреть сообщение
Может потому, что должно быть не "android.net.wifi.STATE_CHANGED", а "android.net.wifi.STATE_CHANGE"?
Андроид ругается на эту константу.
Если убрать запуск потока то всё работает как задумано. Но вот с запуском проблемы.

Ошибка исчезает если запуск задачи выполняется в отдельном потоке (не так как я в начале это делал)
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
public void StartWorkThread()
{
    if(ThreadWorking == false){
        ThreadWorking = true;
        new Thread(new Runnable(){
        public void run(){
            task = new WorkTask();
            task.run();
            }
        }).start();
    }else{
        counter++;
        ShowToast(Integer.toString(counter));
    }
}
 
public void run(){
    ShowToast("А я работаю! :)");
    while(isConnected != NET_NONE){
        GetSettings();
        try {
        TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e){
            e.printStackTrace();
        }
    }
    ThreadWorking = false;
    ShowToast("Поток завершен :(");
}
ShowToast() метод который вызывает метод из главного приложения проверяя Bind между сервисом и приложением.
Всё равно получаю ошибку, но другую..
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

Добавлено через 14 минут
вроде разобрался

Добавлено через 12 часов 31 минуту
Долго ли коротко..)) в общем "скелет" написан, заработал как я и хотел и всё написанное "мяско" к нему тоже, всем спасибо за помощь!!! Рутина закончилась (наивный да?), самое интересное и сладкое впереди, писать саму функциональность
0
10.01.2014, 14:26
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.01.2014, 14:26
Привет! Вот еще темы с ответами:

Написать программу, которая создает, редактирует, перезаписывает, удаляет текстовый файл и производит поиск - Delphi
В программе должно быть комментарии в тексте программы и сделать очистку всех объектов ввода текстовой информации. Окно программы должно...

Написать программу, которая подписывает произвольный файл с помощью ЭЦП и производит верификацию подписи - C#
Написать программу, которая подписывает произвольный файл с помощью ЭЦП и производит верификацию подписи. Открытый ключ должен быть помещен...

Какую работу производит сила? - Геометрия
Помогите пожалуйста решить 3 задания 2) Какую работу производит сила F = (2; -1; -4), когда точка её приложения, двигаясь...

Для проверки работы функции написать основную программу, вычисляющую С2 в четвертой степени,С3 в шестой и С2 в шестой - Turbo Pascal
5. Для проверки работы функции написать основную программу, вычисляющую С2 в четвертой степени,С3 в шестой и С2 в шестой..


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru