Um serviço
é um componente de aplicação andróide que representa:
- Uma aplicação que deseja realizar operações de longa duração sem interagir com o usuário.
- Um componente para fornecer funcionalidade a outras aplicações.
Quando devo utilizar um Serviço
?
Utilize um serviço
se você tiver uma operação de longa duração ou uma tarefa que tenha um ciclo de vida longo. É um bom projeto que operações de longa duração sejam executadas em segundo plano.
Um exemplo é uma tarefa de sincronização de dados em segundo plano.
Nesse tipo de tarefa você pode criar um `serviço' que roda periodicamente ou conforme necessário. Você pode fazer uso de um alarme de sistema.
Então, seu "serviço" pode terminar quando a tarefa terminar.
Ao fazer o trabalho em segundo plano, o principal "tópico" fica livre de ter que fazer essas tarefas, impedindo assim que a interface do usuário seja congelada sempre que uma tarefa intensiva estiver sendo executada.
Mesmo que possamos apenas rodar um novo "tópico" mesmo dentro de uma "atividade", uma maneira muito melhor e mais limpa é delegar as operações em segundo plano a um "serviço".
Onde funciona o "Serviço"?
Todos os componentes andróides, incluindo o "serviço", são executados no principal "tópico" do processo de aplicação.
O ciclo de vida do 'Serviço' é diferente do 'Ciclo de vida da atividade'. O primeiro está melhor adaptado para lidar com operações de longa duração do que o segundo.
Uma vez que passamos nossas operações de longa duração a um "fio" de fundo, podemos iniciar e lidar com esse "fio" dentro do "serviço".
Operações de longa duração que não requerem a interação do usuário são o melhor candidato para delegação a um "serviço".
Vantagens de um serviço
.
- O 'Serviço' nos proporciona um mecanismo mais eficiente para desacoplarmos operações de longa duração da interface do usuário.
Exemplo de utilização de um `Serviço'.
(a). Serviços' sem a entrada do usuário
- Aplicativos que utilizam a rede freqüentemente para fazer pesquisas de atualização.
- Aplicativos que tocam música.
- Aplicativo de mensagens.
(b). Serviços com entrada do usuário.
- Aplicação para compartilhamento de fotos.
Rápido Serviço
Snippets e How-to's
1. Como iniciar um `Serviço'.
No primeiro exemplo, nos foi dado o nome da classe:
public static void startService(String className) {
try {
startService(Class.forName(className));
} catch (Exception e) {
e.printStackTrace();
}
}
No segundo exemplo, temos dado a própria Classe e o contexto:
public static void startService(Class<?> cls, Context context) {
Intent intent = new Intent(context, cls);
context.startService(intent);
}
2. Como parar um `Serviço'.
Digamos que você queira parar um serviço
e lhe foi fornecido o nome da classe:
public static boolean stopService(String className) {
try {
return stopService(Class.forName(className));
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
E se a classe em si tiver sido providenciada?
public static boolean stopService(Class<?> cls, Context context) {
Intent intent = new Intent(context, cls);
return context.stopService(intent);
}
3. Como ligar um `Serviço'.
Temos dois exemplos. Aqui está o primeiro:
public static void bindService(String className, ServiceConnection conn, int flags) {
try {
bindService(Class.forName(className), conn, flags);
} catch (Exception e) {
e.printStackTrace();
}
}
então o segundo exemplo:
public static void bindService(Class<?> cls, ServiceConnection conn, int flags,Context context) {
Intent intent = new Intent(context, cls);
context.bindService(intent, conn, flags);
}
4. como desvincular um `Serviço'.
public static void unbindService(ServiceConnection conn,Context context) {
context.unbindService(conn);
}
5. Como colocar Todos em funcionamento `Serviços'.
Você quer obter todos os "serviços" em funcionamento no sistema e retornar seus nomes como um "Conjunto".
public static Set getAllRunningService(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningServiceInfo> info = activityManager.getRunningServices(0x7FFFFFFF);
Set<String> names = new HashSet<>();
if (info == null || info.size() == 0) return null;
for (RunningServiceInfo aInfo : info) {
names.add(aInfo.service.getClassName());
}
return names;
}
Rápido Serviço
Exemplos
1. Como carregar canções em uma "ArrayList" em um "Serviço".
Temos que fazer isso em um "tópico" de fundo, pois não desejamos congelar nossa interface de usuário.
Registraremos estas músicas, mas é claro que você pode renderizá-las em reciclerview ou listview e implementar uma classe para tocá-las.
Primeiro vamos começar definindo um objeto Song. Esta é a nossa classe Song bean:
public final class Song {
private String name;
private String artist;
private String coverUri;
private long time;
private String location;
public String getName() {
return name;
}
public Song setName(String name) {
this.name = name;
return this;
}
public String getArtist() {
return artist;
}
public Song setArtist(String artist) {
this.artist = artist;
return this;
}
public String getCoverUri() {
return coverUri;
}
public Song setCoverUri(String coverUri) {
this.coverUri = coverUri;
return this;
}
public long getTime() {
return time;
}
public Song setTime(long time) {
this.time = time;
return this;
}
public String getLocation() {
return location;
}
public Song setLocation(String location) {
this.location = location;
return this;
}
@Override
public String toString() {
return String.format("name = %s, artist = %s, location = %s",
name,
artist,
location);
}
}
Em seguida, procedemos à criação de nosso "Serviço".
Você começa criando uma classe que implementa o <code>Serviço</code>
`:
public class ScanMusicService extends Service {...}
Normalmente, quando um "serviço" é criado, o método "onCreate()`service' é invocado pelo sistema.
É aqui que iniciaremos um "tópico" que escaneará nossas músicas e as carregará em um "tópico" de fundo:
@Override
public void onCreate() {
super.onCreate();
new Thread(new Runnable() {
@Override
public void run() {
ArrayList<Song> songs = scanSongs(ScanMusicService.this);
LogUtils.d(songs);
ToastUtils.showLongToast(songs.toString());
}
}).start();
}
O método scanSongs()
será responsável por escanear e preencher nosso arrailista com canções.
Aqui está a classe completa:
import android.app.Service;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.IBinder;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import com.jiangkang.tools.bean.Song;
import com.jiangkang.tools.utils.LogUtils;
import com.jiangkang.tools.utils.ToastUtils;
import java.util.ArrayList;
public class ScanMusicService extends Service {
@Override
public void onCreate() {
super.onCreate();
new Thread(new Runnable() {
@Override
public void run() {
ArrayList<Song> songs = scanSongs(ScanMusicService.this);
LogUtils.d(songs);
ToastUtils.showLongToast(songs.toString());
}
}).start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
private ArrayList<Song> scanSongs(Context context) {
ArrayList<Song> result = new ArrayList<>();
ContentResolver resolver = context.getContentResolver();
Cursor cursor = resolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
null,
null,
null,
null);
if (cursor != null && !cursor.isClosed() && cursor.moveToFirst()) {
while (cursor.moveToNext()) {
String songName = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
String location = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
Song song = new Song();
song.setName(songName)
.setArtist(artist)
.setLocation(location);
LogUtils.d(song.toString());
result.add(song);
}
}
return result;
}
}
E essa é a classe para nos ajudar no carregamento de músicas.
2. Como utilizar o System Download Manager e o `Service' para baixar
Queremos ver como criar um serviço
que possa baixar dados utilizando o System DownloadManager.
Vamos direto ao assunto. Primeiro começamos criando um 'serviço' andróide:
public class DownloadService extends Service {
Em seguida, procedemos à criação de vários campos de classe e instância nessa classe:
private BroadcastReceiver receiver;
private DownloadManager dm;
private long enqueue;
private String downloadUrl = "http://192.168.3.186/StaffAssistant.apk";
private static String apkname = "StaffAssistant.apk";
São eles:
- BroadcastReceiver - nossa instância receptora de radiodifusão.
- DownloadManager - nosso gerenciador de download do sistema.
- Enqueue'(longo) - A identificação única de tarefa de download atribuída pelo gerenciador de download do sistema, que pode ser utilizada para consultar ou processar a tarefa de download através desta identificação.
-
Download URL
- url onde baixar o apk.
- ApK name - nome da aplicação
Lembre-se de que estendemos o "serviço" e ainda não implementamos nenhum dos métodos que precisamos anular. Aqui está um:
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
Voltamos "nulos" lá e nos mudamos para nosso onStartCommand()
.
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
....
Lá, antes de mais nada, receberemos nosso fio de url para download via 'Intent'.
Em seguida, instanciaremos nossa classe BroadcastReceiver e substituiremos o método onReceive()
.
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
install(context);
}
};
Dentro do método onReceive()
você pode ver que estamos invocando o método install()
. Esse método é um método personalizado, que criaremos para instalar nossa aplicação.
Fora de nosso método onReceive()
, registraremos nosso BroadcastReceiver, já que é um componente andróide.
registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
É claro que você pode ver que o registramos programmaticamente, já que o criamos como uma classe anônima.
Então, invocamos o método 'startDownload()`, outro método personalizado que criaremos mais tarde.
startDownload ( downloadUrl );
Note que isto requer um cartão SD com permissões de escrita. Se você estiver usando umSDKVersion alvo maior ou igual a 23, então você pode usar a permissão dinâmica.
Vamos agora ver como instalar o aplicativo de forma programática depois de baixá-lo.
Primeiro criamos o método install()
. Ele receberá um objeto Context que nos permitirá invocar o método startActivity()
.
public static void install(Context context) {
Então, instanciamos um java.io.file. Passamos o caminho onde estamos criando o arquivo e o nome do arquivo:
File file = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
, apkname);
Em seguida, criamos um objeto Intent
:
Intent intent = new Intent(Intent.ACTION_VIEW);
Como a atividade
não é iniciada no ambiente Atividade
, defina o seguinte rótulo:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Se a versão está acima da 7.0.
if (Build.VERSION.SDK_INT >= 24) {
Invocamos então o método 'getUriForFile()`getUriForFile' da classe 'FileProvider'. Estes incluem:
- Contexto.
- Endereço do provedor anfitrião.
- O arquivo a ser instalado.
Uri apkUri =
FileProvider.getUriForFile(context, "com.hzecool.slhStaff.fileprovider", file);
//Adding this sentence means temporarily authorizing the file represented by the Uri to the target application.
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive");
}
context.startActivity(intent);
}
Em seguida, nós viemos e anulamos o método onDestroy()
da classe `Service'. Aqui estamos desregistando nosso BroadcastReceiver.
@Override
public void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
Vamos agora ver como fazer o download.
Primeiro vamos criar o método startDownload()
:
private void startDownload(String downUrl) {
Primeiro, vamos buscar o sistema DownloadManager:
dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
Começamos por instantâneo com a classe "DownloadManager.Request". Enquanto instanciamos, analisamos nossa url de download utilizando o método parse()
da classe Uri
, e a passamos para nossa classe Request
:
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downUrl));
Então definimos nosso tipo de mímica ou tipo de arquivo como APK utilizando o método setMimeType()
:
request.setMimeType("application/vnd.android.package-archive");
Em seguida, definimos o destino para nosso download utilizando o setDestinationInExternalPublicDir()
. Neste caso, utilizamos o diretório de downloads.
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, apkname);
Invocamos a setNotificationVisibility()
para indicar se uma notificação será exibida quando o download estiver completo.
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
Então definimos o título
request.setTitle("Download new version");
Por último, mas não menos importante, realizamos o download e devolvemos a identificação única da tarefa
enqueue = dm.enqueue(request);
}
}
Aqui está o código completo do serviço
:
import android.app.DownloadManager;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.content.FileProvider;
import android.text.TextUtils;
import java.io.File;
public class DownloadService extends Service {
private BroadcastReceiver receiver;
private DownloadManager dm;
private long enqueue;
private String downloadUrl = "http://192.168.3.186/StaffAssistant.apk";
private static String apkname = "StaffAssistant.apk";
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
downloadUrl = intent.getStringExtra("downloadUrl");
if (TextUtils.isEmpty(downloadUrl)) {
apkname = downloadUrl.substring(downloadUrl.lastIndexOf("/") + 1, downloadUrl.length());
}
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
install(context);
}
};
registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
startDownload(downloadUrl);
return Service.START_STICKY;
}
public static void install(Context context) {
File file = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
, apkname);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= 24) {
Uri apkUri =
FileProvider.getUriForFile(context, "com.hzecool.slhStaff.fileprovider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive");
}
context.startActivity(intent);
}
@Override
public void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
private void startDownload(String downUrl) {
dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downUrl));
request.setMimeType("application/vnd.android.package-archive");
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, apkname);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setTitle("Download new version");
enqueue = dm.enqueue(request);
}
}
Exemplos completos de "Serviço
Vejamos exemplos totalmente autônomos que você pode baixar e executar.
1. Exemplo de `Serviço' Simples
**MainActivity.java***
Esta é a principal atividade
. Esta classe é derivada da AppCompatActivity e é responsável por nossa interface de usuário.
Aqui estão algumas definições de API que você pode não conhecer:
**(a). SeviceConnection***.
Esta é uma interface que reside no pacote 'android.content' e é destinada ao monitoramento do estado de um aplicativo 'serviço'.
**(b). IBinder***.
O 'IBinder' é a interface base para objetos removíveis, a parte central de um mecanismo leve de chamada de procedimento remoto projetado para alto desempenho ao realizar chamadas em processo e chamadas entre processos.
package com.example.ankitkumar.boundservice;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
BoundService myService;
boolean isBound = false;
TextView currenttime, time, date;
Button btn_start_service;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Set the activity content from a layout resource
setContentView(R.layout.activity_main);
time = (TextView) findViewById(R.id.tv_time);
date = (TextView) findViewById(R.id.tv_date);
currenttime = (TextView) findViewById(R.id.textView_current_time);
btn_start_service = (Button) findViewById(R.id.button_start_service);
Intent intent = new Intent(MainActivity.this, BoundService.class);
/*
Connect to an application service
Automatically create the service as long as the binding exists
*/
bindService(intent, myConnection, Context.BIND_AUTO_CREATE);
}
public void getcurrenttime(View view) {
currenttime.setText(myService.getCurrentTime());
time.setVisibility(View.VISIBLE);
date.setVisibility(View.VISIBLE);
}
//Setting Up BoundService
private ServiceConnection myConnection = new ServiceConnection() {
//Service Connected
public void onServiceConnected(ComponentName className,
IBinder service) {
BoundService.MyLocalBinder binder = (BoundService.MyLocalBinder) service;
myService = binder.getService();
isBound = true;
}
//Service is Disconnected
public void onServiceDisconnected(ComponentName arg0) {
isBound = false;
}
};
}
**BoundService.java***
Esta é nossa subclasse "serviço".
package com.example.ankitkumar.boundservice;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class BoundService extends Service {
//Base interface for a remotable object, the core part of a lightweight remote procedure call mechanism
private final IBinder myBinder = new MyLocalBinder();
//Binding Service
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return myBinder;
}
//Formatting and parsing dates in a locale-sensitive manner
public String getCurrentTime() {
SimpleDateFormat dateformat = new SimpleDateFormat("HH:mm:ss dd/MMM/yyyy", Locale.US);
return (dateformat.format(new Date()));
}
class MyLocalBinder extends Binder {
BoundService getService() {
return BoundService.this;
}
}
}
**activity_main.xml***
O layout principal da `atividade'.
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout
tools_context="com.example.ankitkumar.boundservice.MainActivity" android_background="#efedef" android_layout_height="match_parent" android_layout_width="match_parent" android_id="@+id/activity_main" >
<TextView
android_layout_height="wrap_content" android_layout_width="100sp" android_id="@+id/tv_time" android_visibility="gone" android_textStyle="bold" android_textSize="18sp" android_textColor="@android:color/background_dark" android_text="@string/time" android_gravity="end" android_fontFamily="sans-serif-condensed" android_layout_marginTop="40sp"/>
<TextView
android_layout_height="wrap_content"
android_layout_width="140sp" android_id="@+id/tv_date" android_visibility="gone" android_textStyle="bold" android_textSize="18sp" android_textColor="@android:color/background_dark" android_text="@string/date" android_gravity="bottom" android_fontFamily="sans-serif-condensed" android_layout_marginTop="40sp" android_layout_alignParentRight="true" android_layout_alignParentEnd="true"/>
<TextView
android_layout_height="wrap_content" android_layout_width="match_parent" android_id="@+id/textView_current_time" android_textSize="36sp" android_textColor="#ee6f64" android_gravity="center" android_fontFamily="sans-serif-condensed" android_layout_marginTop="70dp" android_hint="@string/time_label" android_layout_centerHorizontal="true"/>
<Button
android_background="#e54048" android_layout_height="60sp" android_layout_width="200sp" android_id="@+id/button_start_service" android_textStyle="bold" android_textSize="18sp" android_textColor="#ffff" android_text="@string/show_time" android_fontFamily="sans-serif-condensed" android_onClick="getcurrenttime" android_layout_centerInParent="true"/>
</RelativeLayout>
Faça o download do código abaixo.
Não. | Localização | Link | ||
---|---|---|---|---|
1. | GitHub | Download | ||
2. | GitHub | Browse | [GitHub | Browse |
2. | GitHub | Criador Original: @AnkitKumar111 | [GitHub | Criador Original: @AnkitKumar111 |
Android IntentService
public abstract class IntentService
extends Service
java.lang.Object
↳ android.content.Context
↳ android.content.ContextWrapper
↳ android.app.Service
↳ android.app.IntentService
A "IntentService" é uma classe base para "Serviços" que lidam com solicitações assíncronas (expressas como "Intenções") sob demanda. Os clientes enviam solicitações através de chamadas startService(Intent
); o service
é iniciado conforme necessário, trata cada Intent
por sua vez utilizando um thread
de trabalhador, e pára a si mesmo quando ele fica sem trabalho.
Este padrão de "processador de fila de trabalho" é comumente utilizado para descarregar tarefas a partir do "thread" principal de uma aplicação. A classe "IntentService" existe para simplificar este padrão e cuidar da mecânica. Para utilizá-lo, amplie o IntentService
e implemente o onHandleIntent(Intent
). O "IntentService" receberá o "Intents", lançará um "thread" para o trabalhador e interromperá o "serviço" conforme apropriado.
Todas as solicitações são tratadas em um único "tópico" - elas podem levar o tempo necessário (e não bloquearão o loop principal da aplicação), mas apenas uma solicitação será processada de cada vez.