Serviços de Parse Baseado em Nuvem para Aplicativos Android

Armazene na nuvem e consulte usuários, objetos de dados e arquivos em aplicativos Android

Explore as vantagens de armazenar dados de aplicativos remotos em uma nuvem privada, com essa introdução ao SDK Parse para Android. O "defensor da mobilidade" C. Enrique Ortiz apresenta as classes da API Parse para armazenamento em nuvem e manipulação de usuários, objetos de dados e arquivos para aplicativos remotos.

C. Enrique Ortiz, Mobile Technologist, Independent

C. Enrique Ortiz é "defensor da mobilidade", autor e blogueiro de longa data, que estava criando software remoto de ponta a ponta antes de os smartphones serem smart. Ele escreveu vários artigos técnicos e dois livros sobre desenvolvimento de software remoto e ajudou dezenas de empresas com suas necessidades de computação remota.


nível de autor Contribuidor do
        developerWorks

20/Dez/2012

O SDK remoto Parse oferece APIs e serviços de nuvem para aplicativos iOS, Android e Window ®. O SDK Parse também oferece APIs JavaScript e REST. Usando a API Parse, é possível fazer um aplicativo remoto usar a nuvem de forma rápida e com esforço mínimo. Um aplicativo remoto integrado com a API Parse pode facilmente armazenar objetos de dados e arquivos na nuvem Parse, enviar e receber notificações push, gerenciar usuários, lidar com dados de localização geográfica e usar plataformas de mídia social como Twitter e Facebook. Para aplicativos remotos que precisam de ajuste de escala, o SDK Parse oferece toda a elasticidade de uma plataforma de nuvem.

Antes de iniciar

Eu suponho, para os fins deste artigo, que você já conhece os conceitos básicos para programar aplicativos remotos com JSON, Android e Eclipse. Antes de continuar lendo, acesse Parse.com e defina seu aplicativo. Basta seguir as instruções simples a partir da página de inscrição.

Este artigo apresenta as principais classes da API Parse para usuários, objetos de dados e arquivos do Parse. Você aprenderá a trabalhar com listas de controle de acesso (ACL), realizar operações CRUD em objetos de dados e armazenar e recuperar arquivos na nuvem Parse. Os exemplos são construídos no SDK Parse para Android (consulte Recursos)).

O painel do Parse

O painel do Parse auxilia os desenvolvedores no gerenciamento de aplicativos. O painel oferece métricas de uso gerais e de aplicativos específicos para APIs, arquivos e notificações push. Chaves e configurações de aplicativo são gerenciadas através do painel. O painel também oferece um navegador de dados que permite aos desenvolvedores navegar e mesmo editar objetos Parse armazenados. O navegador de dados é muito útil para depuração. A Figura 1 é uma captura de tela do painel do Parse:

Figura 1. O painel do Parse
O painel do Parse

Os aplicativos são autenticados por meio de um ID do aplicativo e ID de cliente. Para obter os IDs de aplicativo e cliente, é necessário registrar o aplicativo através do painel Parse. Você usará essas chaves ao inicializar a biblioteca Parse no aplicativo.

Objetos de dados do Parse

No Parse, dados são representados usando ParseObject, um contêiner de pares nome-valor. ParseObject pode armazenar quaisquer dados que sejam compatíveis com JSON, como mostra a Listagem 1:

Lista 1. Um exemplo de ParseObject
ParseObject myParseObject = new ParseObject("MyObject"); // Class Name
myParseObject.put("name", "C. Enrique Ortiz");
myParseObject.put("twitterHandle", "eortiz");
myParseObject.put("followers", 123456);

ParseObject recebe um nome de classe quando é instanciado. O nome de classe na Listagem 1 é "MyObject." Os nomes de classe são como nomes de tabela em um banco de dados relacional, e objetos do Parse da mesma classe são como linhas em uma tabela.

ParseObject expõe métodos semelhantes àqueles encontrados em uma classe Map de Java, como put, get e remove, além de alguns outros métodos que são específicos do ParseObject.

ParseObjectnomes de chave devem ser alfanuméricos; recomenda-se usar camel-casing para chaves de nome. Os valores podem ser qualquer tipo de dados que possa ser armazenado em JSON, ou seja, números, cadeias de caractere, booleanos, arrays, JSONObject.NULL, JSONObjects e JSONArrays. Outros tipos de dados suportados por ParseObject são Date e arrays byte[] de Java. Um ParseObject também pode incluir outros ParseObjects.

A Listagem 2 mostra alguns dos tipos de dados de valor para os quais ParseObject oferece suporte:

Lista 2. ParseObject: Alguns tipos de dados de valor com suporte
// Byte Array
byte[] byteArray = {1, 2, 3, 4, 5};

// A date
Date d = new Date(); // java.util.Date

// A number
int number = 21;

// A String
String name = "Enrique";

// A JSONArray - any mix of JSONObjects, JSONArrays, Strings, Booleans, 
//   Integers, Longs, Doubles, null or NULL.
JSONArray jArray = new JSONArray();
jArray.put(number);
jArray.put(name);

// A JSONObject 
JSONObject jObject = new JSONObject();
try {
    jObject.put("number", number);
    jObject.put("name", name);
} catch (JSONException e) {
    e.printStackTrace();
}

// A ParseObject
ParseObject pObject = new ParseObject("MyObject"); // Class name
pObject.put("myByteArray", byteArray);
pObject.put("myDate", d);
pObject.put("myString", name);
pObject.put("myNumber", number);
pObject.put("myJsonArray", jArray);
pObject.put("myJsonObject", jObject);
pObject.put("myNull", JSONObject.NULL);

O código na Listagem 2 cria um ParseObject que é armazenado como um objeto na nuvem Parse. Muitos MyObjects da mesma classe são então armazenados como linhas de objetos de dados ParseObject que podem ser salvos, consultados, atualizados e excluídos do armazenamento em nuvem do Parse. É possível até mesmo salvar dados quando o aplicativo está offline — a biblioteca Parse simplesmente salva os dados localmente até que uma conexão de rede tenha sido restabelecida.

Modificando um ParseObject

Se você conhece o desenvolvimento de aplicativos remotos, sabe que operações longas, como operações de rede, devem geralmente ser feitas em segundo plano, em um encadeamento do trabalhador e não no encadeamento de UI principal do sistema. Isso evita que o encadeamento principal do sistema bloqueie e afete a responsividade da interface com o usuário. Mais adiante no artigo, mostrarei como o Parse facilita o trabalho no plano de fundo para salvar, excluir e localizar objetos. Por ora, considere o seguinte método remove() síncrono, que é usado para remover uma chave de um objeto Parse:

pObject.remove("myNumber"); // remove the field/key "myNumber" from pObject

Após remover ou incluir campos, ou atualizar um campo atual, é possível chamar um dos métodos save...() do ParseObject para salvar (ou atualizar) o objeto de dados.

Resumo: ParseObject

ParseObject representa um objeto de dados na nuvem Parse. Oferece métodos para incluir pares de nome-valor, testar se uma dada chave está presente e excluir ou buscar um dado ParseObject do servidor. ParseObject também permite usar vários métodos get...() e put...() para manipular dados de ParseObject, mesclar ParseObjects, salvar um ParseObject no servidor e mais.

Usuários, funções e ACLs do Parse

Antes de eu mostrar como realizar operações CRUD em um objeto Parse, você deve saber algumas coisas sobre usuários, funções e ACLs (listas de controle de acesso) do Parse. Os três são conceitos e recursos muito importantes para proteger os objetos de dados do aplicativo.

Usuários do Parse

Uma classe chamada ParseUser representa um usuário e oferece recursos de conta do usuário para aplicativos Parse. Todos os aplicativos Parse têm usuários do Parse associados. Um ParseUser é um ParseObject com as propriedades adicionais de nome de usuário, senha e email. É possível incluir qualquer valor de dados adicional que você julgar necessário.

Usuários anônimos no Parse

Um usuário anônimo no Parse não possui nome de usuário ou senha. Os usuários anônimos são úteis para funcionalidades de aplicativo remoto que não exijam autenticação do usuário. Usuários anônimos podem criar objetos de dados, mas eles têm vida curta e não estarão disponíveis após o usuário anônimo efetuar logout.

Os usuários podem inscrever-se como usuários Parse do aplicativo, como mostra a Listagem 3:

Lista 3. ParseUser— - inscrição
ParseUser user = new ParseUser();
user.setUsername("eortiz");
user.setPassword("123456");
user.setEmail("eortiz@nospam.com");
user.put("userType", "Author"); // add another field

