android core aula 7 - aplicações (services, broadcast receivers, ndk/jni)
DESCRIPTION
Última aula de Android Core, sobre aplicações. Nesta aula veremos conceitos e implementações de Services, Broadcasts receivers e código nativo, utilizando NDK e JNI.TRANSCRIPT
![Page 1: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/1.jpg)
Android Core
Felipe Silveirafelipesilveira.com.br Aula 7
![Page 2: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/2.jpg)
Aplicações II
![Page 3: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/3.jpg)
Services
![Page 4: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/4.jpg)
Services
Service é um dos componentes principais da plataforma Android.
● Executado em background
● Sem interface com o usuário
● Sua execução continua mesmo quando o usuário inicia outra aplicação.
![Page 5: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/5.jpg)
Services
Dois principais tipos:
● Started: são services iniciados através de outros componentes (activities, por exemplo) através do método startService(). Após o seu início, o serviço pode continuar sendo executado indefinidamente.
![Page 6: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/6.jpg)
Services
● Bound: são services iniciados através do método bindService(). Os Bound Services interagem com os outros componentes através de uma interface cliente-servidor, que inclusive podem ocorrer entre diferentes processos (IPC).Um Bound Service é executado enquanto possui requisições a serem tratadas.
![Page 7: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/7.jpg)
Services
O que um Service NÃO é:
● Um service NÃO é um processo separado. Ele pode ser executado em um processo separado, mas por padrão não é.
● Um service NÃO é um thread separada. Por padrão, seu código é executado na Main Thread.
![Page 8: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/8.jpg)
Services
Ciclo de vida
![Page 9: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/9.jpg)
Services package android.helloworld.sync;
import android.app.Service;import android.content.Intent;import android.os.AsyncTask;import android.os.IBinder;
public class QuickNotesSyncService extends Service {
@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {
new SyncDataTask().execute();return START_NOT_STICKY;
}
@Overridepublic IBinder onBind(Intent arg0) {
// Neste exemplo, iremos supor que o service sera invocado apenas// atraves de startService()return null;
}
private class SyncDataTask extends AsyncTask<Void, Integer, Void> {protected Void doInBackground(Void... p) {
DataSync d = new DataSync(QuickNotesSyncService.this);d.syncPendingNotes();return null;
}}}
Exemplo de implementação:
QuickNotesSyncService.java
![Page 10: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/10.jpg)
Services
Após implementar a classe filha de Service, é necessário registrar o serviço no AndroidManifest:
<application
android:icon="@drawable/icon"
android:label="QuickNotes" >
…
<service
android:name="android.helloworld.sync.QuickNotesSyncService" >
</service>
</application>
![Page 11: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/11.jpg)
Services
Intent i = new Intent(context,
QuickNotesSyncService.class);
startService(i);
![Page 12: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/12.jpg)
Broadcast Receiver
![Page 13: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/13.jpg)
Broadcast receivers
O último - e não menos importante - dos principais componentes de uma aplicação Android é o Broadcast Receiver.
Broadcast Receivers são componentes responsáveis por receber e tratar mensagens do sistema ou de outras aplicações (Broadcasts)
![Page 14: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/14.jpg)
Broadcast receivers
Broadcasts podem ser lançados pelo sistema ou por aplicações. Exemplos de broadcasts do sistema:
● Intent.ACTION_BOOT_COMPLETED
● Intent.ACTION_POWER_CONNECTED
● Intent.ACTION_POWER_DISCONNECTED
● Intent.ACTION_BATTERY_LOW
● Intent.ACTION_BATTERY_OKAY
![Page 15: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/15.jpg)
Broadcast receivers
Broadcast receivers não possuem Interface com usuário, mas eles podem lançar um Notificação para alertar o usuário que algum evento ocorreu.
Normalmente, o broadcast receiver age como um gateway, recebendo os broadcasts e invocando outros componentes, como activities, services, etc.
![Page 16: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/16.jpg)
Broadcast receivers
Ciclo de vida
O ciclo de vida de um Broadcast é bastante simples: Quando o broadcast a ser capturado ocorre, o método onReceive() é chamado.
Após isso, o broadcast receiver é retirado da memória.
É importante ressaltar que o método onReceive() é executado na main thread, então é importante lançar uma nova thread para operações demoradas.
![Page 17: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/17.jpg)
Broadcast receivers
É importante ressaltar que o método onReceive() é executado na main thread, então é importante lançar uma nova thread para operações demoradas.
![Page 18: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/18.jpg)
Broadcast receiverspackage android.helloworld.sync;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
public class ConnWatcher
extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager cm =
(ConnectivityManager)context.getSystemService(
Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = (activeNetwork != null) &&
activeNetwork.isConnected();
if (isConnected) {
Intent i = new Intent(context, QuickNotesSyncService.class);
context.startService(i);
}
}
}
Exemplo de implementação:
ConnWatcher.java
![Page 19: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/19.jpg)
Broadcast receivers
Após implementar a classe filha de BroadcastReceiver, é necessário registrar o serviço no AndroidManifest:
<application
android:icon="@drawable/icon"
android:label="QuickNotes" >
…<receiver android:name="android.helloworld.sync.ConnWatcher">
<intent-filter><action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter></receiver>
</application>
![Page 20: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/20.jpg)
Broadcast receivers
Além de registrar o broadcast receiver, é também necessário declarar a permissão que será usada. No nosso caso, a permissão para acessar o estado das conexões de rede.
…<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:icon="@drawable/icon"
android:label="QuickNotes" >
![Page 21: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/21.jpg)
HTTP
![Page 22: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/22.jpg)
Clientes HTTP
Em Android temos dois clientes HTTP:
● Apache HTTP Client
● HttpURLConnection
O Google aconselha o uso de HttpURLConnection desde a versão 2.3 (Gingerbread)
![Page 23: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/23.jpg)
Sincronização
Usaremos o HTTPUrlConnection para enviar as notas, que no nosso exemplo são armazenadas no banco de dados local, para um servidor remoto.
Vamos fazer isso em dois passos:
1) Criar uma flag no banco de dados, para termos controle do que já foi enviado.
2) Usar HTTPUrlConnection para enviar os dados via POST para o servidor remoto.
![Page 24: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/24.jpg)
Sincronização
Para criar uma coluna extra na tabela do nosso banco de dados, basta alterar o método onCreate da classe QuickNotesProvider$DBHelper
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + NOTES_TABLE + " (" +
Notes.NOTE_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
Notes.SYNCED + " INTEGER," +
Notes.TEXT + " LONGTEXT" + ");");
}
![Page 25: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/25.jpg)
Sincronização
Após a alteração no DBHelper, é necessário criar a constante SYNCED na classe QuickNotesProvider$Notes, que fica assim:
public static final class Notes implements BaseColumns {
public static final Uri CONTENT_URI = Uri.parse("content://" +
QuickNotesProvider.AUTHORITY + "/notes");
public static final String CONTENT_TYPE =
"vnd.android.cursor.dir/vnd.jwei512.notes";
public static final String NOTE_ID = "_id";
public static final String TEXT = "text";
public static final String SYNCED = "synced";
}
![Page 26: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/26.jpg)
Sincronização
Além das alterações no Content Provider, precisamos alterar o método addNote da MainActivity para passar a gravar as notas com a flag SYNCED = 0, significando que ela ainda não foi enviada ao server.
protected void addNote(String text) {
…values.put(QuickNotesProvider.Notes.SYNCED, 0);
…
}
![Page 27: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/27.jpg)
Sincronização
Com a flag criada, seguimos ao segundo passo, que é a criação dos métodos para acesso ao servidor remoto.
Criaremos para isso a class DataSync, já referenciada no QuickNotesSyncService, e que possui dois métodos:
● syncPendingNotes(), responsável por procurar no banco de dados as notas ainda não enviadas, e
● sendPendingNote(), responsável por enviar uma nota ao servidor.
![Page 28: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/28.jpg)
Sincronização
Com a implementação dos métodos citados, a classe DataSync fica como mostrado no endereço abaixo:
https://github.com/felipesilveira/QuickNotes/blob/master/src/android/helloworld/sync/DataSync.java
![Page 29: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/29.jpg)
Sincronização
Por fim, basta invocar o serviço de sincronização no método addNote(), se houver internet:
ConnectivityManager cm =
(ConnectivityManager)getSystemService(
Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
bool
ean isConnected = (activeNetwork != null) && activeNetwork.isConnected();
if
(isConnected) {
Intent i = new Intent(this, QuickNotesSyncService.class);
startService(i);
}
![Page 30: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/30.jpg)
Backend
Para os testes, foi criado um backend no seguinte endereço:
http://tests.felipesilveira.com.br/android-core/
Onde são listadas todas as notas enviadas através de POST para a URL:
http://tests.felipesilveira.com.br/android-core/insert.php
![Page 31: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/31.jpg)
NDK
![Page 32: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/32.jpg)
NDK
O NDK permite que códigos escritos em linguagem nativa (C/C++) sejam executados em uma aplicação android.
O objetivo do NDK não é substituir o desenvolvimento Java por desenvolvimento nativo, e sim complementá-lo em situações específicas.
![Page 33: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/33.jpg)
NDK
Principais usos:
● Reaproveitamento de bibliotecas nativas
● Execução de algoritmos complexos
● Jogos
![Page 34: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/34.jpg)
JNI
Toda comunicação entre código Java e código nativo é feita através de JNI - Java Native Interface.
![Page 35: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/35.jpg)
Activities
As chamadas nativas podem ser integradas à aplicação de basicamente duas formas:
● Em Activities convencionais
● Em NativeActivities, que são Activities especiais cujo propósito é ser inteiramente implementadas de forma nativa - muito comuns em jogos.
![Page 36: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/36.jpg)
Criando uma chamada nativa
Iremos agora criar uma chamada nativa dentro de nossa MainActivity. Será uma chamada bastante simples, que apenas será responsável por criar uma entrada no log da aplicação.
![Page 37: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/37.jpg)
Criando uma chamada nativa
Passo 1 - Criando o código em C
Crie o diretório jni dentro do diretório do projeto QuickNotes, e dentro dele crie o arquivo native.c, com o seguinte conteúdo:#include <jni.h>
#include <string.h>
#include <android/log.h>
#define DEBUG_TAG "NDK_AndroidNDK1SampleActivity"
void Java_com_example_Activity_helloLog(JNIEnv * env, jobject this, jstring logThis)
{
jboolean isCopy;
const char * szLogThis = (*env)->GetStringUTFChars(env, logThis, &isCopy);
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:LC: [%s]", szLogThis);
(*env)->ReleaseStringUTFChars(env, logThis, szLogThis);
}
![Page 38: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/38.jpg)
Criando uma chamada nativa
Passo 2 - Criando as chamadas no código java
Dentro do método addNote() da MainActivity, adicione a seguinte chamada:
helloLog("Nota corretamente adicionada!");
E declare o método nativo da seguinte forma:
private native void helloLog(String logThis);
![Page 39: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/39.jpg)
Criando uma chamada nativa
Passo 2 - Criando as chamadas no código java
Além disso, é também necessário fazer a inicialização estática da lib a ser criada:
st
atic {
System.loadLibrary("ndk1");
}
![Page 40: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/40.jpg)
Criando uma chamada nativa
Passo 3 - Criando o Makefile para o código nativo
É necessária a criação de um Makefile para o código nativo que criamos, para que seja possível o compilarmos usando o NDK. Para isso, crie o arquivo Android.mk com o seguinte conteúdo:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_MODULE := ndk1
LOCAL_SRC_FILES := native.c
include $(BUILD_SHARED_LIBRARY)
![Page 41: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/41.jpg)
Criando uma chamada nativa
Passo 4 - Compilando o código nativo
Para compilar o código nativo, basta entrar no diretório jni e executar o comando ndk-build (presente na raiz do ndk).
![Page 42: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/42.jpg)
Criando uma chamada nativa
Passo 5 - Compilando a aplicação
Por fim, basta compilar a aplicação QuickNotes da forma tradicional, para a chamada nativa estar integrada ao código Java.
![Page 43: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/43.jpg)
Bibliografia
Pro Android C++ with the NDKOnur Cinar
Advanced Android: Getting Started with the NDKhttp://mobile.tutsplus.com/tutorials/android/ndk-tutorial/
![Page 44: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/44.jpg)
Github
O projeto inteiro está disponível para download no github:
https://github.com/felipesilveira/QuickNotes
![Page 45: Android Core Aula 7 - Aplicações (Services, Broadcast Receivers, NDK/JNI)](https://reader033.vdocuments.net/reader033/viewer/2022052600/5579a021d8b42ac1148b4748/html5/thumbnails/45.jpg)
Obrigado.