Quatro tipos de comunicação entre processos e o uso de aidl

Já a memória não pode ser compartilhada entre aplicativos do sistema Android. Portanto, a troca de dados entre diferentes aplicações (comunicação entre processos) é um pouco mais complicada. Existem 4 métodos para comunicação entre processos fornecidos no Android SDK. Esses quatro métodos correspondem aos quatro componentes do aplicativo no sistema Android: Atividade, Provedor de Conteúdo, Transmissão e Serviço.

Método 1: Acesse a atividade de outros aplicativos

Por exemplo, existem muitos aplicativos no sistema Android que fornecem atividades que podem ser acessadas entre processos. Por exemplo, o código a seguir pode chamar diretamente a atividade que faz uma chamada telefônica.

Intent callIntent =newIntent(Intent.ACTION_CALL, Uri.parse("tel:12345678");
startActivity(callIntent);

Uma constante Intent.ACTION_CALL é usada no código que chama o discador. A constante é definida da seguinte forma:

public  static  final  String ACTION_CALL = "android.intent.action.CALL" ;  

Essa constante é uma constante de string e também é a chave para chamar Activity entre processos que apresentaremos nesta seção. Se quiser compartilhar uma Activity em seu aplicativo, você precisa especificar um ID de string para esta Activity, que é Action. Esta Acção também pode ser considerada como a chave desta Actividade. Em outras aplicações, você pode encontrar a Activity correspondente à Action através desta Action, e iniciar a Activity através do método startActivity.

Vamos primeiro ver como compartilhar a atividade do aplicativo. Os leitores podem seguir as seguintes etapas para compartilhar a atividade:

Especifique a ação no arquivo AndroidManifest.xml. Especifique a ação para usar um rótulo e especifique a ação no atributo android:name do rótulo

Especifique o protocolo de acesso no arquivo AndroidManifest.xml. O protocolo de acesso é necessário ao especificar o Uri (o 2º parâmetro da classe Intent). O protocolo de acesso precisa ser especificado usando o atributo android:scheme da tag. Se o valor deste atributo for "abc", então o Uri deverá ser "abc://A parte principal do Uri", ou seja, o protocolo de acesso é o início do Uri.

Obtenha a parte principal do Uri após o protocolo através do método getIntent().getData().getHost(). Este Host é apenas um título, não necessariamente o nome do host. Os leitores podem tratá-lo como uma string arbitrária.

Obtenha dados passados ​​por outros aplicativos do objeto Bundle.

Esta etapa é, obviamente, para fazer processamento adicional após a obtenção dos dados. Quanto à forma de processar estes dados, deve ser decidida com base em necessidades específicas.

Vamos compartilhar uma atividade de acordo com estes passos. Primeiro, crie um projeto Android (ActionActivity).A atividade principal do projeto é Main. Neste exemplo compartilharemos a classe Main. Primeiro abra o arquivo AndroidManifest.xml, adicione uma tag e redefina os atributos correspondentes de Main. O conteúdo do arquivo AndroidManifest.xml é o seguinte:

<!--  重新配置Main  -->  
<activity android:name=".Main"  android:label="@string/app_name" >  
    <intent-filter>      
        <action android:name="net.blogjava.mobile.MYACTION"  />  
        <data android:scheme="info"  />              
        <category android:name="android.intent.category.DEFAULT"  />  
    </intent-filter>  
</activity>  

Ao configurar o AndroidManifest.xml, observe que várias ações não podem ser configuradas na mesma, caso contrário, a ação MAIN será substituída para que o programa não possa iniciar normalmente (embora seja normal que outros aplicativos chamem Main).
Como pode ser visto no código acima, o valor do atributo android:name do rótulo é net.blogjava.mobile.MYACTION, que é a ação personalizada de Main. A tag especifica o protocolo do URL. Se o valor do atributo android:scheme (info) da tag for especificado, o seguinte URL precisará ser usado ao chamar Main:

info://任意字符串  

1.
O valor do atributo android:name de uma tag geral pode ser definido como android.intent.category.DEFAULT.
Vamos dar uma olhada em como obter dados passados ​​por outras aplicações no método onCreate da classe Main.

package  net.blogjava.mobile.actionactivity;  
... ...  
public  class  Main extends  Activity implements  OnClickListener  
{
    
      
    private  EditText editText;  
    @Override   
    public  void  onClick(View view)  
    {
    
      
        //  单击按钮,会显示文本框中的内容(以Toast信息框形式显示)   
        Toast.makeText(this , editText.getText().toString(), Toast.LENGTH_LONG)  
                .show();  
    }  
    @Override   
    public  void  onCreate(Bundle savedInstanceState)  
    {
    
      
        super .onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        Button button = (Button) findViewById(R.id.button);  
        button.setOnClickListener(this );  
        editText = (EditText) findViewById(R.id.edittext);  
        //  获得其他应用程序传递过来的数据   
        if  (getIntent().getData() != null )  
        {
    
      
            //  获得Host,也就是info://后面的内容   
            String host = getIntent().getData().getHost();  
            Bundle bundle = getIntent().getExtras();  
            //  其他的应用程序会传递过来一个value值,在该应用程序中需要获得这个值   
            String value = bundle.getString("value" );  
            //  将Host和Value组合在一下显示在EditText组件中   
            editText.setText(host + ":"  + value);  
            //  调用了按钮的单击事件,显示Toast信息提示框   
            onClick(button);  
        }  
    }  
}  

Como pode ser visto no programa acima, primeiro use getIntent().getData() para determinar se outros aplicativos passaram por Uri (o método getData retorna um objeto Uri). Se você executar este programa, Uri será nulo, portanto o código dentro da instrução if não será executado. Quando outros aplicativos passarem pelo objeto Uri, o sistema executará o código na instrução if. Após executar a ActionActivity, digite "Running" na caixa de texto, clique no botão "Mostrar o conteúdo da caixa de texto" e a caixa de mensagem Toast mostrada na Figura 2 será exibida.
Escreva a descrição da imagem aqui.
Vamos dar uma olhada em como outros aplicativos chamam Main em ActionActivity. Crie um novo projeto Android (InvokeActivity) e adicione um botão. O código do método de evento de clique do botão é o seguinte:

public void onClick(View view)
{ //Você precisa usar o segundo parâmetro da classe Intent para especificar o Uri Intent intent = new Intent("net.blogjava.mobile.MYACTION" , Uri .parse("info:// Chame outras aplicações Activity" )); // Defina o atributo de valor value intent.putExtra("value", "Call Success" ); // Chame Main startActivity(intent) em ActionActivity ; }







Antes de executar o InvokeActivity, você deve primeiro executar o ActionActivity para instalar o programa no emulador de Android. Em seguida, clique no botão em InvokeActivity e o efeito mostrado na Figura 3 será exibido.
Escreva a descrição da imagem aqui
. Claro, você também pode usar o método startActivityForResult para iniciar a atividade de outros aplicativos para obter o valor de retorno da atividade. Por exemplo, você pode modificar o código onClick da classe Main em ActionActivity para o seguinte formato.

public  void  onClick(View view)  
{
    
      
    Toast.makeText(this , editText.getText().toString(), Toast.LENGTH_LONG).show();  
    Intent intent = new  Intent();  
    //  设置要返回的属性值   
    intent.putExtra("result" , editText.getText().toString());  
    //  设置返回码和Intent对象   
    setResult(2 , intent);  
    //  关闭Activity   
    finish();  
}  

Em seguida, use o código a seguir em InvokeActivity para chamar Main.

intent = new Intent("net.blogjava.mobile.MYACTION", Uri  
        .parse("info://调用其他应用程序的Activity"));  
//  传递数据  
intent.putExtra("value", "调用成功");  
startActivityForResult(intent, 1);              //  1为请求码  

Para receber o valor retornado pela Activity, é necessário sobrescrever o método do evento onActivityResult. O código é o seguinte:

@Override   
protected  void  onActivityResult(int  requestCode, int  resultCode, Intent data)  
{
    
      
    Toast.makeText(this , "返回值:"  + data.getExtras().getString("result" ),  
            Toast.LENGTH_LONG).show();  
}  

Quando o botão correspondente em InvokeActivity for clicado e Main for fechado, a caixa de prompt de informações do Toast mostrada na Figura 4 será exibida.
Escreva uma descrição da imagem aqui
. A partir da introdução nesta seção, podemos ver que o acesso entre processos à Atividade (acesso à Atividade em outros aplicativos) é feito principalmente por meio de uma Ação. Se desejar transferir dados, você também precisa especificar um Uri. Claro, a passagem de dados também pode ser feita através do Intent. O processo de transferência de dados pode ser bidirecional. Se quiser retornar dados da atividade de chamada, você precisará usar o método startActivityForResult para iniciar a atividade.

Método 2: provedor de conteúdo

Os aplicativos Android podem usar arquivos ou bancos de dados SqlLite para armazenar dados. O Provedor de Conteúdo fornece uma maneira de compartilhar dados entre vários aplicativos (compartilhar dados entre processos). Os aplicativos podem usar o Provedor de Conteúdo para concluir as seguintes tarefas

  1. Consultar dados
  2. alterar os dados
  3. adicionando dados
  4. excluir dados

Embora o Provedor de Conteúdo também possa ser acessado dentro do mesmo aplicativo, não faz sentido fazê-lo. O Provedor de Conteúdo existe para compartilhar dados com outros aplicativos e permitir que outros aplicativos adicionem, excluam e modifiquem dados.

O próprio sistema Android fornece muitos provedores de conteúdo, como áudio, vídeo, informações de contato, etc. Podemos obter uma lista de informações relacionadas através desses Provedores de Conteúdo. Esses dados da lista serão retornados como objetos Cursor. Portanto, os dados retornados do Provedor de Conteúdo estão na forma de uma tabela bidimensional.
Para programas que acessam o Content Provider, eles precisam usar objetos ContentResolver. Este objeto precisa ser obtido usando o método getContentResolver. O código é o seguinte:

ContentResolver cr = getContentResolver();
1Assim como
a atividade, o provedor de conteúdo também precisa corresponder a um URI. Cada Provedor de Conteúdo pode controlar vários conjuntos de dados; nesse caso, cada conjunto de dados corresponde a um URI separado. Todos os URIs devem começar com "content://".
Para facilitar a manutenção do programa e simplificar o código do programa, o URI é geralmente definido como uma constante. Por exemplo, a constante a seguir representa o número de telefone de contato do sistema.

android.provider.Contacts.Phones.CONTENT_URI  

1
Vamos dar uma olhada nas etapas específicas para escrever o Provedor de Conteúdo.

Escreva uma subclasse que herda de android.content.ContentProvider. Esta classe é a classe principal do ContentProvider. Os métodos de consulta, inserção, atualização e exclusão serão implementados nesta classe. Na verdade, chamar esses quatro métodos da classe ContentResolver é chamar os métodos correspondentes da classe ContentProvider. Apenas a consulta é introduzida neste artigo. O uso de inserir, atualizar, excluir e consultar é semelhante. Os parâmetros também são passados ​​​​pelo Uri e, em seguida, esses parâmetros são recebidos nesses métodos e processados ​​posteriormente.
Configure ContentProvider no arquivo AndroidManifest.xml. Para determinar exclusivamente um ContentProvider, você precisa especificar o URI deste ContentProvider. Além disso, você também precisa especificar a classe ContentProvider correspondente ao URI. Isso é um pouco parecido com a definição de Servlet. Além de especificar o endereço da Web correspondente ao Servlet, você também precisa especificar a classe do Servlet correspondente a esse endereço.
Agora vamos dar uma olhada no formato específico do Uri. Primeiro, observe o URI mostrado na Figura 5.
Escreva a descrição da imagem aqui
. Aqui está uma explicação das quatro partes do URI mostradas na Figura 5.
R: O prefixo fixo do URI do Provedor de Conteúdo, ou seja, todos os URIs devem começar com content://.
B: A parte mais importante do URI. Esta parte é o identificador exclusivo do Provedor de Conteúdo. Para aplicativos de terceiros, esta parte usa o nome completo da classe (nome do pacote + nome da classe) no final para garantir a exclusividade do URI. Esta parte precisa ser definida na tag do arquivo AndroidManifest.xml. O código é o seguinte:

<provider name=".TransportationProvider" authorities="com.example.transportationprovider"  
          . . .  >  

C: Esta parte é o caminho do URI. Representa vários dados solicitados no URI. Esta parte é opcional e pode ser omitida se o Provedor de Conteúdo fornecer apenas os dados solicitados. Se o Provedor de Conteúdo quiser fornecer vários dados de solicitação. Você precisa adicionar vários caminhos, até mesmo subcaminhos. Por exemplo, "terra/ônibus", "terra/trem" e "mar/navio" especificam três tipos de dados possíveis.
D: Esta parte também é opcional. Se quiser passar um valor para o Provedor de Conteúdo, você pode passá-lo por esta parte. Claro, se não houver necessidade de passar um valor, esta parte pode ser omitida. O URI omitido é o seguinte:

content://com.example.transportationprovider/trains

1Este
exemplo usa o programa de dicionário eletrônico implementado no artigo "Implementação do Dicionário Eletrônico de Inglês Baseado no Android SDK1.5". Através do ContentProvider, a função de busca de palavras do dicionário eletrônico é compartilhada como um objeto Cursor. Dessa forma, outros aplicativos podem usar o ContentProvider para procurar palavras em inglês. Em relação aos detalhes específicos de implementação do dicionário de inglês, os leitores podem visualizar o artigo "Implementação do dicionário eletrônico de inglês baseado no Android SDK1.5" no seguinte endereço.

http://www.ophonesdn.com/article/show/111
1
No programa de dicionário eletrônico, é necessária uma classe DictionaryContentProvider, que é uma subclasse de ContentProvider. O método de consulta é implementado nesta classe e retorna resultados diferentes de acordo com URIs diferentes. Vamos primeiro dar uma olhada na classe DictionaryContentProvider e depois dar algumas explicações sobre o código.

… …

public  class  DictionaryContentProvider extends  ContentProvider  
{
    
      
    private  static  UriMatcher uriMatcher;  
    private  static  final  String AUTHORITY = "net.blogjava.mobile.dictionarycontentprovider" ;  
    private  static  final  int  SINGLE_WORD = 1 ;  
    private  static  final  int  PREFIX_WORDS = 2 ;  
    public  static  final  String DATABASE_PATH = android.os.Environment  
    .getExternalStorageDirectory().getAbsolutePath()  
    + "/dictionary" ;  
    public  static  final  String DATABASE_FILENAME = "dictionary.db" ;  
    private  SQLiteDatabase database;  
    static   
    {
    
      
        //  添加访问ContentProvider的Uri   
        uriMatcher = new  UriMatcher(UriMatcher.NO_MATCH);  
        uriMatcher.addURI(AUTHORITY, "single" , SINGLE_WORD);  
        uriMatcher.addURI(AUTHORITY, "prefix/*" , PREFIX_WORDS);  
    }  
    //  该方法在Activity的onCreate方法之前调用   
    @Override   
    public  boolean  onCreate()  
    {
    
      
        database = openDatabase();  
        return  true ;  
    }  
    //  在本例中只实现了query方法,其他的方法(insert、update和delete)与query方法的实现   
    //  类似   
    @Override   
    public  Cursor query(Uri uri, String[] projection, String selection,  
            String[] selectionArgs, String sortOrder)  
    {
    
      
        Cursor cursor = null ;  
        switch  (uriMatcher.match(uri))  
        {
    
      
            case  SINGLE_WORD:  
                //  查找指定的单词   
                cursor = database.query("t_words" , projection, selection,  
                        selectionArgs, null , null , sortOrder);  
                break ;  
            case  PREFIX_WORDS:  
                String word = uri.getPathSegments().get(1 );  
                //  查找以指定字符串开头的单词集合   
                cursor = database  
                        .rawQuery(  
                                "select english as _id, chinese from t_words where english like ?" ,  
                                new  String[]  
                                {
    
     word + "%"  });  
                break ;  

            default :  
                throw  new  IllegalArgumentException("<"  + uri + ">格式不正确." );  
        }  
        return  cursor;  
    }  
    ... ...  
}  

O código da classe DictionaryContentProvider requer a seguinte explicação.

A AUTORIDADE definida no início da classe DictionaryContentProvider é a primeira metade do URI usado para acessar o ContentProvider.
A segunda metade do URI que acessa o ContentProvider é especificada pelo método uriMatcher.addURI(…). O primeiro parâmetro deste método é AUTHORITY (a primeira metade do Uri), o segundo parâmetro é a segunda metade do Uri e o terceiro parâmetro é o código correspondente ao valor do segundo parâmetro. Quando outros aplicativos acessam ContentProvider por meio de Uri. Depois que o sistema analisa o Uri, ele converte o segundo valor do parâmetro do método addURI no código correspondente (o terceiro valor do parâmetro).
O segundo valor do parâmetro addURI pode usar caracteres curinga. Por exemplo, prefixo/ significa todos os caracteres. Tanto prefixo/abc quanto prefixo/xxx corresponderão com sucesso.
O URI para acessar ContentProvider é o componente do primeiro e segundo valores de parâmetro de addURI. Por exemplo, pressionando os dois URIs definidos em DictionaryContentProvider, você pode combinar os dois URIs a seguir, respectivamente.
content://net.blogjava.mobile.dictionarycontentprovider/single
content://net.blogjava.mobile.dictionarycontentprovider/prefix/wo

Deve-se observar que o URI que acessa o ContentProvider deve começar com “content://”.

No método de consulta, é recomendado usar o método de consulta do objeto SQLiteDatabase para consultar. Como os parâmetros do método de consulta correspondem aos parâmetros do método de consulta na classe DictionaryContentProvider, é mais conveniente de usar.
Como a aplicação com ContentProvider instalado chamará primeiro o método onCreate do ContentProvider (este método será chamado antes do método onCreate da Activity), portanto, basta colocar o método de abertura ou cópia do banco de dados (openDatabase) na classe DictionaryContentProvider , e em onCreate basta chamá-lo no método.
Somente o método de consulta é implementado na classe DictionaryContentProvider. Neste método é determinado qual Uri é enviado por outras aplicações. e manuseie adequadamente. Um desses dois Uri é para consultar a palavra especificada e o outro é para consultar todas as palavras que começam com uma determinada string (usada para exibir a lista de palavras).
Em seguida, configure a classe DictionaryContentProvider no arquivo AndroidManifest.xml.

OK, agora vamos ver como o aplicativo chama ContentProvider. A chave para chamar ContentProvider é usar o método getContentResolver para obter um objeto ContentResolver e acessar o ContentProvider por meio do método de consulta do objeto ContentResolver.
Primeiro defina duas constantes para acessar ContentProvider.

public final String DICTIONARY_SINGLE_WORD_URI = "content://net.blogjava.mobile.dictionarycontentprovider/single";  
public final String DICTIONARY_PREFIX_WORD_URI = "content://net.blogjava.mobile.dictionarycontentprovider/prefix";  

Em seguida, escreva o seguinte código no evento click do botão de consulta para consultar a palavra.

public  void  onClick(View view)  
{
    
      
    Uri uri = Uri.parse(DICTIONARY_SINGLE_WORD_URI);  
    //  通过ContentProvider查询单词,并返回Cursor对象,然后的操作就和直接从数据中获得   
    //  Cursor对象后的操作是一样的了   
    Cursor cursor = getContentResolver().query(uri, null , "english=?" ,  
            new  String[]{
    
     actvWord.getText().toString() }, null );  
    String result = "未找到该单词." ;  
    if  (cursor.getCount() > 0 )  
    {
    
      
        cursor.moveToFirst();  
        result = cursor.getString(cursor.getColumnIndex("chinese" ));  
    }  
    new  AlertDialog.Builder(this ).setTitle("查询结果" ).setMessage(result)  
            .setPositiveButton("关闭" , null ).show();  

}  

Abaixo está o código para exibir uma lista de palavras.

public  void  afterTextChanged(Editable s)  
{
    
      
    if  ("" .equals(s.toString()))  
        return ;  
    Uri uri = Uri.parse(DICTIONARY_PREFIX_WORD_URI + "/"  + s.toString());  
    //  从ContentProvider中获得以某个字符串开头的所有单词的Cursor对象   
    Cursor cursor = getContentResolver().query(uri, null , null , null , null );  
    DictionaryAdapter dictionaryAdapter = new  DictionaryAdapter(this ,  
            cursor, true );  
    actvWord.setAdapter(dictionaryAdapter);  
}  

Agora execute este exemplo e você verá a interface mostrada na Figura 6. Ao consultar palavras, será exibida a lista de palavras mostrada na Figura 7. Após a consulta dos resultados, será exibida a interface mostrada na Figura 8.

Método 3: transmissão

A transmissão é um método passivo de comunicação entre processos. Quando um programa envia uma transmissão para o sistema, outros aplicativos só podem receber passivamente os dados de transmissão. É como uma estação de rádio transmitindo: o público só pode ouvir passivamente e não pode se comunicar ativamente com a estação de rádio.
Enviar transmissões dentro de um aplicativo é relativamente simples. Basta chamar o método sendBroadcast. Este método requer um objeto Intent. Os dados que precisam ser transmitidos podem ser enviados por meio do objeto Intent.
Primeiro crie um projeto Android: sendbroadcast. Coloque dois componentes no arquivo de layout XML: EditText e Button. Ao clicar no botão, uma caixa de diálogo mostrando o texto no componente EditText aparecerá. Após fechar a caixa de diálogo, o método sendBroadcast será usado para enviar uma mensagem e o texto do componente EditText será passado. O objeto Intent é enviado. O código completo é o seguinte:

package  net.blogjava.mobile.sendbroadcast;  
... ...  
public  class  Main extends  Activity implements  OnClickListener  
{
    
      
    private  EditText editText;  
    @Override   
    public  void  onClick(View view)  
    {
    
      
        new  AlertDialog.Builder(this ).setMessage(editText.getText().toString())  
                .setPositiveButton("确定" , null ).show();       
        //  通过Intent类的构造方法指定广播的ID   
        Intent intent = new  Intent("net.blogjava.mobile.MYBROADCAST" );  
        //  将要广播的数据添加到Intent对象中     
        intent.putExtra("text" , editText.getText().toString());  
        //  发送广播     
        sendBroadcast(intent);  
    }  
    ... ...  
}  

O envio de transmissões não requer registro no arquivo AndroidManifest.xml, mas o recebimento de transmissões deve registrar o receptor no arquivo AndroidManifest.xml. Vamos escrever um aplicativo que receba transmissões. Primeiro crie um projeto Android: receptor. Em seguida, escreva uma classe MyReceiver, que é uma subclasse de BroadcastReceiver. O código é o seguinte:

package  net.blogjava.mobile.receiver;  
... ...  
public  class  MyReceiver extends  BroadcastReceiver  
{
    
      
    //  当sendbroadcast发送广播时,系统会调用onReceive方法来接收广播   
    @Override   
    public  void  onReceive(Context context, Intent intent)  
{
    
      
    //  判断是否为sendbroadcast发送的广播   
        if  ("net.blogjava.mobile.MYBROADCAST" .equals(intent.getAction()))  
        {
    
      
            Bundle bundle = intent.getExtras();  
            if  (bundle != null )  
            {
    
      
                String text = bundle.getString("text" );  
                Toast.makeText(context, "成功接收广播:"  + text, Toast.LENGTH_LONG).show();  
            }  
        }  
    }  
}

Quando uma aplicação envia um broadcast, o sistema chama o método onReceive para receber o broadcast e retorna o ID do broadcast através do método intent.getAction(), que é a string especificada pelo construtor Intent ao enviar o broadcast. Então você pode obter os dados correspondentes do objeto Bundle.
Por fim, você precisa registrar o receptor no arquivo AndroidManifest.xml. O código é o seguinte:

<!--  注册receiver   
<receiver android:name="MyReceiver">  
    <intent-filter>  
        <action android:name="net.blogjava.mobile.MYBROADCAST" />  
    </intent-filter>  
</receiver>  

Ao registrar a classe MyReceiver, você precisa usar um rótulo. O atributo android:name especifica a classe MyReceiver e o android:name do rótulo especifica o ID de transmissão.
Primeiro execute o programa receptor e então você poderá fechá-lo. A recepção de transmissões não depende do estado do programa. Mesmo que o programa esteja fechado, você ainda poderá receber transmissões. Em seguida, inicie o programa sendbroadcast. E digite "android" na caixa de texto e clique no botão, uma caixa de diálogo mostrando o conteúdo da caixa de texto aparecerá, conforme mostrado na Figura 9. Quando a caixa de diálogo é fechada, uma caixa de informações do Toast será exibida.Esta caixa de informações é exibida pelo programa receptor. Conforme mostrado na Figura 10.

Método 4: serviço AIDL

O serviço é um componente muito importante no sistema Android. O serviço pode ser executado independentemente do aplicativo. Ou seja, o aplicativo desempenha apenas a função de iniciar o Serviço. Depois que o Serviço for iniciado, mesmo que o aplicativo seja fechado, o Serviço ainda será executado em segundo plano.

O serviço no sistema Android tem principalmente duas funções: operação em segundo plano e comunicação entre processos. Escusado será dizer que a execução em segundo plano.Quando o serviço é iniciado, o código de negócios correspondente pode ser executado no objeto de serviço e o usuário não estará ciente disso. A comunicação entre processos é o assunto desta seção. Se você deseja que os aplicativos se comuniquem entre processos, você precisa usar o serviço AIDL de que falamos nesta seção. O nome completo do AIDL é Android Interface Definition Language, o que significa que AIDL é na verdade uma linguagem de definição de interface. Após definir a interface por meio desta linguagem, o plug-in Eclipse (ODT) gerará automaticamente o código de interface do código Java correspondente. Vamos dar uma olhada nas etapas básicas para escrever um serviço AIDL.

Crie um arquivo com a extensão aidl no diretório de pacotes do projeto Eclipse. O diretório do pacote é o diretório onde as classes Java estão localizadas. A sintaxe deste arquivo é semelhante ao código Java. O que está definido no arquivo aidl é a interface do serviço AIDL. Esta interface precisa ser acessada no programa que chama o serviço AIDL.
Se o conteúdo do arquivo aidl estiver correto, o plug-in Eclipse gerará automaticamente um arquivo de interface Java (*.java).
Crie uma classe de serviço (uma subclasse de Serviço).
Implemente a interface Java gerada pelo arquivo aidl.
Configure o serviço AIDL no arquivo AndroidManifest.xml. Em particular, observe que o valor do atributo android:name do rótulo é o ID do serviço que o cliente deseja referenciar, que é o valor do parâmetro do construtor da classe Intent.
Agora vamos escrever um serviço AIDL. Primeiro, crie um projeto Android: aidlservice. Existe uma classe Main no projeto aidlservice. Crie um arquivo IMyService.aidl em todos os diretórios da classe Main com o seguinte conteúdo:

package net.blogjava.mobile.aidlservice;  
interface IMyService  
{
    
      
    String getValue();  //  为AIDL服务的接口方法,调用AIDL服务的程序需要调用该方法  

}

Depois de salvar o arquivo IMyService.aidl, o ODT irá gerar um arquivo IMyService.java no diretório gen. Os leitores não precisam se preocupar com o conteúdo deste arquivo, nem modificar o conteúdo do arquivo. Este arquivo é mantido automaticamente pelo ODT.Enquanto o conteúdo do arquivo IMyService.aidl for modificado, o conteúdo do arquivo IMyService.java será alterado de acordo.
Em seguida, crie uma classe MyService, que é uma subclasse de Service. O código é o seguinte:

package net.blogjava.mobile.aidlservice;  
... ...  
public class MyService extends Service  
{
    
      
    //  IMyService.Stub类是根据IMyService.aidl文件生成的类,该类中包含了接口方法(getValue)  
    public class MyServiceImpl extends IMyService.Stub  
    {
    
      
        @Override  
        public String getValue() throws RemoteException  
        {
    
      
            return "从AIDL服务获得的值.";  
        }  
    }  
    @Override  
    public IBinder onBind(Intent intent)  
{
    
              
//  该方法必须返回MyServiceImpl类的对象实例  
        return new MyServiceImpl();  
    }  
}  

Por fim, você precisa configurar a classe MyService no arquivo AndroidManifest.xml. O código é o seguinte:

<!--  注册服务 -->  
<service android:name=".MyService">  
    <intent-filter>  
        <!--  指定调用AIDL服务的ID  -->  
        <action android:name="net.blogjava.mobile.aidlservice.IMyService" />  
    </intent-filter>  
</service>  

Vamos dar uma olhada em como chamar esse serviço AIDL. Primeiro crie um projeto Android: aidlclient. Em seguida, copie o arquivo IMyService.java gerado automaticamente no projeto aidlservice para o projeto aidlclient. Antes de chamar o serviço AIDL, você precisa usar o método bindService para vincular o serviço AIDL. O método bindService requer um objeto ServiceConnection. ServiceConnection possui um método onServiceConnected, que é chamado quando o serviço AIDL é vinculado com êxito. E retorne o objeto de serviço AIDL por meio do parâmetro de serviço. Abaixo está o código de conclusão para chamar o serviço AIDL.

package  net.blogjava.mobile.aidlclient;  
... ...  
public  class  Main extends  Activity implements  OnClickListener  
{
    
      
private  IMyService myService = null ;  
//  创建ServiceConnection对象   
    private  ServiceConnection serviceConnection = new  ServiceConnection()  
    {
    
      
        @Override   
        public  void  onServiceConnected(ComponentName name, IBinder service)  
        {
    
      
            // 获得AIDL服务对象   
            myService = IMyService.Stub.asInterface(service);  
            try   
            {
    
      
                //  调用AIDL服务对象中的getValue方法,并以对话框中显示该方法的返回值   
                new  AlertDialog.Builder(Main.this ).setMessage(  
                        myService.getValue()).setPositiveButton("确定" , null )  
                        .show();  
            }  
            catch  (Exception e)  
            {
    
      
            }  
        }  
        @Override   
        public  void  onServiceDisconnected(ComponentName name)  
        {
    
      
        }  
    };  
    @Override   
    public  void  onClick(View view)  
{
    
      
    //  绑定AIDL服务   
        bindService(new  Intent("net.blogjava.mobile.aidlservice.IMyService" ),  
                serviceConnection, Context.BIND_AUTO_CREATE);  
    }  
    ... ...  
} 

Ao escrever serviços e clientes AIDL, preste atenção aos dois pontos a seguir:

  1. O método onBind no serviço AIDL deve retornar o objeto de interface AIDL (objeto MyServiceImpl). Este objeto também é o segundo valor do parâmetro do método de evento onServiceConnected.
  2. O primeiro parâmetro do método bindService é o objeto Intent. Os parâmetros do método de construção do objeto precisam especificar o ID do serviço AIDL, que é o valor do atributo android:name da subtag da tag no arquivo AndroidManifest.xml.
    Agora execute o programa aidlservice para instalar o serviço AIDL, em seguida execute o programa aidlclient e clique no botão A caixa de diálogo mostrada na Figura 11 será exibida. As informações na caixa de diálogo são o valor de retorno do método getValue na interface de serviço AIDL.
    Escreva aqui uma descrição da imagem.
    Resumo
    Este artigo apresenta quatro métodos de comunicação entre processos: Activity, ContentProvider, Broadcast e AIDL Service. Entre eles, Activity pode chamar a atividade de outros aplicativos entre processos; ContentProvider pode acessar o objeto Cursor retornado por outros aplicativos; Broadcast usa um método de recebimento passivo, ou seja, o cliente só pode receber dados de transmissão e não pode enviar dados de transmissão para O programa envia a mensagem. O serviço AIDL pode expor uma interface no programa, para que outros aplicativos possam acessar o objeto de serviço AIDL como objetos locais. Esses quatro métodos de comunicação entre processos podem ser aplicados em diferentes situações. Por exemplo, Activity pode ser usado quando uma interface visual precisa ser exibida e ContentProvider pode ser usado quando um conjunto de registros precisa ser retornado. Quanto a qual método ou métodos usar para comunicação entre processos no aplicativo, os leitores podem escolher de acordo com a situação real.

Acho que você gosta

Origin blog.csdn.net/qq_32670947/article/details/131081316
Recomendado
Clasificación