// Call the asynchronous background method to sign up 
user.signUpInBackground(new SignUpCallback() {
  public void done(ParseException e) {
    if (e == null) {
      // Successful. Allow access to app.
    } else {
      // Failed....
    }
  }
});

O username e email devem ser exclusivos. Se um nome de usuário ou email já estiver em uso, a chamada de inscrição irá fracassar. Você ter um mecanismo para notificar o usuário se um dos campos falhar e um processo para tentar novamente.

Após a inscrição, os usuários podem efetuar login no aplicativo, como mostra a Listagem 4:

Lista 4. ParseUser— - Login
ParseUser.logInInBackground("eortiz", "123456", new LogInCallback() {
  public void done(ParseUser user, ParseException e) {
    if (user != null) {
      // Successful. Allow access to app.
    } else {
      // Failed
    }
  }
});

Para atualizar as informações do usuário, é possível chamar ParseUser.save(). Observe, no entanto, que apenas o proprietário de ParseUser pode modificar seu conteúdo. Para os demais, os dados são somente leitura.

O Parse armazena em cache o usuário conectado atualmente. É possível consultar o usuário atual chamando ParseUser.currentUser(). O método currentUser permite acessar rapidamente as informações do usuário atual, portanto, é necessário solicitar credenciais apenas se a sessão de usuário atual não estiver ativa. A Listagem 5 mostra como recuperar um usuário atual no Parse:

Lista 5. ParseUser— - Obtendo o usuário atual
ParseUser currentUser = ParseUser.getCurrentUser();
if (currentUser != null) {
  // current user is valid
} else {
  // current user not valid, ask for credentials
}

Reconfigurando um usuário atual

É possível reconfigurar um usuário atual no Parse chamando ParseUser.logOut(), como mostra a Listagem 6:

Lista 6. ParseUser— - Reconfigurando o usuário atual (logout)
ParseUser.logOut(); // static method

ACLs do Parse

Um ACL é uma lista de permissões de acesso (ou controles) associados a um objeto de dados. A classe ParseACL permite definir as permissões para um dado ParseObject. Com ACLs, é possível definir acesso público aos objetos de dados do aplicativo e imitar o acesso a usuários ou grupos de usuários específicos (através de funções). A Listagem 7 demonstra o uso de ACLs do Parse:

Lista 7. Usando ParseACL para permissões de acesso
// Define a Parse user
ParseUser user = new ParseUser();
user.setUsername(username);
:
:

// Define a read/write ACL
ParseACL rwACL = new ParseACL();
rwACL.setReadAccess(user, true); // allow user to do reads
rwACL.setWriteAccess(user, true); // allow user to do writes
:
:

// Define a Parse object and its ACL
ParseObject gameObject = new ParseObject("Game");
gameObject.setACL(rwACL); // allow user do read/writes on gameObject
gameObject.saveInBackground(); // save the ACL'ed object to the cloud
:
:

// You can define a public ACL that gives public access to the object
ParseACL publicACL = new ParseACL();
publicACL.setPublicReadAccess(true);
publicACL.setPublicWriteAccess(true);      
gameObject.setACL(publicACL); // allow public read/writes
gameObject.saveInBackground(); // save the ACL'ed object to the cloud

Também é possível definir um ACL padrão para todos os objetos recém-criados. Na Listagem 8, eu configurei o ACL padrão para ser público para leituras e gravações, como definido por publicACL na Listagem 7.

Lista 8. Configurando o ACL padrão
// Set a default ACL for all newly created objects as public access
ParseACL.setDefaultACL(publicACL, true);

Embora não seja mostrado aqui, também poderíamos usar a classe ParseRole para conceder permissões de acesso a grupos de usuários.

Em seguida, vamos examinar como objetos de dados são salvos na e recuperados da nuvem Parse.

Objetos de dados do Parse na nuvem

Após criar e preencher um ParseObject, é possível salvá-lo na nuvem Parse. Salvar objetos de dados na nuvem Parse é, na verdade, uma das coisas mais simples a se fazer com o Parse. A complexidade geralmente associada com representação de dados, serialização, comunicação de rede e transporte etc. é completamente oculta pelo Parse. Será necessário usar métodos auxiliares para mapear a instância do objeto de dados para um ParseObject e vice-versa, e você deverá decidir entre realizar a operação de salvar do Parse no seu próprio encadeamento ou usar o método de salvar em segundo plano.

Cuidado para não bloquear o encadeamento de sistema!

Lembre-se que, em aplicativos remotos, operações longas como de rede, de arquivo ou longos cálculos não devem ser feitos no encadeamento principal do sistema. É melhor executá-los em um encadeamento do trabalhador separado. Bloquear o encadeamento do sistema poderia prejudicar a responsividade do aplicativo, podendo resultar no seu fechamento forçado.

ParseObject oferece dois tipos de métodos para salvar: save() e saveInBackground(). saveInBackground() é o método recomendado, pois realiza a operação de salvar em seu próprio encadeamento do trabalhador. Caso você opte por usar o método save() síncrono, lembre-se de que é sua responsabilidade chamá-lo em seu próprio encadeamento do trabalhador para evitar o bloqueio da UI.

A Listagem 9 mostra o código para salvar um objeto de dados Parse em segundo plano:

Lista 9. Salvar ParseObject em segundo plano
// ParseObject
ParseObject pObject = new ParseObject("ExampleObject");
pObject.put("myNumber", number);
pObject.put("myString", name);
pObject.saveInBackground(); // asynchronous, no callback

E a Listagem 10 mostra o código para salvar um objeto de dados do Parse em segundo plano com um retorno de chamada:

Lista 10. Salvar em segundo plano com retorno de chamada
pObject.saveInBackground(new SaveCallback () {
    @Override
    public void done(ParseException ex) {
        if (ex == null) {
            isSaved = true;
        } else {
            // Failed
            isSaved = false;
        }
    }
  });

As variações do método save...() incluem o seguinte:

  • saveAllinBackground() salva um ParseObject com ou sem um retorno de chamada.
  • saveAll(List<ParseObject> objects) salva uma lista de ParseObjects.
  • saveAllinBackground(List<ParseObject> objects) salva uma lista de ParseObjects em segundo plano.
  • saveEventually() permite salvar um objeto de dados no servidor em algum ponto no futuro; use esse método se a nuvem Parse não estiver disponível no momento.

Após um ParseObject ser salvo com sucesso na nuvem, ele recebe um Object-ID exclusivo. Esse Object-ID é muito importante, pois identifica de forma exclusiva essa instância do ParseObject. O Object-ID pode ser usado, por exemplo, para determinar se o objeto foi salvo com sucesso na nuvem, para recuperar e atualizar uma dada instância de objeto Parse e para excluir um ParseObject em particular.

Recuperando objetos de dados da nuvem

Esta seção examina métodos para consultar e recuperar objetos de dados armazenados na nuvem Parse. É possível consultar um único ParseObject por object-ID, ou consultar um ou mais objetos Parse usando atributos. Se você já tiver um ParseObject, é possível buscar os valores mais recentes no servidor para atualizar ou sincronizar seu conteúdo. Examinaremos todas essas opções nos seguintes fragmentos de código.

Buscando ParseObjects

Para buscar um objeto de dados na nuvem Parse, use o método ParseObjectfetch() ou fetchInBackground(), mostrados na Listagem 11:

Lista 11. Busca (incondicional)
// ParseObject
ParseObject pObject = new ParseObject("ExampleObject");
:
:

// Fetch the parse object unconditionally
try {
    pObject.fetch();
} catch (ParseException e) {
    e.printStackTrace();
}

// Fetch the parse object unconditionally, with Callback
pObject.fetchInBackground(new GetCallback() {
    @Override
    public void done(ParseObject obj, ParseException ex) {
        if (ex == null) {
            // Success
        } else {
            // Failed
        }            
    }
});

É possível também buscar apenas quando necessário; por exemplo, ao buscar um objeto Parse que possui outros objetos Parse relacionados, como na Listagem 12:

Lista 12. Buscando quando necessário
ParseObject po = new ParseObject("ExampleObject");
:

ParseObject po2 = po.getParseObject("key");

// Fetch only if needed
try {
    po2.fetchIfNeeded();
} catch (ParseException e) {
    e.printStackTrace();
}

Outra opção é realizar uma operação "buscar se necessário" em segundo plano, com retorno de chamada. Para isso, usaríamos o método de objeto do Parse fetchIfNeededInBackground(GetCallback callback).

