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

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

Войти
Регистрация
Восстановить пароль
Другие темы раздела
Программирование Android Spinner http://www.cyberforum.ru/android-dev/thread1525782.html
В ответе выдает 0, что исправить? import android.os.Bundle; import android.app.Activity; import android.view.View; import android.widget.ArrayAdapter; import android.widget.Button; import...
Программирование Android Нажать кнопку в ListView Понимаю что простой вопрос, но не нашел как. Почти все работает Есть простая разметка состоящая из TextView и Button <?xml version="1.0" encoding="utf-8"?> <LinearLayout... http://www.cyberforum.ru/android-dev/thread1525770.html
Как создать массив который сохраняет свои значение даже после закрытия приложения Программирование Android
Здравствуйте, уважаемые программисты! Не могли бы вы мне помочь? Как создать массив который сохраняет свои значение даже после закрытия приложения? Через методы onStop и onDestroy? Или какая-то...
Программирование Android Запуск BroadcastReceiver без активити
Имеется приложение, включающее в себя единственный класс: public class MyReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { ...
Программирование Android Не обрабатывает касания http://www.cyberforum.ru/android-dev/thread1525469.html
Обрабатывается только нажатие, почему? public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: ...
Программирование Android Получить картинку из ресурсов Вот так приложение получает иконку: android:icon="@drawable/ic_launcher" Вопрос: Как получить картинку так-же, только программно и в Bitmap? подробнее

Показать сообщение отдельно
REALIST07
Автор FAQ
Автор FAQ
176 / 176 / 13
Регистрация: 11.06.2010
Сообщений: 934

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

06.09.2015, 17:28. Просмотров 366. Ответов 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));
    }
}
0
Миниатюры
Небольшая статья об использовании сервиса   Небольшая статья об использовании сервиса  
Вложения
Тип файла: zip MyServiceEx.zip (5.99 Мб, 0 просмотров)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru