IMPORTANT: Per accedir als fitxer de subversion: http://acacha.org/svn (sense password). Poc a poc s'aniran migrant els enllaços. Encara però funciona el subversion de la farga però no se sap fins quan... (usuari: prova i la paraula de pas 123456)

Primera pregunta

Expliqueu els cicle de vida d'una activitat Android basant-vos en una gràfica. Expliqueu amb les vostres paraules els estats i les transicions del cicle de vida d'una activitat. Poseu exemples d'aplicacions en cada estat.

Jordiromeroactivity01.png

Una activitat d'Android es pot dividir en quatre grans estats:

  • Activa (Running): L'activitat està damunt de la pila.
  • Visible (Paused): L'activitat es visible però no té el focus.
  • Parada (Stopped): Quan l'activitat no es visible.
  • Destruïda (Destroyed): Quan l'activitat acaba.

El cicle de vida sencera d'una activitat va des de la primera crida a onCreate() fins que finalment acaba al onDestroy().

Els diferents mètodes que capturaran els diferents events d'una aplicació Android són els següents:

  • onCreate(): Es realitza la crida a l'activitat.
  • onStart(): L'activitat està a punt de ser mostrada al usuari.
  • onResume(): Es crida quan l'activitat començar a interaccionar amb l'usuari.
  • onPause(): Indica que la activitat està a punt d'entrar en segon pla, normalament es tracta que aplicació passa a segon pla per que una altra aplicació passar a primer pla, convé guardar l'estat de l'aplicació.
  • onStop(): L'aplicació ja no serà visible per a l'usuari.
  • onRestart(): L'activitat tornarà a ser presentada després de passar per un onStop().
  • onDestroy(): És crida abans que una aplicació sigui totalment destruïda.

Segona pregunta

Expliqueu a partir d'una gràfica i amb les vostres paraules l'arquitectura del sistema operatiu Android. Detalleu les capes i les seves funcionalitats.

Jordiromeroandroid01.png


  • Kernel linux: El nucli del sistema operatiu Android està basat en el nucli de Linux però adaptat a les característiques del maquinari en el qual s'executarà Android.
  • Llibreries: La següent capa que se situa just sobre el nucli la componen les biblioteques natives d'Android, també anomenades llibreries. Aquestes normalment estan fetes pel fabricant, qui també s'encarrega d'instal·lar-les al dispositiu abans de posar-lo a la venda. Entre les llibreries incloses habitualment trobem OpenGL (motor gràfic), Biblioteques multimèdia (formats d'àudio, imatge i vídeo), Webkit (navegador).
  • Entorn d'execució: L'entorn d'execució d'Android no es considera una capa en si mateix, atès que també està format per llibreries. Aquí trobem les llibreries amb la funcionalitats habituals de Java així com altres específiques d'Android. El component principal de l'entorn d'execució d'Android és la màquina virtual Dalvik. Les aplicacions es codifiquen en Java i són compilades en un format específic perquè aquesta màquina virtual les executi.
  • Framework d'aplicacions: La següent capa està formada per totes les classes i serveis que utilitzen directament les aplicacions per realitzar les seves funcions.
  • Aplicacions. En l'última capa s'inclouen totes les aplicacions del dispositiu, tant les que tenen interfície d'usuari com les que no, les que vénen preinstal·lades al dispositiu i aquelles que l'usuari ha instal·lat. En aquesta capa hi trobem també l'aplicació principal del sistema: Inici (Home) o llançador (launcher).

Tercera pregunta

Indiqueu i expliqueu amb detall el codi bàsic d'una activitat tipus hola mon que carregui un recurs layout bàsic.

Mostrem el fitxer MainActivity.java, en una aplicació com el helloworld, es crida a l'activitat onCreate(), que a través del setContentView el que fa és carregar el recurs de layout, que en una aplicació simple com pot ser el helloworld correspon a l'activity_main.xml.

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}