Em alguns casos, será necessário buscar uma coleção de objetos Parse de uma vez, de forma incondicional, ou apenas se necessário. ParseObject oferece um conjunto de métodos estáticos para isso. Cada um deles recebe como entrada uma lista de objetos Parse e retorna uma lista de objetos Parse:

  • fetchAll(List<ParseObject> objects)
  • fetchAllIfNeeded(List<ParseObject> objects)
  • fetchAllIfNeededInBackground(List<ParseObject> objects, FindCallback callback)
  • fetchAllInBackground(List<ParseObject> objects, FindCallback callback)

Consultando objetos de dados na nuvem

Você já deve ter percebido que a API Parse é muito abrangente — mas espere, ainda tem mais! Além de buscar objetos de dados, Parse também permite consultar objetos de dados usando object-ID ou atributos. Para consultar um objeto de dados da nuvem Parse, use ParseQuery. É possível usar ParseQuery para consultas de dados básicas e complexas, recebendo de volta um dado objeto ou uma Lista de objetos correspondentes.

A Listagem 13 mostra como recuperar um objeto Parse específico do servidor em um encadeamento de plano de fundo, dado em object-ID:

Lista 13. Usando ParseQuery para recuperar um dado ParseObject
String myID = "12345";
ParseQuery query = new ParseQuery("Players");
query.getInBackground(myID, new GetCallback() {
    @Override
    public void done(ParseObject object, ParseException e) {
        if (object != null) {
            // Get object
        } else {
            // Not found
        }
    }            
});

Observe que query.getInBackground() não usa o cache de ParseQuery.

A Listagem 14 mostra uma consulta que recupera todos os objetos de dados da classe: Players. (Nenhuma restrição fornecida.)

Lista 14. Usando ParseQuery para todos os ParseObjects de uma dada classe
ParseQuery query = new ParseQuery("Players");
query.findInBackground(new FindCallback() {
    @Override
    public void done(List<ParseObject> players, ParseException e) {
        if (players != null) {
            // Get list of players
        } else {
            // No players
        }
    }
});

Na Listagem 15, usei uma restrição de consulta para recuperar um ou mais objetos Parse correspondentes; no caso, Players ativos:

Lista 15. Usando ParseQuery para recuperar ParseObjects correspondentes
ParseQuery query = new ParseQuery("Players");
query.whereEqualTo("status", "active");
query.findInBackground(new FindCallback() {
    @Override
    public void done(List<ParseObject> players, ParseException e) {
        if (players != null) {
            // Success - players contain active players 
        } else {
            // Failed
        }
    }
});

ParseQuery também oferece um método para obter a contagem de objetos correspondentes sem recuperar os próprios objetos, o que é muito útil. A Listagem 16 mostra como obter a contagem de jogadores ativos:

Lista 16. Usando ParseQuery para contar ParseObjects correspondentes
ParseQuery query = new ParseQuery("Players");
query.whereEqualTo("status", "active"); //remove this line to count ALL
query.countInBackground(new CountCallback() {
    @Override
    public void done(int count, ParseException e) {
        if (e == null) {
            // Success, see count variable
        } else {
            // Failed
        }
    }
});

Métodos e restrições de ParseQuery

ParseQuery suporta mais de 20 métodos diferentes de restrição de consulta. Aqui estão alguns exemplos:

  • whereMatches(String key, String regex) localiza valores de cadeia de caracteres que correspondem à expressão regular fornecida.
  • whereStartsWith(String key, String prefix) localiza valores de cadeia de caracteres que começam com uma sequência fornecida.
  • whereContains(String key, String substring) localiza valores que contêm uma cadeia de caractere fornecida.
  • whereGreaterThan(String key, Object value) localiza valores maiores que o valor fornecido.
  • whereWithinKilometers(String key, ParseGeoPoint point, double maxDistance) localiza objetos com valores de ponto próximo do ponto dado e dentro da distância máxima dada.

Os resultados da consulta podem ser ordenados, como mostra a Listagem 17. Para ordenar os resultados da consulta, chame um dos métodos query orderBy...(), especificando o campo pelo qual ordenar.

Lista 17. Ordenando resultados de consulta
query.orderByAscending("name"); 

query.orderByDescending("name");



For example:



ParseQuery query = new ParseQuery("Players");
query.whereEqualTo("status", "active");
query.orderByAscending("lastName"); // By lastname ascending order
query.findInBackground(new FindCallback() {
    @Override

  public void done(List<ParseObject> players, ParseException e) {

    if (players != null) {
      // Success - players contain active players

    } else {

      // Failed
		
                          } 

             }	

});

Observe também que os resultados de ParseQuery são armazenados em cache. É possível configurar a política de armazenamento em cache da consulta de acordo com o aplicativo. Existe suporte para as seguintes políticas de cache:

  • IGNORE_CACHE: Não use o cache. É a política padrão.
  • CACHE_ONLY: Carregue apenas do cache. Se não houver resultados de cache, haverá uma ParseException.
  • NETWORK_ONLY: Sempre acesse a rede, mas salve os resultados no cache.
  • CACHE_ELSE_NETWORK: Acesse o cache primeiro. Se isso falhar, carregue da rede. Se nem o cache nem a rede tiverem sucesso, o resultado será ParseException.
  • NETWORK_ELSE_CACHE: Acesse a rede primeiro. Se isso falhar, carregue do cache. Se nem a rede nem o cache tiverem sucesso, o resultado será ParseException.
  • CACHE_THEN_NETWORK: Acesse o cache primeiro e, em seguida, carregue da rede. Observe que FindCallback será chamado duas vezes: primeiro com os resultados em cache e depois com os resultados da rede. Essa política pode ser usada apenas de forma assíncrona com findInBackground.

Configurar a política de cache é simples. Faça isso antes de chamar o método find...(), como mostra a Listagem 18:

Lista 18. Gerenciando CachePolicy
ParseQuery query = new ParseQuery("Players");
query.setCachePolicy(ParseQuery.CachePolicy.NETWORK_ELSE_CACHE);
query.findInBackground(new FindCallback() {
    @Override
    public void done(List<ParseObject> players, ParseException e) {
        if (e == null) {
            // Success - players contain active players 
        } else {
            // Failed
        }
    }
});

A classe ParseQuery oferece todos os métodos necessários para consultar objetos de dados armazenados na nuvem. Com ParseQuery, é possível especificar restrições de consulta de todos os tipos, contar objetos de dados correspondentes, definir limites, ignorar objetos de dados, ordenar, limpar o cache e muito mais.


Removendo objetos de dados

Remover um objeto de dados da nuvem Parse também é muito simples. Quando você tiver a instância de objeto, é possível excluir um ParseObject da nuvem chamando o método do ParseObjectdelete() ou deleteInBackground(). Ambos são mostrados na Listagem 19:

Lista 19. Removendo um objeto Parse da nuvem
parseObject.delete();
parseObject.deleteInBackground();

Como seria de esperar, delete() é uma chamada bloqueadora, o que significa é necessário executá-la em seu próprio encadeamento do trabalhador. Ou você pode deixar que o Parse cuide do encadeamento com deleteInBackground() com ou sem um retorno de chamada.

Trabalhando com arquivos

Até agora, trabalhamos com objetos e consultas Parse. Também apresentei a você usuários, ACLs e funções do Parse. Para encerrar, farei uma demonstração das funções para ler, gravar e salvar arquivos no Parse.

Lembre-se que é possível armazenar dados byte[] brutos em um ParseObject, o que é útil para pequenos volumes de dados. Para armazenar itens maiores, como imagens ou documentos, use Arquivos Parse.

Os arquivos na nuvem Parse são representados usando ParseFile, que oferece métodos para obter o nome de um arquivo, sua URL e os dados de arquivo, se estiverem disponíveis. Também é possível fazer download e upload de arquivos e acessar alguns outros métodos auxiliares.

Os dados de arquivo são representados pela sintaxe byte[]. Observe que, atualmente, um arquivo não pode ser maior que 10 MB. Ao dar um nome a um arquivo, a biblioteca do Parse cuida de potenciais colisões de nomes. Supondo que uma extensão ajude o Parse a lidar com o conteúdo do arquivo.

A Listagem 20 demonstra como salvar um arquivo JPG:

Lista 20. Salvando um ParseFile
// Save image file
Drawable drawable = ...;
Bitmap bitmap = (Bitmap)((BitmapDrawable) drawable).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] data = stream.toByteArray();                
ParseFile imageFile = new ParseFile("image.jpg", data);
imageFile.saveInBackground();

As instruções iniciais na Listagem 20 convertem o bitmap em um byte[]. O byte[] é então salvo usando o método ParseFile saveInBackground(), semelhante à forma como um ParseObject é salvo no servidor.

