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

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

Войти
Регистрация
Восстановить пароль
 
REALIST07
Автор FAQ
Автор FAQ
176 / 176 / 13
Регистрация: 11.06.2010
Сообщений: 932
#1

Небольшая статья об использовании сервиса - Программирование Android

06.09.2015, 17:28. Просмотров 347. Ответов 3
Метки нет (Все метки)

В голову пришла мысль написать небольшую статью по использованию сервисов в Android.
Представленный мной план ниже - это не мое детище,но я готов поделиться с вами им.

Итак давайте напишем 2 метода для сложения и умножения 2 чисел, обработка которых будет происходить в сервисе.
Сервис будет уведомлять об этом класс наследник Application по именни App.
А уже App - класс будет слать уведомления нашей активити.

Вы скажете зачем это нужно,можно и напрямую отдавать ответ в Activity?
Да, можно.
Лично я насчитал 3 причины для того,чтобы отдавать значение в App - класс, а не напрямую:
  1. Для моих задач очень часто бывает потребность в объявлении глобальных переменных контейнеров - кешей,
    наследник Application отлично подходит для этого, так как данные доступны везде и всегда обновлены.
  2. У вас всегда есть доступ к статичному контексту из Application - наследника, так как объявление в активити такого-public static Context - вредит здоровью приложения
  3. Это СПАРТА, детка
)


Модель передачи и приема данных ложится на LocalBroadcastReciever - очень полезная штука.

Что нужно для решения?
Application класс - 1 штука
Service - 1 штука
Service Helper - 1 штука
Activity - 1 штука
LocalBroadcastReciever - 2 штука
Кружка чая - 1 штука
Хорошее настроения - всегда!

Манифест выглядит так:
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
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.nallab.realist07.myserviceex" >
 
    <application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true" >
        </service>
    </application>
 
</manifest>
Создадим обычный бланк проект и поместим ListView,2 EditText и кнопку внутрь основного layout:
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
30
31
32
33
34
35
36
37
38
39
40
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
       android:orientation="vertical" >
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        >
        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:id="@+id/number1"
            android:hint="Введите первое число"/>
        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:id="@+id/number2"
            android:hint="Введите второе число"
            />
    </LinearLayout>
    <Button
        android:layout_width="fill_parent"
        android:layout_height="50dp"
        android:id="@+id/calc"
        android:text="Calculate"/>
   <ListView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:id="@+id/listView">
   </ListView>
    </LinearLayout>
</RelativeLayout>
Далее создадим Service,обычный класс ServiceHelper, класс App - наследник Application

Начнем с сервиса...Вы должны знать, что сервис является частью приложения и работает в том же потоке что и activity.
Ну и что? А то, что если вы будете считать количество звезд на небе в сервисе,то приложение зависнет навсегда.
Поэтому нам нужен другой ручной наш собственный милый поток и Handler!
И еще вот оно как - сервис мы можем запускать сколько нам угодно раз,
и поэтому мы можем запустить сервис с нужными нам параметрами ( для нашей задачи 2 числа) в Intent'e.
Нам нужны публичные статические методы, вызывающие сервис с нужными нам параметрами.
Вот пример моего сервиса:
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
package com.nallab.realist07.myserviceex;
 
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
 
public class MyService extends Service implements Handler.Callback {
    private Handler mHandler; // <-- наш handler для передачи данных в новый поток
 
    public MyService() {
    }
 
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
 
 
    @Override
    public void onCreate() {
 
        // создаем новый поток и связываем Handler наш с ним
        HandlerThread mThread = new HandlerThread("MyServiceThread",
                android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
        mThread.start();
        mHandler = new Handler(mThread.getLooper(), this);
 
 
 
    }
 
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
 
        // тут получаем intent передаваемый при запуске и передаем на обработку в handleMessage
        int method = intent.getIntExtra(ServiceHelper.KEY_METHOD, -1);
        mHandler.sendMessage(mHandler.obtainMessage(method, intent));
        return START_STICKY;
    }
 
    @Override
    public boolean handleMessage(android.os.Message msg) {
 
        // тут обработка вашего запроса в другом потоке в зависимости от типа метода можно обрабатывать все
        int number1,number2;
        int method = msg.what;
 
        switch (method) {
            case ServiceHelper.METHOD_ADD:
                Intent addIntent = (Intent) msg.obj;
                 number1= addIntent.getIntExtra(ServiceHelper.KEY_NUMBER1,0);
                 number2 = addIntent.getIntExtra(ServiceHelper.KEY_NUMBER2, 0);
                _addNumbers(number1,number2);
                break;
            case ServiceHelper.METHOD_MUL:
                Intent mulIntent = (Intent) msg.obj;
                number1 = mulIntent.getIntExtra(ServiceHelper.KEY_NUMBER1,0);
                number2 = mulIntent.getIntExtra(ServiceHelper.KEY_NUMBER2,0);
                _mulNumbers(number1, number2);
                break;
            default:
                break;
        }
 
        return false;
    }
 
    @Override
    public void onDestroy() {
        super.onDestroy();
    }
 
 
 
    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }
 
    @SuppressLint("NewApi")
    @Override
    public void onRebind(Intent intent) {
        super.onRebind(intent);
    }
 
    @Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        // тут можно разрывать соединения, очищать переменные и т.д.
    }
 
    // статические методы которые можно вызывать из активити
    public static void mulNumbers(final Context context,int number1,int number2) {
 
 
        context.startService(ServiceHelper.addInfoToMulMethod(context, number1, number2));
    }
 
    public static void addNumbers(final Context context,int number1,int number2) {
        context.startService(ServiceHelper.addInfoToAddMethod(context, number1, number2));
    }
 
    // а это реальные методы где идет выполнение ваших операции, они скрыты
    private void _mulNumbers(int number1,int number2) {
        int res = number1 *number2;
        ServiceHelper._sendResultToApp(res);
    }
    private void _addNumbers(int number1,int number2) {
        int res = number1 + number2;
        ServiceHelper._sendResultToApp(res);
    }
}
Класс ServiceHelper
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
package com.nallab.realist07.myserviceex;
 
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
 
 
public class ServiceHelper {
    public static final String KEY_METHOD ="KEY_METHOD" ;
 
 
    public static final int METHOD_ADD = 0 ;
    public static final int METHOD_MUL = 1;
 
    public static final String KEY_NUMBER1 ="KEY_NUMBER1" ;
    public static final String KEY_NUMBER2 = "KEY_NUMBER2";
 
    public static final String ACTION_MESSAGE_RESULT_TO_APP ="com.nallab.realist07.myserviceex.RESULT_TO_APP" ;
    public static final String ACTION_MESSAGE_SIGNAL_TO_ACTIVITY = "com.nallab.realist07.myserviceex.RESULT_TO_ACTIVITY";
 
    public static final String RESULT_PARAM = "PARAM" ;
 
 
 
    public static Intent addInfoToMulMethod(final Context context, int number1,
                                            int number2) {
        Intent intent = getMyServiceIntent(context);
        intent.putExtra(KEY_METHOD, METHOD_MUL);
        intent.putExtra(KEY_NUMBER1, number1);
        intent.putExtra(KEY_NUMBER2, number2);
        return intent;
    }
    public static Intent addInfoToAddMethod(final Context context, int number1,
                                            int number2) {
        Intent intent = getMyServiceIntent(context);
        intent.putExtra(KEY_METHOD, METHOD_ADD);
        intent.putExtra(KEY_NUMBER1, number1);
        intent.putExtra(KEY_NUMBER2, number2);
        return intent;
    }
 
 
    public static Intent getMyServiceIntent(final Context context) {
        return new Intent(context,MyService.class);
    }
 
