Diferencia entre revisiones de «Intents implícitos. Permisos. Filtros.»
| (No se muestran 20 ediciones intermedias del mismo usuario) | |||
| Línea 86: | Línea 86: | ||
:* Aínda que o action pode ter calquera nome, por convención se usa este formato nos action definidos por Android: '''.intent.action.nome_acción'''. | :* Aínda que o action pode ter calquera nome, por convención se usa este formato nos action definidos por Android: '''.intent.action.nome_acción'''. | ||
:: Por exemplo, 'android.intent.action.MAIN' é o action que define Android para unha activity de categoría 'Launcher'. | :: Por exemplo, 'android.intent.action.MAIN' é o action que define Android para unha activity de categoría 'Launcher'. | ||
| − | :: Podemos consultar todos os action definidos no [https://developer.android.com/reference/android/content/Intent?hl=es-419# | + | :: Podemos consultar todos os action definidos no [https://developer.android.com/reference/android/content/Intent?hl=es-419#standard-activity-actions seguinte enlace]. |
| − | :: Se queremos chamar a unha activity que 'atenda' a un tipo de acción teríamos que poñer: Intent intent = new Intent(Intent.ACTION_MAIN); | + | :: Se queremos chamar a unha activity que 'atenda' a un tipo de acción teríamos que poñer: |
| + | |||
| + | <syntaxhighlight lang="java" line highlight=""> | ||
| + | Intent intent = new Intent(Intent.ACTION_MAIN); // Neste caso buscamos as que atendan o tipo ACTION_MAIN. | ||
| + | startActivity(intent); | ||
| + | </syntaxhighlight> | ||
| Línea 162: | Línea 167: | ||
: Como vemos temos: | : Como vemos temos: | ||
:* <action android:name="android.intent.action.MAIN" />: indica que é unha activity inicial que non se lle vai a enviar datos nin devolver datos. | :* <action android:name="android.intent.action.MAIN" />: indica que é unha activity inicial que non se lle vai a enviar datos nin devolver datos. | ||
| − | :* <category android:name="android.intent.category.LAUNCHER" />: indica que a activity pode | + | :* <category android:name="android.intent.category.LAUNCHER" />: indica que a activity pode aparecer no Launcher do S.O. (o programa que 'lanza' as aplicacións). |
| Línea 175: | Línea 180: | ||
</intent-filter> | </intent-filter> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| + | |||
| + | :* <action android:name="android.intent.action.VIEW" />: indica que vai poder visualizar algún tipo de información. | ||
| + | :* <category android:name="android.intent.category.BROWSABLE" />: Indica que a activity vai poder ser invocada dende o navegador ao premer nalgún enlace. | ||
| + | :* <category android:name="android.intent.category.DEFAULT" /> : Necesaria para que a activity poida ser invocada de forma implícita. | ||
: Neste caso cando esteamos navegando, ó premer sobre unha canción mp3 abrirase a posibilidade de reproducila coa nosa activity. Xa dentro da nosa activity, o dato que podemos obter é a URL da canción a reproducir os poderíamos obter da seguinte forma: | : Neste caso cando esteamos navegando, ó premer sobre unha canción mp3 abrirase a posibilidade de reproducila coa nosa activity. Xa dentro da nosa activity, o dato que podemos obter é a URL da canción a reproducir os poderíamos obter da seguinte forma: | ||
| Línea 209: | Línea 218: | ||
<br /> | <br /> | ||
| + | * Exemplos de emprego de Actions: https://developer.android.com/guide/components/intents-common?hl=es-419 | ||
| + | |||
| + | |||
| + | <br /> | ||
==Etiqueta category== | ==Etiqueta category== | ||
| Línea 227: | Línea 240: | ||
Intent intento = new Intent(Intent.ACTION_MAIN, null); | Intent intento = new Intent(Intent.ACTION_MAIN, null); | ||
intento.addCategory(Intent.CATEGORY_LAUNCHER); | intento.addCategory(Intent.CATEGORY_LAUNCHER); | ||
| − | startActivity( | + | startActivity(intento); |
</syntaxhighlight> | </syntaxhighlight> | ||
| Línea 234: | Línea 247: | ||
| + | <br /> | ||
| + | * Para lanzar a calculadora, en vez de empregar o nome do paquete xunto coa clase (estes nomes poden variar dun teléfono a outro debido a persoalización do S.O. Android que fai os diferentes fabricantes) podemos empregar unha categoría: | ||
| + | ::<syntaxhighlight lang="java" line highlight=""> | ||
| + | Intent intent = new Intent(); | ||
| + | intent.setAction(Intent.ACTION_MAIN); | ||
| + | intent.addCategory(Intent.CATEGORY_APP_CALCULATOR); | ||
| + | startActivity(intent); | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | : Pero tamén neste caso pode dar problemas, xa que para que unha aplicación poida ser chamada de forma implícita ten que ter no seu AndroidManifiest.xml esta outra categoría: <category android:name="android.intent.category.DEFAULT" /> | ||
| + | : Se non a ten, dará un erro. | ||
| + | : Veremos a continuación como comprobar se existe unha aplicación que atenda ao noso intento antes de lanzala. | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | <br /> | ||
| + | |||
| + | ==Comprobando a disponibilidade== | ||
| + | |||
| + | * Sempre que facemos uso das chamadas de tipo '''implícito''' deberíamos comprobar si existe algunha Activity que poide responder ao tipo de Action que imos solicitar. | ||
| + | |||
| + | : Isto é necesario xa que se non o comprobamos, a aplicación deixará de funcionar e se pechará. | ||
| + | : Para comprobalo temos que chamar ao [https://developer.android.com/reference/android/content/Intent.html?hl=es-419#resolveActivity(android.content.pm.PackageManager) método resolveActivity] da [https://developer.android.com/reference/android/content/Intent clase Intent]. | ||
| + | |||
| + | <syntaxhighlight lang="java" line highlight="2"> | ||
| + | Intento intent = new Intent(INDICAMOS A ACCIÓN); | ||
| + | if (intent.resolveActivity(getPackageManager())!=null){ // Comprobamos sempre nas chamadas implicitas se existe algunha activity que poida atender a miña petición | ||
| + | startActivity(intent); | ||
| + | } | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | |||
| + | * Indicar tamén que os action poden ser indicados chamando ao [https://developer.android.com/reference/android/content/Intent.html?hl=es-419#setAction(java.lang.String) método setAction] da [https://developer.android.com/reference/android/content/Intent clase Intent] da forma: | ||
| + | <syntaxhighlight lang="java" line highlight="2"> | ||
| + | Intent intent = new Intent(); | ||
| + | intent.setAction(Intent.ACTION_MAIN); | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | ==Caso Práctico 1== | ||
| + | |||
| + | * Partimos que xa temos creado o proxecto inicial como [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Creando_proxecto_base xa indicamos anteriormente]. | ||
| + | : Se non o temos creado antes, crearemos un novo paquete de nome: '''Intents''' como un subpaquete do teu paquete principal. | ||
| + | |||
| + | |||
| + | <br /> | ||
| + | * Dentro do paquete '''Intents''' crear unha nova 'Empty Activity' de nome: '''UD06_02_A1_Intents''' de tipo Launcher e sen compatibilidade. | ||
| + | : Modifica o arquivo '''AndroidManifiest.xml''' e engade unha label á activity como [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Creando_proxecto_base xa vimos na creación do proxecto base]. | ||
| + | |||
| + | * Dentro do paquete '''Intents''' crear unha nova 'Empty Activity' de nome: '''UD06_02_A2_Intents''' de <u>tipo no Launcher</u> e sen compatibilidade. | ||
| + | : Modifica o arquivo '''AndroidManifiest.xml''' e engade unha label á activity como [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Creando_proxecto_base xa vimos na creación do proxecto base]. | ||
| + | * Dentro do paquete '''Intents''' crear unha nova 'Empty Activity' de nome: '''UD06_02_A3_Intents''' de <u>tipo no Launcher</u> e sen compatibilidade. | ||
| + | : Modifica o arquivo '''AndroidManifiest.xml''' e engade unha label á activity como [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Creando_proxecto_base xa vimos na creación do proxecto base]. | ||
| + | |||
| + | |||
| + | |||
| + | <br /> | ||
| + | * O que imos facer é crear tres activities, unha principal cun botón dende a cal se chamará a outra das dúas activities creadas, pero en base ao seu Action: | ||
| + | <gallery caption="Lanzando unha activity polo seu Action" widths="350" heights="300px" perrow="2"> | ||
| + | Image:PDM_Intents_13.jpg| Activity principal de tipo Launcher. | ||
| + | Image:PDM_Intents_14.jpg| Ao premer sobre o botón o S.O. amosará todas as activities que teñan o tipo de acción. | ||
| + | Image:PDM_Intents_15.jpg| Escollimos a segunda Activity. | ||
| + | Image:PDM_Intents_16.jpg| Se prememos o botón Back podemos escoller a outra Activity. | ||
| + | </gallery> | ||
<br /> | <br /> | ||
| + | ===O XML da Activity Principal=== | ||
| + | <syntaxhighlight lang="xml" line highlight=""> | ||
| + | <?xml version="1.0" encoding="utf-8"?> | ||
| + | <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| + | xmlns:app="http://schemas.android.com/apk/res-auto" | ||
| + | xmlns:tools="http://schemas.android.com/tools" | ||
| + | android:layout_width="match_parent" | ||
| + | android:layout_height="match_parent" | ||
| + | tools:context=".Intents.UD06_02_A1_Intents"> | ||
| + | <Button | ||
| + | android:id="@+id/btnLanzar_UD06_02_A1_Intents" | ||
| + | android:layout_width="0dp" | ||
| + | android:layout_height="wrap_content" | ||
| + | android:layout_marginEnd="8dp" | ||
| + | android:layout_marginStart="8dp" | ||
| + | android:layout_marginTop="8dp" | ||
| + | android:text="Lanzar Activity Implicita" | ||
| + | app:layout_constraintEnd_toEndOf="parent" | ||
| + | app:layout_constraintStart_toStartOf="parent" | ||
| + | app:layout_constraintTop_toTopOf="parent" /> | ||
| + | </android.support.constraint.ConstraintLayout> | ||
| + | </syntaxhighlight> | ||
| − | == | + | <br /> |
| − | + | ===Código da Activity Principal=== | |
| − | + | <syntaxhighlight lang="java" line highlight="21"> | |
| − | + | package es.cursoandroid.cifprodolfoucha.aprendiendo.Intents; | |
| + | |||
| + | import android.app.Activity; | ||
| + | import android.content.Intent; | ||
| + | import android.os.Bundle; | ||
| + | import android.view.View; | ||
| + | |||
| + | import es.cursoandroid.cifprodolfoucha.aprendiendo.R; | ||
| − | = | + | public class UD06_02_A1_Intents extends Activity { |
| − | + | ||
| − | + | @Override | |
| − | + | protected void onCreate(Bundle savedInstanceState) { | |
| + | super.onCreate(savedInstanceState); | ||
| + | setContentView(R.layout.activity_ud06_02__a1__intents); | ||
| + | |||
| + | |||
| + | findViewById(R.id.btnLanzar_UD06_02_A1_Intents).setOnClickListener(new View.OnClickListener() { | ||
| + | @Override | ||
| + | public void onClick(View v) { | ||
| + | Intent intent = new Intent(Intent.ACTION_MAIN); | ||
| + | if (intent.resolveActivity(getPackageManager())!=null){ // Comprobamos sempre nas chamadas implicitas se existe algunha activity que poida atender a miña petición | ||
| + | startActivity(intent); | ||
| + | } | ||
| + | } | ||
| + | }); | ||
| + | |||
| + | } | ||
| + | } | ||
| + | |||
| + | </syntaxhighlight> | ||
| + | |||
| + | : Neste caso estamos a utilizar un dos Actions predefinidos do S.O. Android. | ||
| + | |||
| + | |||
| + | <br /> | ||
| + | ===O XML da Segunda Activity=== | ||
| + | <syntaxhighlight lang="xml" line highlight=""> | ||
| + | <?xml version="1.0" encoding="utf-8"?> | ||
| + | <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| + | xmlns:app="http://schemas.android.com/apk/res-auto" | ||
| + | xmlns:tools="http://schemas.android.com/tools" | ||
| + | android:layout_width="match_parent" | ||
| + | android:layout_height="match_parent" | ||
| + | tools:context=".Intents.UD06_02_A2_Intents"> | ||
| − | + | <TextView | |
| + | android:id="@+id/textView7" | ||
| + | android:layout_width="wrap_content" | ||
| + | android:layout_height="wrap_content" | ||
| + | android:layout_marginEnd="8dp" | ||
| + | android:layout_marginStart="8dp" | ||
| + | android:layout_marginTop="8dp" | ||
| + | android:text="Segunda Activity" | ||
| + | android:textSize="24sp" | ||
| + | app:layout_constraintEnd_toEndOf="parent" | ||
| + | app:layout_constraintStart_toStartOf="parent" | ||
| + | app:layout_constraintTop_toTopOf="parent" /> | ||
| + | </android.support.constraint.ConstraintLayout> | ||
| + | </syntaxhighlight> | ||
| − | |||
| − | + | <br /> | |
| + | ===O XML da Terceira Activity=== | ||
| + | <syntaxhighlight lang="xml" line highlight=""> | ||
| + | <?xml version="1.0" encoding="utf-8"?> | ||
| + | <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| + | xmlns:app="http://schemas.android.com/apk/res-auto" | ||
| + | xmlns:tools="http://schemas.android.com/tools" | ||
| + | android:layout_width="match_parent" | ||
| + | android:layout_height="match_parent" | ||
| + | tools:context=".Intents.UD06_02_A1_Intents"> | ||
| − | |||
| − | |||
<?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||
| − | < | + | <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| − | + | xmlns:app="http://schemas.android.com/apk/res-auto" | |
| − | android: | + | xmlns:tools="http://schemas.android.com/tools" |
| − | android: | + | android:layout_width="match_parent" |
| + | android:layout_height="match_parent" | ||
| + | tools:context=".Intents.UD06_02_A3_Intents"> | ||
| + | |||
| + | <TextView | ||
| + | android:id="@+id/textView8" | ||
| + | android:layout_width="wrap_content" | ||
| + | android:layout_height="wrap_content" | ||
| + | android:layout_marginBottom="8dp" | ||
| + | android:layout_marginEnd="8dp" | ||
| + | android:layout_marginStart="8dp" | ||
| + | android:layout_marginTop="8dp" | ||
| + | android:text="TERCEIRA ACTIVITY" | ||
| + | android:textSize="30sp" | ||
| + | app:layout_constraintBottom_toBottomOf="parent" | ||
| + | app:layout_constraintEnd_toEndOf="parent" | ||
| + | app:layout_constraintStart_toStartOf="parent" | ||
| + | app:layout_constraintTop_toTopOf="parent" /> | ||
| + | </android.support.constraint.ConstraintLayout> | ||
| + | </syntaxhighlight> | ||
| + | |||
| − | + | <br /> | |
| − | + | ===O Arquivo AndroidManifiest.xml=== | |
| − | |||
| − | + | <syntaxhighlight lang="xml" line highlight="13,14,21,22"> | |
| − | |||
| − | |||
| − | |||
| − | |||
<activity | <activity | ||
| − | android:name=". | + | android:name=".Intents.UD06_02_A1_Intents" |
| − | android:label=" | + | android:label="UD06_02_A1_Intents"> |
<intent-filter> | <intent-filter> | ||
<action android:name="android.intent.action.MAIN" /> | <action android:name="android.intent.action.MAIN" /> | ||
| Línea 283: | Línea 455: | ||
</intent-filter> | </intent-filter> | ||
</activity> | </activity> | ||
| − | <activity | + | <activity android:name=".Intents.UD06_02_A2_Intents" |
| − | android:name=". | + | android:label="UD06_02_A2_Intents"> |
| − | android:label=" | + | <intent-filter> |
| + | <action android:name="android.intent.action.MAIN" /> | ||
| + | <category android:name="android.intent.category.DEFAULT" /> | ||
| + | </intent-filter> | ||
| + | </activity> | ||
| + | |||
| + | <activity android:name=".Intents.UD06_02_A3_Intents" | ||
| + | android:label="UD06_02_A3_Intents"> | ||
| + | <intent-filter> | ||
| + | <action android:name="android.intent.action.MAIN" /> | ||
| + | <category android:name="android.intent.category.DEFAULT" /> | ||
| + | </intent-filter> | ||
| + | </activity> | ||
| + | |||
| + | </syntaxhighlight> | ||
| + | |||
| + | |||
| + | : Liñas 14,22: Vemos como debes incluír a categoría CATEGORY_DEFAULT no filtro de intents. Se non se pon, startActivity() ou startActivityForResult() non funcionarán. | ||
| + | |||
| + | |||
| + | <br /> | ||
| + | * Podemos facer o mesmo, pero definindo a noso propio Action (lembrar que nese caso <u>o nome do Action ten que estar precedido polo nome do paquete</u>): | ||
| + | : Modificamos o '''AndroidManifiest.xml''' | ||
| + | <syntaxhighlight lang="xml" line highlight="4,12"> | ||
| + | <activity android:name=".Intents.UD06_02_A2_Intents" | ||
| + | android:label="UD06_02_A2_Intents"> | ||
| + | <intent-filter> | ||
| + | <action android:name="es.cursoandroid.cifprodolfoucha.aprendiendo.ACCION_VISUALIZAR" /> | ||
| + | <category android:name="android.intent.category.DEFAULT" /> | ||
| + | </intent-filter> | ||
| + | </activity> | ||
| + | |||
| + | <activity android:name=".Intents.UD06_02_A3_Intents" | ||
| + | android:label="UD06_02_A3_Intents"> | ||
| + | <intent-filter> | ||
| + | <action android:name="es.cursoandroid.cifprodolfoucha.aprendiendo.ACCION_VISUALIZAR" /> | ||
| + | <category android:name="android.intent.category.DEFAULT" /> | ||
| + | </intent-filter> | ||
</activity> | </activity> | ||
| − | </ | + | |
| + | </syntaxhighlight> | ||
| + | |||
| + | |||
| + | * E modificamos o código da Activity Principal: | ||
| + | <syntaxhighlight lang="java" line highlight="12,24"> | ||
| + | package es.cursoandroid.cifprodolfoucha.aprendiendo.Intents; | ||
| + | |||
| + | import android.app.Activity; | ||
| + | import android.content.Intent; | ||
| + | import android.os.Bundle; | ||
| + | import android.view.View; | ||
| + | |||
| + | import es.cursoandroid.cifprodolfoucha.aprendiendo.R; | ||
| + | |||
| + | public class UD06_02_A1_Intents extends Activity { | ||
| + | |||
| + | public final String ACCION_VISUALIZAR = "es.cursoandroid.cifprodolfoucha.aprendiendo.ACCION_VISUALIZAR"; | ||
| + | |||
| + | @Override | ||
| + | protected void onCreate(Bundle savedInstanceState) { | ||
| + | super.onCreate(savedInstanceState); | ||
| + | setContentView(R.layout.activity_ud06_02__a1__intents); | ||
| + | |||
| + | |||
| + | findViewById(R.id.btnLanzar_UD06_02_A1_Intents).setOnClickListener(new View.OnClickListener() { | ||
| + | @Override | ||
| + | public void onClick(View v) { | ||
| + | Intent intent = new Intent(); | ||
| + | intent.setAction(ACCION_VISUALIZAR); | ||
| + | if (intent.resolveActivity(getPackageManager())!=null){ // Comprobamos sempre nas chamadas implicitas se existe algunha activity que poida atender a miña petición | ||
| + | startActivity(intent); | ||
| + | } | ||
| + | } | ||
| + | }); | ||
| + | |||
| + | } | ||
| + | } | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | |||
| + | <br /> | ||
| + | ==Caso Práctico 2== | ||
| + | |||
| + | '''<u>NOTA ACLARATORIA:</u>''' | ||
| + | |||
| + | * Chegados a este punto, aínda non vimos o tema dos permisos en Android. | ||
| + | : Se o alumno quere ir mirando o pode facer [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Avanzado_Permisos_AndroidManifiest.xml neste punto da WIKI]. | ||
| + | |||
| + | : Ata o de agora estamos a facer as probas sobre un emulador API 27. | ||
| + | : A partires da API 23, o sistema de permisos cambia e agora, certos permisos necesitan ser solicitados pola aplicación para poder funcionar. | ||
| + | |||
| + | : Este caso práctico fai uso de certos permisos que están dentro da categoría anterior, polo que o alumno necesitaría engadir o código que se atopa na sección da WIKI indicada anteriormente para poder funcionar sobre o emulador API 27. | ||
| + | |||
| + | : Se non se quere facer isto, este caso práctico (e o seguinte desta sección) facelo sobre un emulador cunha API < 23, por exemplo API 22 ou API 21. | ||
| + | ::<u>Nota:</u> Mellor crear un novo emulador que cambiar de API nun emulador existente, xa que a min doume problemas e non arrancaba. | ||
| + | |||
| + | |||
| + | <br /> | ||
| + | * Partimos que xa temos creado o proxecto inicial como [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Creando_proxecto_base xa indicamos anteriormente]. | ||
| + | : Se non o temos creado antes, crearemos un novo paquete de nome: '''Intents''' como un subpaquete do teu paquete principal. | ||
| + | |||
| + | <br /> | ||
| + | * Dentro do paquete '''Intents''' crear unha nova 'Empty Activity' de nome: '''UD06_03_A1_Intents''' de tipo Launcher e sen compatibilidade. | ||
| + | : Modifica o arquivo '''AndroidManifiest.xml''' e engade unha label á activity como [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Creando_proxecto_base xa vimos na creación do proxecto base]. | ||
| + | |||
| + | * Dentro do paquete '''Intents''' crear unha nova 'Empty Activity' de nome: '''UD06_03_A2_Intents''' de <u>tipo no Launcher</u> e sen compatibilidade. | ||
| + | : Modifica o arquivo '''AndroidManifiest.xml''' e engade unha label á activity como [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Creando_proxecto_base xa vimos na creación do proxecto base]. | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | <br /> | ||
| + | <gallery caption="Intents implícitos" widths="350" heights="300px" perrow="2"> | ||
| + | Image:PDM_Intents_17.jpg| Premer en '''Amosar contactos'''. <br>No ficheiro AndroidManifest demos permiso á aplicación para que acceda aos contactos. Para lanzar a seguinte activity da aplicación contactos o intent ten o seguinte formato:<br>'''intent = new Intent(Intent.ACTION_VIEW, Uri.parse("content://contacts/people/"));''' | ||
| + | Image:PDM_Intents_18.jpg| A lista de contactos. | ||
| + | Image:PDM_Intents_17.jpg| Premer en '''Seleccionar contactos'''. Lánzase o seguinte intent:<br>''' intent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts/people"));<br />startActivityForResult(intent, COD_CONTACTOS); | ||
| + | Image:PDM_Intents_18B.jpg| Seleccionamos un contacto e grazas á Acción coa que se lanzou o intent podemos devolver á actividade principal os datos dese contacto. | ||
| + | Image:PDM_Intents_18C.jpg| Cando volvemos á actividade principal podemos recuperar o nome do contacto seleccionado. | ||
| + | Image:PDM_Intents_17.jpg| Premer en '''Chamar por teléfono'''. Vaise lanzar o seguinte intent: <br>''' intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:(+34)981445566"));''' | ||
| + | Image:PDM_Intents_20.jpg|Xa iniciou a marcación ao teléfono indicado. | ||
| + | Image:PDM_Intents_17.jpg| Premer en '''Marcar nº teléfono'''. Vainos lanzar a activity na que nos decidimos se marcamos o número a marcar.<br>intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:(+34)986112233")); | ||
| + | Image:PDM_Intents_19.jpg| Activity na que o usuario marca o número de teléfono, pero que xa lle vén cuberto o campo. | ||
| + | Image:PDM_Intents_17.jpg| Premer agora en '''Abrir navegador*'''. Onde se van ofrecer un par de opcións para abrir a url especificada.<br>'''intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.es/"));''' | ||
| + | Image:PDM_Intents_21A.jpg| Activities que teñen definidos filtros de intención nos seus ficheiros AndroidMnaifest para procesar datos de tipo http. | ||
| + | Image:PDM_Intents_21.jpg| Neste caso seleccionouse o navegador web. | ||
| + | Image:PDM_Intents_22.jpg| Neste outro caso, seleccionouse a nosa actividade secundaria (RecibirDatos) e o que fai é amosar a URL. | ||
| + | </gallery> | ||
| + | |||
| + | ===Permisos=== | ||
| + | *Cando instalamos unha aplicación nun dispositivo real (non nun AVD) se precisa acceder a características que esixen algún tipo de permiso, o proceso de instalación pregunta se estamos dispostos a dar eses permisos para que a aplicación poida funcionar con tódalas súas funcionalidades. | ||
| + | *Por exemplo, instalando Gmail: | ||
| + | [[Image:Gmail.png|250px]] | ||
| + | |||
| + | *O proceso de instalación pregunta ao usuario se por exemplo lle deixa acceder a esta aplicación á súa lista de contactos. | ||
| + | |||
| + | *No ficheiro '''AndroidManifest.xml''' é onde se declaran os permisos que precisa a aplicación para poder facer uso de funcionalidades protexidas: contactos, cámara, mermoria usb, gps, etc. | ||
| + | |||
| + | *A través de unha ou varias etiquetas '''<uses-permission>''' vanse declarar os permisos que precisa a aplicación. | ||
| + | |||
| + | Exemplos de permisos no ficheiro AndroidManifest.xml | ||
| + | <syntaxhighlight lang="xml" line enclose="div" highlight="6-8" > | ||
| + | <?xml version="1.0" encoding="utf-8"?> | ||
| + | <manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
| + | package="es.cursoandroid.cifprodolfoucha.aprendiendo"> | ||
| + | |||
<uses-permission android:name="android.permission.CALL_PHONE" /> | <uses-permission android:name="android.permission.CALL_PHONE" /> | ||
<uses-permission android:name="android.permission.INTERNET" /> | <uses-permission android:name="android.permission.INTERNET" /> | ||
<uses-permission android:name="android.permission.READ_CONTACTS" /> | <uses-permission android:name="android.permission.READ_CONTACTS" /> | ||
| − | |||
| − | </ | + | |
| + | <application | ||
| + | android:allowBackup="true" | ||
| + | android:icon="@mipmap/ic_launcher" | ||
| + | android:label="@string/app_name" | ||
| + | android:roundIcon="@mipmap/ic_launcher_round" | ||
| + | android:supportsRtl="true" | ||
| + | android:theme="@style/AppTheme"> | ||
| + | <activity android:name=".MainActivity" /> | ||
| + | |||
</syntaxhighlight > | </syntaxhighlight > | ||
| − | *'''Liña | + | *'''Liña 6''': Permiso que "permite" realizar unha chamada de telefono sen pasar a través do interface do teléfono para que o usuario marque. |
| − | *'''Liña | + | *'''Liña 7''': Permítelle á aplicación abrir conexións de rede. |
| − | *'''Liña | + | *'''Liña 8''': Da súa lectura pódese concluír o que permite. |
*Para coñecer os permisos dispoñibles podemos consultar o seguinte enlace e incluílos directamente no xml: | *Para coñecer os permisos dispoñibles podemos consultar o seguinte enlace e incluílos directamente no xml: | ||
**http://developer.android.com/reference/android/Manifest.permission.html | **http://developer.android.com/reference/android/Manifest.permission.html | ||
| − | * | + | |
| − | + | * Se imos a instalar a aplicación nun dispositivo cunha API 23 ou superior, dependendo do tipo de permiso, teremos solicitalo especificamente por programación a maiores de telo posto no arquivo AndroidManifiest.xml como podemos ver [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Avanzado_Permisos_AndroidManifiest.xml neste sección da WIKI]. | |
| − | + | ||
| + | |||
*Lembrar que os permisos asígnanse no momento da instalación a aplicación. Nun dispositivo real pídeselle consentimento ao usuario, non así nun AVD. | *Lembrar que os permisos asígnanse no momento da instalación a aplicación. Nun dispositivo real pídeselle consentimento ao usuario, non así nun AVD. | ||
| − | ==Chamadas a intents de modo implícito== | + | ===Chamadas a intents de modo implícito=== |
*Como xa se dixo, un compoñente pode ser lanzado de forma implícita cando se indica a '''acción''' que se desexa realizar e se é o caso os datos sobre os que se desexa realizar a acción. | *Como xa se dixo, un compoñente pode ser lanzado de forma implícita cando se indica a '''acción''' que se desexa realizar e se é o caso os datos sobre os que se desexa realizar a acción. | ||
*Non se vai especificar cal é a activity que vai atender o intent. Incluso se hai varias Activities que poidan atender ese intent o sistema ofrecerá ao usuario as distintas posibilidades para que escolla. | *Non se vai especificar cal é a activity que vai atender o intent. Incluso se hai varias Activities que poidan atender ese intent o sistema ofrecerá ao usuario as distintas posibilidades para que escolla. | ||
| − | *Por exemplo, cando dende contactos se desexa enviar | + | *Por exemplo, cando dende contactos se desexa enviar unha mensaxe a un número de teléfono o sistema ofrece a posibilidade de que se envíe a través de sms, Whatsapp, Viber, etc, se se teñen instalados estes últimos. |
*A seguinte imaxe amosa un exemplo no que para abrir unha URL hai dúas aplicacións que o poden facer. | *A seguinte imaxe amosa un exemplo no que para abrir unha URL hai dúas aplicacións que o poden facer. | ||
| Línea 335: | Línea 658: | ||
**http://developer.android.com/reference/android/content/Intent.html | **http://developer.android.com/reference/android/content/Intent.html | ||
| − | ==Filtros de intencións (Intent Filters)== | + | ===Filtros de intencións (Intent Filters)=== |
*Android busca os compoñentes que poden responder a unha '''Acción''' nos filtros de intención que se definen no ficheiro '''AndroidManifest.xml''' de tódalas aplicacións que están instaladas no dispositivo. | *Android busca os compoñentes que poden responder a unha '''Acción''' nos filtros de intención que se definen no ficheiro '''AndroidManifest.xml''' de tódalas aplicacións que están instaladas no dispositivo. | ||
*Cando se constrúe unha activity nunha aplicación, pódese indicar os filtros de intención de manifestan que esa activity pode dar resposta as '''Accións''' que lanzan outras aplicacións. | *Cando se constrúe unha activity nunha aplicación, pódese indicar os filtros de intención de manifestan que esa activity pode dar resposta as '''Accións''' que lanzan outras aplicacións. | ||
| Línea 346: | Línea 669: | ||
*Para iso é preciso definir que esa Activity pode atender Accións de visionado de datos tipo http. | *Para iso é preciso definir que esa Activity pode atender Accións de visionado de datos tipo http. | ||
| + | : Modificamos o arquivo '''AndroidManifiest.xml''' para a segunda activity. | ||
| − | <syntaxhighlight lang="xml" line enclose="div" highlight=" | + | <syntaxhighlight lang="xml" line enclose="div" highlight="4-7" > |
| − | + | <activity android:name=".Intents.UD06_03_A2_Intents" | |
| − | + | android:label="UD06_03_02_Intents"> | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | <activity | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | android:label=" | ||
<intent-filter> | <intent-filter> | ||
<action android:name="android.intent.action.VIEW" /> | <action android:name="android.intent.action.VIEW" /> | ||
| − | |||
<category android:name="android.intent.category.DEFAULT" /> | <category android:name="android.intent.category.DEFAULT" /> | ||
| − | + | <category android:name="android.intent.category.BROWSABLE" /> | |
<data android:scheme="http" /> | <data android:scheme="http" /> | ||
</intent-filter> | </intent-filter> | ||
</activity> | </activity> | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
</syntaxhighlight > | </syntaxhighlight > | ||
| − | + | *'''Liña 4:''' indica para que tipo de accións esta dispoñible esta activity. | |
| − | *'''Liña | + | *'''Liña 5,6:''' A categoría indica as circunstancias nas que se debe desenvolver a acción. |
| − | *'''Liña | + | *'''Liña 7:''' o tipo de datos que pode atender esta activity cando haxa unha intención preguntando por recursos http. |
| − | *'''Liña | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| + | <br /> | ||
===XML do Layout principal=== | ===XML do Layout principal=== | ||
| − | + | <syntaxhighlight lang="xml" line enclose="div" highlight="" > | |
| − | <syntaxhighlight lang="xml" line enclose="div" highlight=" | + | <?xml version="1.0" encoding="utf-8"?> |
| − | < | + | <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| + | xmlns:app="http://schemas.android.com/apk/res-auto" | ||
| + | xmlns:tools="http://schemas.android.com/tools" | ||
android:layout_width="match_parent" | android:layout_width="match_parent" | ||
android:layout_height="match_parent" | android:layout_height="match_parent" | ||
| − | + | tools:context=".Intents.UD06_03_A1_Intents"> | |
| − | |||
| − | < | + | <Button |
| − | android:layout_width=" | + | android:id="@+id/btnAmosarContact_UD06_03_01_Intents" |
| + | android:layout_width="0dp" | ||
android:layout_height="wrap_content" | android:layout_height="wrap_content" | ||
| − | android: | + | android:layout_marginEnd="8dp" |
| + | android:layout_marginStart="8dp" | ||
| + | android:layout_marginTop="8dp" | ||
| + | android:text="Amosar Contacto" | ||
| + | app:layout_constraintEnd_toEndOf="parent" | ||
| + | app:layout_constraintStart_toStartOf="parent" | ||
| + | app:layout_constraintTop_toTopOf="parent" /> | ||
| − | + | <Button | |
| − | + | android:id="@+id/btnSelContacts_UD06_03_01_Intents" | |
| − | + | android:layout_width="0dp" | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | < | ||
| − | android:id="@+id/ | ||
| − | android:layout_width=" | ||
android:layout_height="wrap_content" | android:layout_height="wrap_content" | ||
| − | android: | + | android:layout_marginEnd="8dp" |
| − | android:text=" | + | android:layout_marginStart="8dp" |
| + | android:layout_marginTop="8dp" | ||
| + | android:text="Seleccionar Contacto" | ||
| + | app:layout_constraintEnd_toEndOf="parent" | ||
| + | app:layout_constraintStart_toStartOf="parent" | ||
| + | app:layout_constraintTop_toBottomOf="@+id/btnAmosarContact_UD06_03_01_Intents" /> | ||
| − | < | + | <Button |
| − | android:layout_width=" | + | android:id="@+id/btnChamar_UD06_03_01_Intents" |
| + | android:layout_width="0dp" | ||
android:layout_height="wrap_content" | android:layout_height="wrap_content" | ||
| − | android: | + | android:layout_marginEnd="8dp" |
| − | android:text=" | + | android:layout_marginStart="8dp" |
| − | + | android:layout_marginTop="8dp" | |
| + | android:text="Chamar por teléfono" | ||
| + | app:layout_constraintEnd_toEndOf="parent" | ||
| + | app:layout_constraintStart_toStartOf="parent" | ||
| + | app:layout_constraintTop_toBottomOf="@+id/btnSelContacts_UD06_03_01_Intents" /> | ||
<Button | <Button | ||
| − | android:id="@+id/ | + | android:id="@+id/btnMarcar_UD06_03_01_Intents" |
| − | android:layout_width=" | + | android:layout_width="0dp" |
android:layout_height="wrap_content" | android:layout_height="wrap_content" | ||
| − | android: | + | android:layout_marginEnd="8dp" |
| − | android:text=" | + | android:layout_marginStart="8dp" |
| + | android:layout_marginTop="8dp" | ||
| + | android:text="Marcar número de teléfono" | ||
| + | app:layout_constraintEnd_toEndOf="parent" | ||
| + | app:layout_constraintStart_toStartOf="parent" | ||
| + | app:layout_constraintTop_toBottomOf="@+id/btnChamar_UD06_03_01_Intents" /> | ||
<Button | <Button | ||
| − | android:id="@+id/ | + | android:id="@+id/btnAbrirNav_UD06_03_01_Intents" |
| − | android:layout_width=" | + | android:layout_width="0dp" |
| − | android:layout_height=" | + | android:layout_height="50dp" |
| − | android: | + | android:layout_marginEnd="8dp" |
| − | android:text=" | + | android:layout_marginStart="8dp" |
| + | android:layout_marginTop="8dp" | ||
| + | android:text="Abrir Navegador" | ||
| + | app:layout_constraintEnd_toEndOf="parent" | ||
| + | app:layout_constraintHorizontal_bias="0.502" | ||
| + | app:layout_constraintStart_toStartOf="parent" | ||
| + | app:layout_constraintTop_toBottomOf="@+id/btnMarcar_UD06_03_01_Intents" /> | ||
| + | |||
| + | </android.support.constraint.ConstraintLayout> | ||
| + | </syntaxhighlight> | ||
| + | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| + | <br /> | ||
===Código Java da activity principal=== | ===Código Java da activity principal=== | ||
| − | <syntaxhighlight lang="java" line enclose="div" highlight=" | + | |
| − | package | + | * Neste caso optouse por implemtar a Interface ActionListener na Activity. |
| + | |||
| + | <syntaxhighlight lang="java" line enclose="div" highlight="17,27-39,41-47,50-75" > | ||
| + | package es.cursoandroid.cifprodolfoucha.aprendiendo.Intents; | ||
import android.app.Activity; | import android.app.Activity; | ||
| Línea 528: | Línea 781: | ||
import android.os.Bundle; | import android.os.Bundle; | ||
import android.provider.ContactsContract; | import android.provider.ContactsContract; | ||
| − | |||
import android.view.View; | import android.view.View; | ||
| − | |||
| − | |||
import android.widget.Toast; | import android.widget.Toast; | ||
| − | + | import es.cursoandroid.cifprodolfoucha.aprendiendo.R; | |
| − | + | public class UD06_03_A1_Intents extends Activity implements View.OnClickListener { | |
| − | |||
| − | |||
| − | |||
| − | + | private static final int COD_CONTACTOS = 7; | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | @Override | |
| − | + | protected void onCreate(Bundle savedInstanceState) { | |
| − | + | super.onCreate(savedInstanceState); | |
| − | + | setContentView(R.layout.activity_ud06_03_a1__intents); | |
| − | |||
| − | |||
| − | + | xestionarEventos(); | |
| − | + | } | |
| − | + | protected void onActivityResult(int requestCode, int resultCode, Intent data) { | |
| − | |||
| − | + | if (requestCode == COD_CONTACTOS && resultCode == RESULT_OK) { | |
| − | + | Uri contactoData = data.getData(); | |
| + | Cursor cursor = getContentResolver().query(contactoData, null, null, null, null); | ||
| + | if (cursor.moveToFirst()) { | ||
| + | String nombre = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME)); | ||
| + | Toast.makeText(this, "Contacto: " + nombre, Toast.LENGTH_LONG).show(); | ||
| + | } | ||
| + | } | ||
| − | |||
| − | |||
| − | |||
| − | + | } | |
| − | + | private void xestionarEventos(){ | |
| − | + | findViewById(R.id.btnSelContacts_UD06_03_01_Intents).setOnClickListener(this); | |
| − | + | findViewById(R.id.btnAmosarContact_UD06_03_01_Intents).setOnClickListener(this); | |
| − | + | findViewById(R.id.btnMarcar_UD06_03_01_Intents).setOnClickListener(this); | |
| + | findViewById(R.id.btnChamar_UD06_03_01_Intents).setOnClickListener(this); | ||
| + | findViewById(R.id.btnAbrirNav_UD06_03_01_Intents).setOnClickListener(this); | ||
| + | } | ||
| − | + | @Override | |
| − | + | public void onClick(View v) { | |
| − | + | Intent intent = null; | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | switch (v.getId()) { | |
| + | case R.id.btnSelContacts_UD06_03_01_Intents: | ||
| + | intent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts/people/")); | ||
| + | startActivityForResult(intent, COD_CONTACTOS); | ||
| + | break; | ||
| + | case R.id.btnAmosarContact_UD06_03_01_Intents: | ||
| + | intent = new Intent(Intent.ACTION_VIEW, Uri.parse("content://contacts/people/")); | ||
| + | startActivity(intent); | ||
| + | break; | ||
| + | case R.id.btnMarcar_UD06_03_01_Intents: | ||
| + | intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:(+34)981445566")); | ||
| + | startActivity(intent); | ||
| + | break; | ||
| + | case R.id.btnChamar_UD06_03_01_Intents: | ||
| + | intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:(+34)986112233")); | ||
| + | startActivity(intent); | ||
| + | break; | ||
| + | case R.id.btnAbrirNav_UD06_03_01_Intents: | ||
| + | intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.es/")); | ||
| + | startActivity(intent); | ||
| + | break; | ||
| − | + | } | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| + | } | ||
} | } | ||
</syntaxhighlight > | </syntaxhighlight > | ||
| − | *'''Liña | + | *'''Liña 17''': Créase unha nova constante de tipo enteiro cun valor calquera para cando chamemos a activity de contactos para que nos devolva un contacto. |
| − | *'''Liñas | + | *'''Liñas 27-39''': Revisamos cando se volva dunha actividade secundaria, se é a de Contactos. Nese caso (escápase aos obxectivos desta unidade) créase un cursos para procesar os datos recibidos da activity contactos. |
| − | *'''Liñas | + | *'''Liñas 41-47''': Rexístrase o evento de Click en todos os botóns. |
| − | *'''Liñas | + | *'''Liñas 50-75''': Procesado dos distintos botóns, creación dos intents en función do tipo de acción e datos que se desexan procesar. |
| + | *'''Liñas 56''': Observar como se chama a activity de contactos para que logo nos devolva o contacto seleccionado. | ||
| + | <br /> | ||
| + | ===XML do Layout da Activity Secundaria: UD06_03_A2_Intents=== | ||
| − | |||
| − | |||
<syntaxhighlight lang="xml" line enclose="div" highlight="" > | <syntaxhighlight lang="xml" line enclose="div" highlight="" > | ||
| + | <?xml version="1.0" encoding="utf-8"?> | ||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
xmlns:tools="http://schemas.android.com/tools" | xmlns:tools="http://schemas.android.com/tools" | ||
| Línea 652: | Línea 874: | ||
<TextView | <TextView | ||
| − | android:id="@+id/ | + | android:id="@+id/tvResultado_UD06_03_A2_Intents" |
android:layout_width="wrap_content" | android:layout_width="wrap_content" | ||
android:layout_height="wrap_content" | android:layout_height="wrap_content" | ||
| Línea 659: | Línea 881: | ||
android:textSize="20sp" /> | android:textSize="20sp" /> | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
<Button | <Button | ||
| − | android:id="@+id/ | + | android:id="@+id/btnPechar_UD06_03_A2_Intents" |
android:layout_width="wrap_content" | android:layout_width="wrap_content" | ||
android:layout_height="wrap_content" | android:layout_height="wrap_content" | ||
android:layout_gravity="center_horizontal" | android:layout_gravity="center_horizontal" | ||
| − | |||
android:text="Pechar" /> | android:text="Pechar" /> | ||
</LinearLayout> | </LinearLayout> | ||
</syntaxhighlight > | </syntaxhighlight > | ||
| − | ===O código Java da Activity Secundaria: | + | |
| − | <syntaxhighlight lang="java" line enclose="div" highlight=" | + | <br /> |
| − | package | + | ===O código Java da Activity Secundaria: UD06_03_A2_Intents=== |
| + | <syntaxhighlight lang="java" line enclose="div" highlight="18-20" > | ||
| + | package es.cursoandroid.cifprodolfoucha.aprendiendo.Intents; | ||
import android.app.Activity; | import android.app.Activity; | ||
import android.content.Intent; | import android.content.Intent; | ||
import android.os.Bundle; | import android.os.Bundle; | ||
| − | |||
import android.view.View; | import android.view.View; | ||
| − | |||
import android.widget.TextView; | import android.widget.TextView; | ||
| − | + | import es.cursoandroid.cifprodolfoucha.aprendiendo.R; | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | public class UD06_03_A2_Intents extends Activity { | |
| − | |||
| − | |||
| − | |||
| − | + | @Override | |
| + | protected void onCreate(Bundle savedInstanceState) { | ||
| + | super.onCreate(savedInstanceState); | ||
| + | setContentView(R.layout.activity_ud06_03__a2__intents); | ||
| − | + | TextView tvResultado = (TextView) findViewById(R.id.tvResultado_UD06_03_A2_Intents); | |
| − | + | Intent intent = getIntent(); | |
| − | + | tvResultado.setText("URL: " + intent.getDataString()); | |
| − | |||
| − | |||
| + | findViewById(R.id.btnPechar_UD06_03_A2_Intents).setOnClickListener(new View.OnClickListener() { | ||
| + | @Override | ||
| + | public void onClick(View v) { | ||
| + | finish(); | ||
| + | } | ||
| + | }); | ||
| + | } | ||
} | } | ||
| + | </syntaxhighlight > | ||
| + | *'''Liñas 18-20''': Engadiuse a posibilidade de poder procesar intents cuxo esquema (getSchema) sexa de tipo http. Nese caso simplemente amosamos a URL á que desexaba conectarse o usuario. | ||
| − | |||
| − | |||
| + | <br /> | ||
| + | '''[https://wiki.cifprodolfoucha.es/index.php?title=Programaci%C3%B3n_de_dispositivos_m%C3%B3biles#UNIDADE_6:_Men.C3.BAs.2C_Intents_e_Di.C3.A1logos Enlace a la página principal de la UD6]''' | ||
| + | <br /> | ||
| + | <br /> | ||
| + | '''[https://wiki.cifprodolfoucha.es/index.php?title=Programación_de_dispositivos_móbiles Enlace a la página principal del curso]''' | ||
| + | <br /> | ||
| − | <br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- ( | + | <br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2018). |
Revisión actual del 17:37 11 nov 2020
Sumario
Intent en Activities
- Máis información neste enlace.
- Para lanzar outra activity se fai uso dos Intent.
- Nota Importante: En Android cando lanzamos unha nova activity, a anterior queda en memoria formando unha cola LIFO. O pechar a nova activity aparecerá a anterior. SE QUEREMOS PECHAR UNHA ACTIVITY PARA ABRIR UNHA NOVA DEBEMOS DE ABRIR A NOVA ACTIVITY E CHAMAR Ó MÉTODO finish() da activity que chama.
Construíndo un Intent
- http://developer.android.com/training/basics/firstapp/starting-activity.html
- http://developer.android.com/guide/components/intents-filters.html
- A efectos prácticos, unha activity vense a identificar cunha pantalla. Os intent´s vannos servir para chamar a ditas pantallas entre outras cousas.
- Tamén van servir para chamar a outras aplicacións ANDROID e esperar unha resposta (ou non).
- Un intent prové un enlace entre diferentes compoñentes coma poden ser dúas activity´s. Se pode traducir coma a intención da aplicación de facer algo.
- Cando chama, o pode facer indicando a Activity que quere lanzar (Intent Explícitos) ou simplemente indica a acción que quere realizar e é o S.O. quen decide en base a acción e o tipo de información, que aplicación debe lanzar (Intent Implícitos).
- Para chamar a unha activity dende outra temos o seguinte código:
1 Intent intent = new Intent(this, DisplayMessageActivity.class);
- O primeiro parámetro é unha referencia ó contexto (a clase Activity é unha subclase de Context, por iso poñemos this).
- O segundo parámetro é a clase que o Sistema Operativo ‘intentará’ cargar (no noso caso a activity a cargar).
- Nota: O context é unha interface que nos permite acceder os recursos da aplicación, clases e outras operacións, como acceso as activities…
Etiqueta action
- Como vimos anteriormente, cada vez que se crea unha activity se engade no AndroidManifiest.xml.
- Dita activity ten asociado un filtro de intento (<intent-filter>) ou podemos engadirllo en caso de non ser un tipo 'launcher'.
- Dentro deste temos a etiqueta <action....> no que se define o nome do filtro para a activity.
- Desta forma podemos chamar a outra activity polo seu nome:
- startActivity(new Intent(this,NomeClase.class); :Esta é a opción vista ata o de agora.
- startActivity(new Intent(“nome.definido.etiqueta.action”)); :Chamamos co nome definido na etiqueta action.
- Neste segundo caso teremos que definir unha categoría por defecto, para poder chamar a activity polo seu nome (<category android:name="android.intent.category.DEFAULT" />)
- Vexamos un exemplo:
1 <activity 2 android:name="com.example.variasactiviy.MainActivity1" 3 android:label="@string/app_name1" > 4 <intent-filter> 5 <action android:name="android.intent.action.MAIN" /> 6 <category android:name="android.intent.category.LAUNCHER" /> 7 </intent-filter> 8 </activity> 9 <activity 10 android:name="com.example.variasactiviy.MainActivity2" 11 android:label="@string/app_name2" > 12 <intent-filter> 13 <action android:name="com.example.variasactiviy.ActionMainActivity2" /> 14 <category android:name="android.intent.category.DEFAULT" /> 15 </intent-filter> 16 </activity>
- Para chamar a segunda activity:
1 startActivity(new Intent("com.example.variasactiviy.ActionMainActivity2"));
- Nome dos action:
- Aínda que o action pode ter calquera nome, por convención se usa este formato nos action definidos por Android: .intent.action.nome_acción.
- Por exemplo, 'android.intent.action.MAIN' é o action que define Android para unha activity de categoría 'Launcher'.
- Podemos consultar todos os action definidos no seguinte enlace.
- Se queremos chamar a unha activity que 'atenda' a un tipo de acción teríamos que poñer:
1 Intent intent = new Intent(Intent.ACTION_MAIN); // Neste caso buscamos as que atendan o tipo ACTION_MAIN.
2 startActivity(intent);
- No caso das activities definidas por nos que non teñen un action 'predefinido' de Android, o name terá o formato: nome_paquete.nome_accion.
- No exemplo anterior: com.example.variasactiviy.ActionMainActivity2
- Unha activity pode levar varias accións asociadas.
- Se existen varias activities co mesmo nome o S.O. amosará unha mensaxe para que escollamos cal delas debe abrir.
- Os intent´s vainos servir para chamar a outras aplicacións que estean instaladas no sistema operativo Android. A idea é chamar a unha aplicación cun tipo de dato, e que sexa o S.O. en base os 'filter' das aplicacións instaladas, o que chame á aplicación correspondente.
Dentro do Intent irán os datos necesarios para que a aplicación que reciba a petición poida dar o servizo. Así, se abro o navegador, podo enviarlle a url que quero que abra (é opcional mandalo). Para mandar os datos faremos uso do método putExtra da clase Intent (o veremos despois noutro punto).
- Así, grazas a esta forma de traballar, podemos usar Intent´s:
- Para chamar a un teléfono
- Para enviar un sms/correo
- Para abrir o navegador
- Para abrir unha localización dentro dun mapa
- Ou para chamar a Activities doutras aplicacións.
- Por exemplo:
- Un intent para enviar un correo electrónico:
1 Intent intent = new Intent(Intent.ACTION_SEND); 2 intent.setType("application/octet-stream"); 3 intent.putExtra(Intent.EXTRA_SUBJECT, "Subject"); 4 intent.putExtra(Intent.EXTRA_TEXT, "Texto do Mail"); 5 intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"android@cursoandroid.es"}); 6 startActivity(intent);
- Un intent para amosar o dial de teléfono:
1 Intent intent = new Intent(Intent.ACTION_DIAL); 2 startActivity(intent);
- Un intent para lanzar unha busca do navegador web:
1 Intent intent = new Intent(Intent.ACTION_WEB_SEARCH); 2 intent.putExtra(SearchManager.QUERY, "Android"); 3 startActivity(intent);
- A un Intent podemos asociarlle unha acción, uns datos e unha categoría.
- As activities poden declarar o tipo de accións que poden levar a cabo e os tipos de datos que poden xestionar.
- As accións son cadeas de texto estándar que describen o que unha activity pode facer.
- Por exemplo android.intent.action.VIEW é unha acción que indica que a actividade pode amosar datos ó usuario.
- Máis información en:
- Cando definimos unha activity normalmente aparece isto no AndroidManifiest,xml:
1 <activity 2 android:name=".MainActivity" 3 android:label="@string/title_activity_main" > 4 <intent-filter> 5 <action android:name="android.intent.action.MAIN" /> 6 <category android:name="android.intent.category.LAUNCHER" /> 7 </intent-filter> 8 </activity>
- Como vemos temos:
- <action android:name="android.intent.action.MAIN" />: indica que é unha activity inicial que non se lle vai a enviar datos nin devolver datos.
- <category android:name="android.intent.category.LAUNCHER" />: indica que a activity pode aparecer no Launcher do S.O. (o programa que 'lanza' as aplicacións).
- Outro exemplo sería o seguinte:
1 <intent-filter > 2 <action android:name="android.intent.action.VIEW" /> 3 <category android:name="android.intent.category.DEFAULT" /> 4 <category android:name="android.intent.category.BROWSABLE" /> 5 <data android:scheme="http" android:pathPattern=".*mp3" android:mimeType="audio/*" /> 6 </intent-filter>
- <action android:name="android.intent.action.VIEW" />: indica que vai poder visualizar algún tipo de información.
- <category android:name="android.intent.category.BROWSABLE" />: Indica que a activity vai poder ser invocada dende o navegador ao premer nalgún enlace.
- <category android:name="android.intent.category.DEFAULT" /> : Necesaria para que a activity poida ser invocada de forma implícita.
- Neste caso cando esteamos navegando, ó premer sobre unha canción mp3 abrirase a posibilidade de reproducila coa nosa activity. Xa dentro da nosa activity, o dato que podemos obter é a URL da canción a reproducir os poderíamos obter da seguinte forma:
1 Intent intent = getIntent(); 2 // Por se voltamos do navegador web. 3 if (intent != null && intent.getData() != null) { 4 TextView txturl = (TextView)findViewById(R.id.txtURL); 5 txturl.setText(intent.getData().toString()); 6 }
- No caso da ACTION_VIEW é unha acción moi xenérica e Android ten que descubrir que activity pode chamar facendo uso da composición da URI.
- Para iso mira o esquema que posúe a URI (neste caso http) e pregunta a todas as actividades cal delas entende dito esquema.
- Poderíamos ter rexistrados varios esquemas:
1 <activity ...> 2 <intent -filter> 3 <action android:name="android.intent.action.VIEW"/> 4 <data android:scheme="http" /> 5 <data android:scheme="https" /> 6 </intent> 7 </activity>
- Máis información sobre a etiqueta en http://developer.android.com/guide/topics/manifest/data-element.html
- Exemplos de emprego de Actions: https://developer.android.com/guide/components/intents-common?hl=es-419
Etiqueta category
- No que se refire a etiqueta <category> esta se utiliza para categorizar as activities e que se podan atopar máis facilmente.
- Máis información en: http://developer.android.com/reference/android/content/Intent.html#CATEGORY_ALTERNATIVE
- Anteriormente vimos un exemplo no que tiñamos: <category android:name="android.intent.category.BROWSABLE" />
- Se ides o enlace anterior e buscades dita categoría, vos informa que dita categoría é necesaria para que unha activity sexa chamada dende o navegador.
- Por exemplo, mentres que o sistema se está iniciando busca as activities que teñan a category de launcher: <category android:name="android.intent.category.LAUNCHER" />
- Por exemplo, poderíamos lanzar unha activity en base a súa categoría:
1 Intent intento = new Intent(Intent.ACTION_MAIN, null); 2 intento.addCategory(Intent.CATEGORY_LAUNCHER); 3 startActivity(intento);
Dará como resultado:
- Para lanzar a calculadora, en vez de empregar o nome do paquete xunto coa clase (estes nomes poden variar dun teléfono a outro debido a persoalización do S.O. Android que fai os diferentes fabricantes) podemos empregar unha categoría:
1 Intent intent = new Intent(); 2 intent.setAction(Intent.ACTION_MAIN); 3 intent.addCategory(Intent.CATEGORY_APP_CALCULATOR); 4 startActivity(intent);
- Pero tamén neste caso pode dar problemas, xa que para que unha aplicación poida ser chamada de forma implícita ten que ter no seu AndroidManifiest.xml esta outra categoría: <category android:name="android.intent.category.DEFAULT" />
- Se non a ten, dará un erro.
- Veremos a continuación como comprobar se existe unha aplicación que atenda ao noso intento antes de lanzala.
Comprobando a disponibilidade
- Sempre que facemos uso das chamadas de tipo implícito deberíamos comprobar si existe algunha Activity que poide responder ao tipo de Action que imos solicitar.
- Isto é necesario xa que se non o comprobamos, a aplicación deixará de funcionar e se pechará.
- Para comprobalo temos que chamar ao método resolveActivity da clase Intent.
1 Intento intent = new Intent(INDICAMOS A ACCIÓN);
2 if (intent.resolveActivity(getPackageManager())!=null){ // Comprobamos sempre nas chamadas implicitas se existe algunha activity que poida atender a miña petición
3 startActivity(intent);
4 }
- Indicar tamén que os action poden ser indicados chamando ao método setAction da clase Intent da forma:
1 Intent intent = new Intent();
2 intent.setAction(Intent.ACTION_MAIN);
Caso Práctico 1
- Partimos que xa temos creado o proxecto inicial como xa indicamos anteriormente.
- Se non o temos creado antes, crearemos un novo paquete de nome: Intents como un subpaquete do teu paquete principal.
- Dentro do paquete Intents crear unha nova 'Empty Activity' de nome: UD06_02_A1_Intents de tipo Launcher e sen compatibilidade.
- Modifica o arquivo AndroidManifiest.xml e engade unha label á activity como xa vimos na creación do proxecto base.
- Dentro do paquete Intents crear unha nova 'Empty Activity' de nome: UD06_02_A2_Intents de tipo no Launcher e sen compatibilidade.
- Modifica o arquivo AndroidManifiest.xml e engade unha label á activity como xa vimos na creación do proxecto base.
- Dentro do paquete Intents crear unha nova 'Empty Activity' de nome: UD06_02_A3_Intents de tipo no Launcher e sen compatibilidade.
- Modifica o arquivo AndroidManifiest.xml e engade unha label á activity como xa vimos na creación do proxecto base.
- O que imos facer é crear tres activities, unha principal cun botón dende a cal se chamará a outra das dúas activities creadas, pero en base ao seu Action:
- Lanzando unha activity polo seu Action
O XML da Activity Principal
1 <?xml version="1.0" encoding="utf-8"?>
2 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 tools:context=".Intents.UD06_02_A1_Intents">
8
9 <Button
10 android:id="@+id/btnLanzar_UD06_02_A1_Intents"
11 android:layout_width="0dp"
12 android:layout_height="wrap_content"
13 android:layout_marginEnd="8dp"
14 android:layout_marginStart="8dp"
15 android:layout_marginTop="8dp"
16 android:text="Lanzar Activity Implicita"
17 app:layout_constraintEnd_toEndOf="parent"
18 app:layout_constraintStart_toStartOf="parent"
19 app:layout_constraintTop_toTopOf="parent" />
20 </android.support.constraint.ConstraintLayout>
Código da Activity Principal
1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Intents;
2
3 import android.app.Activity;
4 import android.content.Intent;
5 import android.os.Bundle;
6 import android.view.View;
7
8 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
9
10 public class UD06_02_A1_Intents extends Activity {
11
12 @Override
13 protected void onCreate(Bundle savedInstanceState) {
14 super.onCreate(savedInstanceState);
15 setContentView(R.layout.activity_ud06_02__a1__intents);
16
17
18 findViewById(R.id.btnLanzar_UD06_02_A1_Intents).setOnClickListener(new View.OnClickListener() {
19 @Override
20 public void onClick(View v) {
21 Intent intent = new Intent(Intent.ACTION_MAIN);
22 if (intent.resolveActivity(getPackageManager())!=null){ // Comprobamos sempre nas chamadas implicitas se existe algunha activity que poida atender a miña petición
23 startActivity(intent);
24 }
25 }
26 });
27
28 }
29 }
- Neste caso estamos a utilizar un dos Actions predefinidos do S.O. Android.
O XML da Segunda Activity
1 <?xml version="1.0" encoding="utf-8"?>
2 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 tools:context=".Intents.UD06_02_A2_Intents">
8
9 <TextView
10 android:id="@+id/textView7"
11 android:layout_width="wrap_content"
12 android:layout_height="wrap_content"
13 android:layout_marginEnd="8dp"
14 android:layout_marginStart="8dp"
15 android:layout_marginTop="8dp"
16 android:text="Segunda Activity"
17 android:textSize="24sp"
18 app:layout_constraintEnd_toEndOf="parent"
19 app:layout_constraintStart_toStartOf="parent"
20 app:layout_constraintTop_toTopOf="parent" />
21 </android.support.constraint.ConstraintLayout>
O XML da Terceira Activity
1 <?xml version="1.0" encoding="utf-8"?>
2 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 tools:context=".Intents.UD06_02_A1_Intents">
8
9 <?xml version="1.0" encoding="utf-8"?>
10 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
11 xmlns:app="http://schemas.android.com/apk/res-auto"
12 xmlns:tools="http://schemas.android.com/tools"
13 android:layout_width="match_parent"
14 android:layout_height="match_parent"
15 tools:context=".Intents.UD06_02_A3_Intents">
16
17 <TextView
18 android:id="@+id/textView8"
19 android:layout_width="wrap_content"
20 android:layout_height="wrap_content"
21 android:layout_marginBottom="8dp"
22 android:layout_marginEnd="8dp"
23 android:layout_marginStart="8dp"
24 android:layout_marginTop="8dp"
25 android:text="TERCEIRA ACTIVITY"
26 android:textSize="30sp"
27 app:layout_constraintBottom_toBottomOf="parent"
28 app:layout_constraintEnd_toEndOf="parent"
29 app:layout_constraintStart_toStartOf="parent"
30 app:layout_constraintTop_toTopOf="parent" />
31 </android.support.constraint.ConstraintLayout>
O Arquivo AndroidManifiest.xml
1 <activity
2 android:name=".Intents.UD06_02_A1_Intents"
3 android:label="UD06_02_A1_Intents">
4 <intent-filter>
5 <action android:name="android.intent.action.MAIN" />
6
7 <category android:name="android.intent.category.LAUNCHER" />
8 </intent-filter>
9 </activity>
10 <activity android:name=".Intents.UD06_02_A2_Intents"
11 android:label="UD06_02_A2_Intents">
12 <intent-filter>
13 <action android:name="android.intent.action.MAIN" />
14 <category android:name="android.intent.category.DEFAULT" />
15 </intent-filter>
16 </activity>
17
18 <activity android:name=".Intents.UD06_02_A3_Intents"
19 android:label="UD06_02_A3_Intents">
20 <intent-filter>
21 <action android:name="android.intent.action.MAIN" />
22 <category android:name="android.intent.category.DEFAULT" />
23 </intent-filter>
24 </activity>
- Liñas 14,22: Vemos como debes incluír a categoría CATEGORY_DEFAULT no filtro de intents. Se non se pon, startActivity() ou startActivityForResult() non funcionarán.
- Podemos facer o mesmo, pero definindo a noso propio Action (lembrar que nese caso o nome do Action ten que estar precedido polo nome do paquete):
- Modificamos o AndroidManifiest.xml
1 <activity android:name=".Intents.UD06_02_A2_Intents"
2 android:label="UD06_02_A2_Intents">
3 <intent-filter>
4 <action android:name="es.cursoandroid.cifprodolfoucha.aprendiendo.ACCION_VISUALIZAR" />
5 <category android:name="android.intent.category.DEFAULT" />
6 </intent-filter>
7 </activity>
8
9 <activity android:name=".Intents.UD06_02_A3_Intents"
10 android:label="UD06_02_A3_Intents">
11 <intent-filter>
12 <action android:name="es.cursoandroid.cifprodolfoucha.aprendiendo.ACCION_VISUALIZAR" />
13 <category android:name="android.intent.category.DEFAULT" />
14 </intent-filter>
15 </activity>
- E modificamos o código da Activity Principal:
1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Intents;
2
3 import android.app.Activity;
4 import android.content.Intent;
5 import android.os.Bundle;
6 import android.view.View;
7
8 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
9
10 public class UD06_02_A1_Intents extends Activity {
11
12 public final String ACCION_VISUALIZAR = "es.cursoandroid.cifprodolfoucha.aprendiendo.ACCION_VISUALIZAR";
13
14 @Override
15 protected void onCreate(Bundle savedInstanceState) {
16 super.onCreate(savedInstanceState);
17 setContentView(R.layout.activity_ud06_02__a1__intents);
18
19
20 findViewById(R.id.btnLanzar_UD06_02_A1_Intents).setOnClickListener(new View.OnClickListener() {
21 @Override
22 public void onClick(View v) {
23 Intent intent = new Intent();
24 intent.setAction(ACCION_VISUALIZAR);
25 if (intent.resolveActivity(getPackageManager())!=null){ // Comprobamos sempre nas chamadas implicitas se existe algunha activity que poida atender a miña petición
26 startActivity(intent);
27 }
28 }
29 });
30
31 }
32 }
Caso Práctico 2
NOTA ACLARATORIA:
- Chegados a este punto, aínda non vimos o tema dos permisos en Android.
- Se o alumno quere ir mirando o pode facer neste punto da WIKI.
- Ata o de agora estamos a facer as probas sobre un emulador API 27.
- A partires da API 23, o sistema de permisos cambia e agora, certos permisos necesitan ser solicitados pola aplicación para poder funcionar.
- Este caso práctico fai uso de certos permisos que están dentro da categoría anterior, polo que o alumno necesitaría engadir o código que se atopa na sección da WIKI indicada anteriormente para poder funcionar sobre o emulador API 27.
- Se non se quere facer isto, este caso práctico (e o seguinte desta sección) facelo sobre un emulador cunha API < 23, por exemplo API 22 ou API 21.
- Nota: Mellor crear un novo emulador que cambiar de API nun emulador existente, xa que a min doume problemas e non arrancaba.
- Partimos que xa temos creado o proxecto inicial como xa indicamos anteriormente.
- Se non o temos creado antes, crearemos un novo paquete de nome: Intents como un subpaquete do teu paquete principal.
- Dentro do paquete Intents crear unha nova 'Empty Activity' de nome: UD06_03_A1_Intents de tipo Launcher e sen compatibilidade.
- Modifica o arquivo AndroidManifiest.xml e engade unha label á activity como xa vimos na creación do proxecto base.
- Dentro do paquete Intents crear unha nova 'Empty Activity' de nome: UD06_03_A2_Intents de tipo no Launcher e sen compatibilidade.
- Modifica o arquivo AndroidManifiest.xml e engade unha label á activity como xa vimos na creación do proxecto base.
- Intents implícitos
Premer en Chamar por teléfono. Vaise lanzar o seguinte intent:
intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:(+34)981445566"));Premer en Marcar nº teléfono. Vainos lanzar a activity na que nos decidimos se marcamos o número a marcar.
intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:(+34)986112233"));Premer agora en Abrir navegador*. Onde se van ofrecer un par de opcións para abrir a url especificada.
intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.es/"));
Permisos
- Cando instalamos unha aplicación nun dispositivo real (non nun AVD) se precisa acceder a características que esixen algún tipo de permiso, o proceso de instalación pregunta se estamos dispostos a dar eses permisos para que a aplicación poida funcionar con tódalas súas funcionalidades.
- Por exemplo, instalando Gmail:
- O proceso de instalación pregunta ao usuario se por exemplo lle deixa acceder a esta aplicación á súa lista de contactos.
- No ficheiro AndroidManifest.xml é onde se declaran os permisos que precisa a aplicación para poder facer uso de funcionalidades protexidas: contactos, cámara, mermoria usb, gps, etc.
- A través de unha ou varias etiquetas <uses-permission> vanse declarar os permisos que precisa a aplicación.
Exemplos de permisos no ficheiro AndroidManifest.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3 package="es.cursoandroid.cifprodolfoucha.aprendiendo">
4
5
6 <uses-permission android:name="android.permission.CALL_PHONE" />
7 <uses-permission android:name="android.permission.INTERNET" />
8 <uses-permission android:name="android.permission.READ_CONTACTS" />
9
10
11 <application
12 android:allowBackup="true"
13 android:icon="@mipmap/ic_launcher"
14 android:label="@string/app_name"
15 android:roundIcon="@mipmap/ic_launcher_round"
16 android:supportsRtl="true"
17 android:theme="@style/AppTheme">
18 <activity android:name=".MainActivity" />
- Liña 6: Permiso que "permite" realizar unha chamada de telefono sen pasar a través do interface do teléfono para que o usuario marque.
- Liña 7: Permítelle á aplicación abrir conexións de rede.
- Liña 8: Da súa lectura pódese concluír o que permite.
- Para coñecer os permisos dispoñibles podemos consultar o seguinte enlace e incluílos directamente no xml:
- Se imos a instalar a aplicación nun dispositivo cunha API 23 ou superior, dependendo do tipo de permiso, teremos solicitalo especificamente por programación a maiores de telo posto no arquivo AndroidManifiest.xml como podemos ver neste sección da WIKI.
- Lembrar que os permisos asígnanse no momento da instalación a aplicación. Nun dispositivo real pídeselle consentimento ao usuario, non así nun AVD.
Chamadas a intents de modo implícito
- Como xa se dixo, un compoñente pode ser lanzado de forma implícita cando se indica a acción que se desexa realizar e se é o caso os datos sobre os que se desexa realizar a acción.
- Non se vai especificar cal é a activity que vai atender o intent. Incluso se hai varias Activities que poidan atender ese intent o sistema ofrecerá ao usuario as distintas posibilidades para que escolla.
- Por exemplo, cando dende contactos se desexa enviar unha mensaxe a un número de teléfono o sistema ofrece a posibilidade de que se envíe a través de sms, Whatsapp, Viber, etc, se se teñen instalados estes últimos.
- A seguinte imaxe amosa un exemplo no que para abrir unha URL hai dúas aplicacións que o poden facer.
- Para lanzar un intent de modo implícito precísase indicar:
- Acción (action): A acción que se desexa levar a cabo. Por exemplo,
- ACTION_VIEW, para mostrar datos ao usario
- ACTION_EDIT, para editar os datos que nos pasan
- ACTION_PICK. selecciona un ítem dun conxunto de datos e devolve o selccionado.
- ACTION_WEB_SEARCH. busca no navegador as palabras indicadas.
- etc.
- Datos (data): os datos sobre os que se vai operar, por exemplo, unha url, os datos dun contacto,a cadea de busca, etc.
- Acción (action): A acción que se desexa levar a cabo. Por exemplo,
- Exemplo:
- ACTION_VIEW content://contacts/people/1 -- Amosa a información sobre a persoa con identificador 1.
Filtros de intencións (Intent Filters)
- Android busca os compoñentes que poden responder a unha Acción nos filtros de intención que se definen no ficheiro AndroidManifest.xml de tódalas aplicacións que están instaladas no dispositivo.
- Cando se constrúe unha activity nunha aplicación, pódese indicar os filtros de intención de manifestan que esa activity pode dar resposta as Accións que lanzan outras aplicacións.
- No noso caso, imos modificar un chisco o código da actividade secundaria para que poida atender a peticións de visionar urls de tipo http.
- Así cando se lance, por exemplo, que se desexa ver http://www.google.es o sistema vai ofrecer 2 opcións: o navegador de internet e a nosa actividade secundaria do proxecto (RecibirDatos).
- Para iso é preciso definir que esa Activity pode atender Accións de visionado de datos tipo http.
- Modificamos o arquivo AndroidManifiest.xml para a segunda activity.
1 <activity android:name=".Intents.UD06_03_A2_Intents"
2 android:label="UD06_03_02_Intents">
3 <intent-filter>
4 <action android:name="android.intent.action.VIEW" />
5 <category android:name="android.intent.category.DEFAULT" />
6 <category android:name="android.intent.category.BROWSABLE" />
7 <data android:scheme="http" />
8 </intent-filter>
9 </activity>
- Liña 4: indica para que tipo de accións esta dispoñible esta activity.
- Liña 5,6: A categoría indica as circunstancias nas que se debe desenvolver a acción.
- Liña 7: o tipo de datos que pode atender esta activity cando haxa unha intención preguntando por recursos http.
XML do Layout principal
1 <?xml version="1.0" encoding="utf-8"?>
2 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 tools:context=".Intents.UD06_03_A1_Intents">
8
9 <Button
10 android:id="@+id/btnAmosarContact_UD06_03_01_Intents"
11 android:layout_width="0dp"
12 android:layout_height="wrap_content"
13 android:layout_marginEnd="8dp"
14 android:layout_marginStart="8dp"
15 android:layout_marginTop="8dp"
16 android:text="Amosar Contacto"
17 app:layout_constraintEnd_toEndOf="parent"
18 app:layout_constraintStart_toStartOf="parent"
19 app:layout_constraintTop_toTopOf="parent" />
20
21 <Button
22 android:id="@+id/btnSelContacts_UD06_03_01_Intents"
23 android:layout_width="0dp"
24 android:layout_height="wrap_content"
25 android:layout_marginEnd="8dp"
26 android:layout_marginStart="8dp"
27 android:layout_marginTop="8dp"
28 android:text="Seleccionar Contacto"
29 app:layout_constraintEnd_toEndOf="parent"
30 app:layout_constraintStart_toStartOf="parent"
31 app:layout_constraintTop_toBottomOf="@+id/btnAmosarContact_UD06_03_01_Intents" />
32
33 <Button
34 android:id="@+id/btnChamar_UD06_03_01_Intents"
35 android:layout_width="0dp"
36 android:layout_height="wrap_content"
37 android:layout_marginEnd="8dp"
38 android:layout_marginStart="8dp"
39 android:layout_marginTop="8dp"
40 android:text="Chamar por teléfono"
41 app:layout_constraintEnd_toEndOf="parent"
42 app:layout_constraintStart_toStartOf="parent"
43 app:layout_constraintTop_toBottomOf="@+id/btnSelContacts_UD06_03_01_Intents" />
44
45 <Button
46 android:id="@+id/btnMarcar_UD06_03_01_Intents"
47 android:layout_width="0dp"
48 android:layout_height="wrap_content"
49 android:layout_marginEnd="8dp"
50 android:layout_marginStart="8dp"
51 android:layout_marginTop="8dp"
52 android:text="Marcar número de teléfono"
53 app:layout_constraintEnd_toEndOf="parent"
54 app:layout_constraintStart_toStartOf="parent"
55 app:layout_constraintTop_toBottomOf="@+id/btnChamar_UD06_03_01_Intents" />
56
57 <Button
58 android:id="@+id/btnAbrirNav_UD06_03_01_Intents"
59 android:layout_width="0dp"
60 android:layout_height="50dp"
61 android:layout_marginEnd="8dp"
62 android:layout_marginStart="8dp"
63 android:layout_marginTop="8dp"
64 android:text="Abrir Navegador"
65 app:layout_constraintEnd_toEndOf="parent"
66 app:layout_constraintHorizontal_bias="0.502"
67 app:layout_constraintStart_toStartOf="parent"
68 app:layout_constraintTop_toBottomOf="@+id/btnMarcar_UD06_03_01_Intents" />
69
70 </android.support.constraint.ConstraintLayout>
Código Java da activity principal
- Neste caso optouse por implemtar a Interface ActionListener na Activity.
1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Intents;
2
3 import android.app.Activity;
4 import android.content.Intent;
5 import android.database.Cursor;
6 import android.net.Uri;
7 import android.os.Bundle;
8 import android.provider.ContactsContract;
9 import android.view.View;
10 import android.widget.Toast;
11
12 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
13
14 public class UD06_03_A1_Intents extends Activity implements View.OnClickListener {
15
16
17 private static final int COD_CONTACTOS = 7;
18
19 @Override
20 protected void onCreate(Bundle savedInstanceState) {
21 super.onCreate(savedInstanceState);
22 setContentView(R.layout.activity_ud06_03_a1__intents);
23
24 xestionarEventos();
25 }
26
27 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
28
29 if (requestCode == COD_CONTACTOS && resultCode == RESULT_OK) {
30 Uri contactoData = data.getData();
31 Cursor cursor = getContentResolver().query(contactoData, null, null, null, null);
32 if (cursor.moveToFirst()) {
33 String nombre = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));
34 Toast.makeText(this, "Contacto: " + nombre, Toast.LENGTH_LONG).show();
35 }
36 }
37
38
39 }
40
41 private void xestionarEventos(){
42 findViewById(R.id.btnSelContacts_UD06_03_01_Intents).setOnClickListener(this);
43 findViewById(R.id.btnAmosarContact_UD06_03_01_Intents).setOnClickListener(this);
44 findViewById(R.id.btnMarcar_UD06_03_01_Intents).setOnClickListener(this);
45 findViewById(R.id.btnChamar_UD06_03_01_Intents).setOnClickListener(this);
46 findViewById(R.id.btnAbrirNav_UD06_03_01_Intents).setOnClickListener(this);
47 }
48
49 @Override
50 public void onClick(View v) {
51 Intent intent = null;
52
53 switch (v.getId()) {
54 case R.id.btnSelContacts_UD06_03_01_Intents:
55 intent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts/people/"));
56 startActivityForResult(intent, COD_CONTACTOS);
57 break;
58 case R.id.btnAmosarContact_UD06_03_01_Intents:
59 intent = new Intent(Intent.ACTION_VIEW, Uri.parse("content://contacts/people/"));
60 startActivity(intent);
61 break;
62 case R.id.btnMarcar_UD06_03_01_Intents:
63 intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:(+34)981445566"));
64 startActivity(intent);
65 break;
66 case R.id.btnChamar_UD06_03_01_Intents:
67 intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:(+34)986112233"));
68 startActivity(intent);
69 break;
70 case R.id.btnAbrirNav_UD06_03_01_Intents:
71 intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.es/"));
72 startActivity(intent);
73 break;
74
75 }
76
77
78
79 }
80 }
- Liña 17: Créase unha nova constante de tipo enteiro cun valor calquera para cando chamemos a activity de contactos para que nos devolva un contacto.
- Liñas 27-39: Revisamos cando se volva dunha actividade secundaria, se é a de Contactos. Nese caso (escápase aos obxectivos desta unidade) créase un cursos para procesar os datos recibidos da activity contactos.
- Liñas 41-47: Rexístrase o evento de Click en todos os botóns.
- Liñas 50-75: Procesado dos distintos botóns, creación dos intents en función do tipo de acción e datos que se desexan procesar.
- Liñas 56: Observar como se chama a activity de contactos para que logo nos devolva o contacto seleccionado.
XML do Layout da Activity Secundaria: UD06_03_A2_Intents
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:tools="http://schemas.android.com/tools"
4 android:layout_width="match_parent"
5 android:layout_height="match_parent"
6 android:orientation="vertical" >
7
8 <TextView
9 android:id="@+id/tvResultado_UD06_03_A2_Intents"
10 android:layout_width="wrap_content"
11 android:layout_height="wrap_content"
12 android:layout_gravity="center_horizontal"
13 android:text="resultado"
14 android:textSize="20sp" />
15
16
17 <Button
18 android:id="@+id/btnPechar_UD06_03_A2_Intents"
19 android:layout_width="wrap_content"
20 android:layout_height="wrap_content"
21 android:layout_gravity="center_horizontal"
22 android:text="Pechar" />
23 </LinearLayout>
O código Java da Activity Secundaria: UD06_03_A2_Intents
1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Intents;
2
3 import android.app.Activity;
4 import android.content.Intent;
5 import android.os.Bundle;
6 import android.view.View;
7 import android.widget.TextView;
8
9 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
10
11 public class UD06_03_A2_Intents extends Activity {
12
13 @Override
14 protected void onCreate(Bundle savedInstanceState) {
15 super.onCreate(savedInstanceState);
16 setContentView(R.layout.activity_ud06_03__a2__intents);
17
18 TextView tvResultado = (TextView) findViewById(R.id.tvResultado_UD06_03_A2_Intents);
19 Intent intent = getIntent();
20 tvResultado.setText("URL: " + intent.getDataString());
21
22 findViewById(R.id.btnPechar_UD06_03_A2_Intents).setOnClickListener(new View.OnClickListener() {
23 @Override
24 public void onClick(View v) {
25 finish();
26 }
27 });
28 }
29 }
- Liñas 18-20: Engadiuse a posibilidade de poder procesar intents cuxo esquema (getSchema) sexa de tipo http. Nese caso simplemente amosamos a URL á que desexaba conectarse o usuario.
Enlace a la página principal de la UD6
Enlace a la página principal del curso
-- Ángel D. Fernández González e Carlos Carrión Álvarez -- (2018).