Una altra part d'una aplicació simple és el fitxer de layout, on decirem el tipus de presentació que li volem donar a la aplicació i com és col·locarà això o decidirem amb el tipus de layout que voldrem utilitzar en el cas d'aquesta aplicació a través d'un RelativeLayout. També introduirem una TextView que ens mostrarà a l'usuari un text, en aquest cas u helloworld, també definirem dins del TextView la posició que ocuparà dins del layout.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</RelativeLayout>

Totes les aplicacions Android han de tenir un arxiu AndroidManifest.xml, té la informació essencial sobre l'aplicació Android, quina és la versió mínima d'Android sobre la que correrà l'aplicació, quina és la versió per defecte, així com el número d'activitats que té la nostra aplicació.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.iesebre.helloworld"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.iesebre.helloworld.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Exercici pràctic

Poseu aquí un enllaç a l'aplicació bàsica amb Action bar i pestanyes que heu fet a classe.

Entregueu:

  • Documentació: el codi ha d'estar explicat
  • El codi en format wiki

Carreguem el fitxer MainActivity.java.

import java.util.Locale;

import android.app.ActionBar;
import android.app.ActionBar.TabListener;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.NavUtils;
import android.support.v4.view.ViewPager;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class MainActivity extends FragmentActivity implements TabListener {

	/**
	 * The {@link android.support.v4.view.PagerAdapter} that will provide
	 * fragments for each of the sections. We use a
	 * {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
	 * will keep every loaded fragment in memory. If this becomes too memory
	 * intensive, it may be best to switch to a
	 * {@link android.support.v4.app.FragmentStatePagerAdapter}.
	 */
	SectionsPagerAdapter mSectionsPagerAdapter;

	/**
	 * The {@link ViewPager} that will host the section contents.
	 */
	ViewPager mViewPager;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// Set up the action bar.
		final ActionBar actionBar = getActionBar();
		actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

		// Create the adapter that will return a fragment for each of the three
		// primary sections of the app.
		mSectionsPagerAdapter = new SectionsPagerAdapter(
				getSupportFragmentManager());

		// Set up the ViewPager with the sections adapter.
		mViewPager = (ViewPager) findViewById(R.id.pager);
		mViewPager.setAdapter(mSectionsPagerAdapter);

		// When swiping between different sections, select the corresponding
		// tab. We can also use ActionBar.Tab#select() to do this if we have
		// a reference to the Tab.
		mViewPager
				.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
					@Override
					public void onPageSelected(int position) {
						actionBar.setSelectedNavigationItem(position);
					}
				});

		// For each of the sections in the app, add a tab to the action bar.
		for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
			// Create a tab with text corresponding to the page title defined by
			// the adapter. Also specify this Activity object, which implements
			// the TabListener interface, as the callback (listener) for when
			// this tab is selected.
			actionBar.addTab(actionBar.newTab()
					.setText(mSectionsPagerAdapter.getPageTitle(i))
					.setTabListener(this));
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	

	@Override
	public void onTabSelected(ActionBar.Tab tab,
			FragmentTransaction fragmentTransaction) {
		// When the given tab is selected, switch to the corresponding page in
		// the ViewPager.
		mViewPager.setCurrentItem(tab.getPosition());
	}

	@Override
	public void onTabUnselected(ActionBar.Tab tab,
			FragmentTransaction fragmentTransaction) {
	}

	@Override
	public void onTabReselected(ActionBar.Tab tab,
			FragmentTransaction fragmentTransaction) {
	}

	/**
	 * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
	 * one of the sections/tabs/pages.
	 */
	public class SectionsPagerAdapter extends FragmentPagerAdapter {

		public SectionsPagerAdapter(FragmentManager fm) {
			super(fm);
		}

		@Override
		public Fragment getItem(int position) {
			// getItem is called to instantiate the fragment for the given page.
			// Return a DummySectionFragment (defined as a static inner class
			// below) with the page number as its lone argument.
			
			/* Carreguem tres fragments un per a cada pestanya creada*/
			Fragment fragment = new DummySectionFragment();
			Fragment fragment2 = new DummySectionFragment2();
			Fragment fragment3 = new DummySectionFragment3();
			
			Bundle args = new Bundle();
			args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 0);
			args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
			args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 2);
			fragment.setArguments(args);
			fragment2.setArguments(args);
			fragment3.setArguments(args);
			
			switch (position) {
			case 0:
				return fragment;
			case 1:
				return fragment2;
			case 2:
				return fragment3;
			
			}
			return null;

		}

		@Override
		public int getCount() {
			// Show 3 total pages.
			return 3;
		}

		@Override
		public CharSequence getPageTitle(int position) {
			Locale l = Locale.getDefault();
			switch (position) {
			case 0:
				return getString(R.string.title_section1).toUpperCase(l);
			case 1:
				return getString(R.string.title_section2).toUpperCase(l);
			case 2:
				return getString(R.string.title_section3).toUpperCase(l);
			}
			return null;
		}
	}

	/**
	 * A dummy fragment representing a section of the app, but that simply
	 * displays dummy text.
	 */
	public static class DummySectionFragment extends Fragment {
		/**
		 * The fragment argument representing the section number for this
		 * fragment.
		 */
		public static final String ARG_SECTION_NUMBER = "section_number";

		public DummySectionFragment() {
		}
        /*Carreguem la vista que mostra el petit formulari que em creat*/
		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			View rootView = inflater.inflate(R.layout.formulari,
					container, false);
			
			return rootView;
		}
	}
	
	public static class DummySectionFragment2 extends Fragment {
		/**
		 * The fragment argument representing the section number for this
		 * fragment.
		 */
		public static final String ARG_SECTION_NUMBER = "section_number";

		public DummySectionFragment2() {
		}

		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			View rootView2 = inflater.inflate(R.layout.fragment_main_dummy,
					container, false);
			TextView dummyTextView = (TextView) rootView2
					.findViewById(R.id.section_label);
			dummyTextView.setText(Integer.toString(getArguments().getInt(
					ARG_SECTION_NUMBER)));
			return rootView2;
		}
	}
	public static class DummySectionFragment3 extends Fragment {
		/**
		 * The fragment argument representing the section number for this
		 * fragment.
		 */
		public static final String ARG_SECTION_NUMBER = "section_number";

		public DummySectionFragment3() {
		}

		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			View rootView3 = inflater.inflate(R.layout.fragment_main_dummy,
					container, false);
			TextView dummyTextView = (TextView) rootView3
					.findViewById(R.id.section_label);
			dummyTextView.setText(Integer.toString(getArguments().getInt(
					ARG_SECTION_NUMBER)));
			return rootView3;
		}
	}

}