    public static boolean _sendResultToApp(int result) {
        Intent intent = new Intent(ACTION_MESSAGE_RESULT_TO_APP);
        intent.putExtra(RESULT_PARAM, result);
        Context context = App.getAppContext();
        return LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
    }
 
    public static boolean _sendSignalToActivity() {
        Intent intent = new Intent(ACTION_MESSAGE_SIGNAL_TO_ACTIVITY);
        Context context = App.getAppContext();
        return LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
    }
}
Класс App:
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
package com.nallab.realist07.myserviceex;
 
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
 
import java.util.ArrayList;
 
/**
 * Created by Alanches on 05.09.2015.
 */
public class App extends Application {
 
    BroadcastReceiver broadcastReceiver;
 
    //Типа наш кеш
    public static ArrayList<String> results;
 
    public static Context getAppContext() {return context; }
 
    private static Context context;
    @Override
    public void onCreate() {
        super.onCreate();
 
        App.context = getApplicationContext();
        results = new ArrayList<>();
        // ловим сообщение из сервиса
        broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                // ловим результат из сервиса и отправляем в активити
                // тут вы можете делать что угодно - обновлять данные, списки, настройки что угодно
                // я добавлю результат в список results и оповещу активити, что нужно обновить данные
                int res = intent.getIntExtra(ServiceHelper.RESULT_PARAM,0);
               results.add(String.valueOf(res));
                ServiceHelper._sendSignalToActivity();
            }
        };
 
        // регистритруем ресивер на ACTION_MESSAGE_RESULT_TO_APP
        LocalBroadcastManager.getInstance(getAppContext()).registerReceiver(broadcastReceiver,new IntentFilter(ServiceHelper.ACTION_MESSAGE_RESULT_TO_APP));
    }
}
Миниатюры
Небольшая статья об использовании сервиса   Небольшая статья об использовании сервиса  
Вложения
Тип файла: zip MyServiceEx.zip (5.99 Мб, 0 просмотров)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.09.2015, 17:28     Небольшая статья об использовании сервиса
Посмотрите здесь:

Небольшая правка .apk приложения - Программирование Android
У меня простой вопрос переименовываю я .apk файл в zip затем распаковываю. Меняю в архиве картинку либо мелодию и запаковываю обратно. ...