Quando um arquivo tiver sido salvo no Parse, ele precisa ser associado com (colocado em) um ParseOject. Em outras palavras, arquivos Parse não são objetos independentes e, para que possam ser recuperados e usados posteriormente, devem ser associados a uma dada instância de ParseObject. Essa limitação pode ser eliminada em um release futuro do Parse. A Listagem 21 associa o arquivo de imagem com um objeto Player do Parse:

Lista 21. Associando um ParseFile com um ParseObject
// Associate image with Parse object
ParseObject po = new ParseObject("Players");
po.put("name", "eortiz");
po.put("photo", imageFile);
po.saveInBackground();

Eu associei o arquivo ao objeto de dados e salvei o objeto no servidor usando saveInBackgroud(), discutido anteriormente.

A Listagem 22 mostra como recuperar um arquivo que está associado a um objeto de dados:

Lista 22. Recuperando o ParseFile
// Retrieving the file 
ParseFile imageFile2 = (ParseFile)po.get("photo");
imageFile2.getDataInBackground(new GetDataCallback() {
  public void done(byte[] data, ParseException e) {
    if (data != null) {
      // Success; data has the file
    } else {
      // Failed
    }
  }
});

Após receber uma referência de ParseFile do objeto Parse, chamei getDataInBackground() para recuperar o ParseFile dos servidores. Observe que eu usei o retorno de chamada GetDataCallback para recuperar os arquivos Parse, em vez de GetCallback, que serve para recuperar objetos Parse com ParseQuery.

Concluindo

A API Parse é muito abrangente, incluindo classes para acessar serviços remotos como notificação push, uso de dados geográficos, integração com plataformas de mídias sociais e mais. Neste artigo, mostrei apenas a ponta do iceberg em termos de utilidade do Parse, apresentando as APIs para armazenamento de dados e arquivos na nuvem. Saber como armazenar e manipular usuários, objetos de dados, arquivos e ACLs do Parse na nuvem Parse é uma boa base para explorar melhor essa plataforma de nuvem para desenvolvimento para dispositivos móveis.

Agradecimentos

Agradeço a Athen O'Shea por ter lido este artigo.

Recursos

Aprender

  • Saiba mais sobre o SDK para Android do Parse; veja também o Guia Rápido do Parse para escolher uma plataforma remota, configurar um aplicativo e fazer o download e a instalação do SDK do Parse.
  • Visualize uma listagem completa das APIs para Android do Parse.
  • "Develop Android applications with Eclipse (Frank Ableson, developerWorks, fevereiro de 2008): Pratique o desenvolvimento de aplicativos Android no ambiente de desenvolvimento Eclipse, dessa vez usando o plug-in Eclipse para Android.
  • "Introdução ao jQuery Mobile" (C. Enrique Ortiz, developerWorks, maio de 2012): Conheça os fundamentos de jQuery Mobile e como escrever uma interface com o usuário de um aplicativo da web móvel funcional. Exemplos funcionais abordam páginas, navegação, barras de ferramentas, visualizações de lista, controles de formulário e efeitos de transição no jQuery Mobile.
  • "Solucione seus Desafios de Integração de Aplicativo Remoto de Diversos Dispositivos para Diversas Plataformas" (Olivier Picciotto, developerWorks, agosto de 2012): Desenvolvimento para dispositivos móveis e computação em nuvem são praticamente inseparáveis hoje em dia, mas integrar aplicativos remotos na nuvem ainda é território novo. Saiba como a mobile enterprise application platform (MEAP) supera alguns desafios da integração de dispositivos móveis e nuvem.
  • "DevOps de Dispositivo Móvel" (Michael Rowe, developerWorks, julho de 2012): Empresas de todo o mundo querem explorar o mercado de dispositivos móveis, fornecendo aos clientes e usuários aplicativos que tornam a computação remota mais fácil. Este artigo discute alguns dos problemas técnicos e de negócios envolvidos na integração de desenvolvimento e operações para plataformas remotas no local de trabalho.
  • Siga o developerWorks no Twitter.
  • Acompanhe as demos sob demanda do developerWorks que abrangem desde demos de instalação e configuração de produtos para iniciantes até funcionalidades avançadas para desenvolvedores experientes.

Discutir

  • Participe da comunidade do developerWorks. Entre em contato com outros usuários do developerWorks e explore os blogs, fóruns, grupos e wikis voltados para desenvolvedores.

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java, Cloud computing
ArticleID=852817
ArticleTitle=Serviços de Parse Baseado em Nuvem para Aplicativos Android
publish-date=12202012