Mostrem el fitxer activity_main.xml.

<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" />

El fitxer fragment_main_dumy.xml.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity$DummySectionFragment" >

    <TextView
        android:id="@+id/section_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

El fitxer del formulari en xml.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/nom" />

      <EditText
        android:id="@+id/editText1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10" > 

        <requestFocus />
    </EditText> 

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/cognom" />

      <EditText
        android:id="@+id/editText2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10" /> 

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/password" />

    <EditText
        android:id="@+id/editText3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPassword" />

    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/repassword" />

    <EditText
        android:id="@+id/editText4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPassword" />

    <Switch
        android:id="@+id/switch1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/Switch" />

    <RadioGroup
        android:id="@+id/radioGroup1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >

        <RadioButton
            android:id="@+id/radio0"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:checked="true"
            android:text="@string/gat" />

        <RadioButton
            android:id="@+id/radio1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/gos" />

        <RadioButton
            android:id="@+id/radio2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/reptil" />
    </RadioGroup>

    <Spinner
        android:id="@+id/spinner1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <CheckBox
        android:id="@+id/checkBox1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/accepta" />

</LinearLayout>

El fitxer de android_manifest.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.iesebre.actionbarpestanyes"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="18" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.iesebre.actionbarpestanyes.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
  • L'Enllaç al codi a github

https://github.com/jordiromero/actionbar.git

  • El apk android instalable

Fitxer:Jordiromeroactionabar.zip