Завершение сервиса - Программирование Android
вот метод завершающий сервис в основной активности: public void onClickStop(View v) { stopService(new Intent(this,...

Управление громкостью из сервиса - Программирование Android
в сервисе воспроизводится звук с некоторыми промежутками, получается клавиши громкости управляют громкостью звука только при...

Восстановление сервиса и Intent - Программирование Android
Добрый день! Разбираюсь с сервисами по одному из интернет уроков, возникла непонятная ситуация. Автор приводит следующий код: public...

Запуск и останов сервиса - Программирование Android
Здравствуйте, поздравляйте с почином, первое сообщение) Вопрос такой: пишу приложение с сервисом, который должен запускаться при старте...

Создание неубиваемого сервиса - Программирование Android
А как можно создать неубиваемый сервис кроме метода startforaground()? Может какой то флаг можно передать в startCommand чтобы он вообще не...

Разбудить телефон из сервиса - Программирование Android
Плиз, помогите. Как из сервиса (IntenetService) разбудить телефон на время выполнения какой-либо задачи (в onHandleIntent)? В чем...

Два сервиса и Notification - Программирование Android
Друзья, в приложении есть сервис, в нем формируется уведомление, в котором есть кнопка с PendingIntent, вызывающая другой сервис, в котором...

Обращение из сервиса к основному (UI) потоку - Программирование Android
как сделать так чтобы из сервиса можно было обращаться к основному потоку в котором находится UI ? изменять UI возможно ли это и если...

Подскажите с работой сервиса в андроид - Программирование Android
вообщем вот у меня есть сервис: import java.util.ArrayList; import java.util.List; import org.apache.http.NameValuePair; ...

Запись в память телефона из сервиса - Программирование Android
Нужно через сервис сохранить файл в память телефона в директорию. Делаю так: if...

Как из сервиса запустить fragment - Программирование Android
Привет друзья в общем у меня есть Сервис который при определенных обстоятельствах должен выводить на экран телефона Fragments, подскажите...


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

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
REALIST07
Автор FAQ
Автор FAQ
176 / 176 / 13
Регистрация: 11.06.2010
Сообщений: 932
06.09.2015, 17:31  [ТС]     Небольшая статья об использовании сервиса #2
Вот мое активити:
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
package com.nallab.realist07.myserviceex;
 
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
 
public class MainActivity extends Activity {
 
 
    BroadcastReceiver receiver;
    ListView lv;
    EditText et1,et2;
    Button btn;
    ArrayAdapter<String> adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        // инициализируем view
        lv = (ListView) findViewById(R.id.listView);
        et1 = (EditText) findViewById(R.id.number1);
        et2 = (EditText) findViewById(R.id.number2);
        btn = (Button) findViewById(R.id.calc);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int n1 = Integer.parseInt(et1.getText().toString());
                int n2 = Integer.parseInt(et2.getText().toString());
 
                // вызов методов сервиса
                MyService.addNumbers(getApplicationContext(),n1,n2);
                MyService.mulNumbers(getApplicationContext(),n1,n2);
            }
        });
        adapter = new ArrayAdapter<String>(getApplicationContext(),android.R.layout.simple_list_item_1,App.results);
 
        lv.setAdapter(adapter);
 
        // также ставим прослушку от App класса о том, что данные изменились
        receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                refreshListView();
            }
        };
 
        // регистрируем на оповещения для ACTION_MESSAGE_SIGNAL_TO_ACTIVITY вы можете сделать это для многих Activity
        LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(receiver, new IntentFilter(ServiceHelper.ACTION_MESSAGE_SIGNAL_TO_ACTIVITY));
 
    }
 
    private void refreshListView() {
 
        adapter.notifyDataSetChanged();
    }
 
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
 
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
 
        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }
 
        return super.onOptionsItemSelected(item);
    }
}
Я думаю сами разберетесь с методами Handlera и LocalBroadcastRecievera.

P.S. Не забудьте прописать в манифесте:
XML
1
2
<application
        android:name=".App"
Tester64
395 / 356 / 43
Регистрация: 22.05.2013
Сообщений: 2,518
06.09.2015, 18:55     Небольшая статья об использовании сервиса #3
В общих чертах мыслите правильно... Но пример выбран плохо. Что значит "складывать" и "умножать". Мало скриншотов (а чужой код читать - лень). Опять-же, насколько я изучил сервисы, аппликейшн использовать не желательно! Он может ДУБЛИРОВАТЬСЯ в памяти! Причин не понял, но ловил несколько раз... Опять-же убийство программы через хоум +слайд убивает аппликейшн и часто убивает и сервис. Перезапуск сервиса через ресивер создает заново аппликэйшн (ловил логами). Повторный запуск программы через иконку еще раз запускает аппликэйшн.
Но для простой программы - сойдет...
REALIST07
Автор FAQ
Автор FAQ
176 / 176 / 13
Регистрация: 11.06.2010
Сообщений: 932
06.09.2015, 19:56  [ТС]     Небольшая статья об использовании сервиса #4
Спасибо,за конструктивные замечания, этот подход подойдет скорее для тех, кому нужно постоянная работа с сервисом, то есть если вам нужно тяжелые операции сделать в сервисе,то для этого есть IntentService, а это можно использовать для уведомлений,поддержки связи с сервером и т.д.

Я пытался хоть как-то разделить основные понятия - UI (Activity) , данные (App) , обработка (Service), это очень простой пример для начинающих
Yandex
Объявления
06.09.2015, 19:56     Небольшая статья об использовании сервиса
Ответ Создать тему
Опции темы

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