Obraz zawierający tekst, Czcionka, Grafika

Opis wygenerowany automatycznie 

Kierunek Informatyka

 

Instrukcja do ćwiczeń laboratoryjnych nr:

4

Nazwa przedmiotu:
Programowanie aplikacji mobilnych

Temat: intencje jawienie zdefiniowane    

Tryb studiów: stacjonarne

Czas trwanie ćw.

2x45 min

Autor materiałów: dr Marcin Skuba

 

1. Treści programowe:

Tworzenie nowych aktywności. Intencje. Przekazywanie wartości przez intencje. Intencje wywołujące aktywności w sposób jawny i niejawny. 

 

2. Cel zajęć:

Celem zajęć jest opanowanie umiejętności uruchamiania nowych aktywności poprzez Intencje oraz przekazywanie danych pomiędzy aktywnościami również przez Intencje.

 

3. Materiały dydaktyczne

 

Intencje są jednym z podstawowych komponentów aplikacji w systemie Android. Intencje odpowiadają przede wszystkim za obsługę rozkazów wydawanych przez użytkownika np.: „zrób zdjęcie”, zadzwoń do …”, „uruchom okno”. Najważniejszym zadaniem Intencji jest uruchamianie odpowiednich Aktywności.

Intencje możemy używać do uruchamiania innych aktywności w sposób jawny oraz niejawny.

W tej instrukcji opisany zostanie jawny sposób wywoływania aktywności. Aktywności wywoływane niejawnie opisane zostaną w następnej instrukcji.

 

ü  Jawne definiowanie Aktywności

Jawne definiowanie aktywności to takie gdzie tworząc nową Intencje podajemy dokładny typ (Klasę) uruchamianej Aktywności. Klasa ta musi znajdować się w tym samym projekcie co aktywność wywołująca. Np.: 

 

Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);

 

Przekazywanie danych między aktywnościami

Możesz przekazywać dane dodając je do intencjci za pomocą metody putExtra():

Wysyłanie danych:

Intent intent = new Intent(MainActivity.this, MainActivity2.class);
// Przekazywanie danych różnych typów
intent.putExtra("KEY_STRING", "Przykładowy tekst");
intent.putExtra("KEY_INT", 123);
intent.putExtra("KEY_BOOLEAN", true);
intent.putExtra("KEY_FLOAT", 3.14f);
intent.putExtra("KEY_LONG", 9876543210L);

// Jeśli masz własny obiekt implementujący Serializable
MyObject myObject = new MyObject("Jan", 25);
intent.putExtra("KEY_OBJECT", myObject);

// Jeśli masz obiekt implementujący Parcelable (np. klasy Androidowe)
MyParcelableObject parcelableObject = new MyParcelableObject("Dane");
intent.putExtra("KEY_PARCELABLE", parcelableObject);

// Uruchomienie drugiej aktywności
startActivity(intent);

Odbieranie danych w drugiej aktywności:

String user = getIntent().getStringExtra("username");

//onCreate
    Intent intent = getIntent();

    String stringValue = intent.getStringExtra("KEY_STRING");
    int intValue = intent.getIntExtra("KEY_INT", 0);
    boolean boolValue = intent.getBooleanExtra("KEY_BOOLEAN", false);
    float floatValue = intent.getFloatExtra("KEY_FLOAT", 0f);
    long longValue = intent.getLongExtra("KEY_LONG", 0L);

    // Dla Serializable
   
MyObject myObject = (MyObject) intent.getSerializableExtra("KEY_OBJECT");

    // Dla Parcelable (opisane poniżej)
   
MyParcelableObject parcelableObject = intent.getParcelableExtra("KEY_PARCELABLE");

-----------------------------------------------------------------------------------------------------------------------

Przykład 1

Aplikacja przekazująca wartość z aktywności pierwszej do drugiej bez odpowiedzi aktywności drugiej.

 

Aktywność pierwsza

 

Obraz zawierający tekst, zrzut ekranu, Czcionka, żółty

Zawartość wygenerowana przez AI może być niepoprawna.

 

activity_main.xml

 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:id="@+id/main"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
   
android:background="@android:color/holo_orange_light"
   
tools:context=".MainActivity">

    <Button
        
android:id="@+id/button"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:text="Prześlij dane do drugiej aktywności"
       
app:layout_constraintBottom_toBottomOf="parent"
       
app:layout_constraintEnd_toEndOf="parent"
       
app:layout_constraintHorizontal_bias="0.498"
       
app:layout_constraintStart_toStartOf="parent"
       
app:layout_constraintTop_toTopOf="parent"
       
app:layout_constraintVertical_bias="0.623" />

    <TextView
        
android:id="@+id/textView"
       
android:layout_width="0dp"
       
android:layout_height="wrap_content"
       
android:text="Aktywnosc pierwsza "
       
android:textAlignment="center"
       
android:textSize="34sp"
       
app:layout_constraintBottom_toTopOf="@+id/editTextText"
       
app:layout_constraintEnd_toEndOf="parent"
       
app:layout_constraintStart_toStartOf="parent"
       
app:layout_constraintTop_toTopOf="parent"
       
app:layout_constraintVertical_bias="0.66" />

    <EditText
        
android:id="@+id/editTextText"
       
android:layout_width="0dp"
       
android:layout_height="wrap_content"
       
android:layout_marginStart="16dp"
       
android:layout_marginEnd="16dp"
       
android:layout_marginBottom="112dp"
       
android:ems="10"
       
android:hint="Wprowadz tekst do wysłania"
       
android:inputType="text"
       
app:layout_constraintBottom_toTopOf="@+id/button"
       
app:layout_constraintEnd_toEndOf="parent"
       
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

MainActivity.java

 

package com.example.dwie_aktywnosci;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;

import com.example.dwie_aktywnosci.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {
   
private  ActivityMainBinding binding;

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
       
binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(
binding.getRoot());

       
binding.button.setOnClickListener(new View.OnClickListener() {
           
@Override
           
public void onClick(View view) {
                String wiadomosc =
binding.editTextText.getText().toString().trim();

               
if (!wiadomosc.isEmpty()) {
                    Intent intent =
new Intent(MainActivity.this, MainActivity2.class);
                    intent.putExtra(
"KEY_WIADOMOSC", wiadomosc);
                    startActivity(intent);
                }
else {
                    Toast.makeText(MainActivity.this,
"Wpisz wiadomość!", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

Aktywność druga

 

Aktywność druga

 

Obraz zawierający tekst, zrzut ekranu, Czcionka

Zawartość wygenerowana przez AI może być niepoprawna.

 

activity_main2.xml

 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:id="@+id/main"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
   
android:background="@color/design_default_color_secondary"
   
tools:context=".MainActivity2">

    <Button
       
android:id="@+id/button"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:text="Zwróć dane do pierszej aktywności"
       
app:layout_constraintBottom_toBottomOf="parent"
       
app:layout_constraintEnd_toEndOf="parent"
       
app:layout_constraintHorizontal_bias="0.498"
       
app:layout_constraintStart_toStartOf="parent"
       
app:layout_constraintTop_toTopOf="parent"
       
app:layout_constraintVertical_bias="0.623" />

    <TextView
       
android:id="@+id/textView"
       
android:layout_width="0dp"
       
android:layout_height="wrap_content"
       
android:text="Aktywnosc druga"
       
android:textAlignment="center"
       
android:textSize="34sp"
       
app:layout_constraintBottom_toTopOf="@+id/editTextText"
       
app:layout_constraintEnd_toEndOf="parent"
       
app:layout_constraintStart_toStartOf="parent"
       
app:layout_constraintTop_toTopOf="parent"
       
app:layout_constraintVertical_bias="0.66" />

    <EditText
       
android:id="@+id/editTextText"
       
android:layout_width="0dp"
       
android:layout_height="wrap_content"
       
android:layout_marginStart="16dp"
       
android:layout_marginEnd="16dp"
       
android:layout_marginBottom="112dp"
       
android:ems="10"
       
android:hint="Wprowadz tekst do wysłania"
       
android:inputType="text"
       
app:layout_constraintBottom_toTopOf="@+id/button"
       
app:layout_constraintEnd_toEndOf="parent"
       
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

 

MainActivity2.java

 

package com.example.dwie_aktywnosci;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import com.example.dwie_aktywnosci.databinding.ActivityMain2Binding;

public class MainActivity2 extends AppCompatActivity {
   
private ActivityMain2Binding binding;
   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
       
binding= ActivityMain2Binding.inflate(getLayoutInflater());
        setContentView(
binding.getRoot());

       
//odbieranie danych z pierwszej aktywności
       
Intent intent = getIntent();

       
// Sprawdzenie, czy intent nie jest null i czy zawiera dane
       
if (intent != null && intent.hasExtra("KEY_WIADOMOSC")) {
            String wiadomosc = intent.getStringExtra(
"KEY_WIADOMOSC");

           
// Dodatkowe sprawdzenie na null
           
if (wiadomosc != null) {
               
binding.editTextText.setText(wiadomosc);
            }
else {
               
binding.editTextText.setText(""); // lub inny tekst domyślny
           
}
        }

       
binding.button.setOnClickListener(new View.OnClickListener() {
           
@Override
           
public void onClick(View view) {
                finish();
            }
        });
    }
}

 

 

-----------------------------------------------------------------------------------------------------------------------

Przykład 2

Aplikacja przekazująca wartość z aktywności pierwszej do drugiej oraz zwracanie wartości z drugiej do pierwszej przy pomocy intencji

 

MainActivity.java

 

package com.example.dwie_aktywnosci;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import androidx.activity.EdgeToEdge;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import com.example.dwie_aktywnosci.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {
   
private  ActivityMainBinding binding;

   
// Rejestrujemy launcher do odbioru wyniku z innej aktywności


   
private final ActivityResultLauncher<Intent> getResult =
            registerForActivityResult(
                   
new ActivityResultContracts.StartActivityForResult(),
                   
new ActivityResultCallback<ActivityResult>() {
                       
                       
@Override
                       
public void onActivityResult(ActivityResult result) {
                           
if (result.getResultCode() == Activity.RESULT_OK) {
                                Intent data = result.getData();
                               
if (data != null) {
                                    String returnedText = data.getStringExtra(
"RESULT_KEY");
                                    binding.editTextText.setText(returnedText);
                                }
                            }
                        }
                    });

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
       
binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(
binding.getRoot());

       
binding.button.setOnClickListener(v -> {
            String text =
binding.editTextText.getText().toString();

            Intent intent =
new Intent(MainActivity.this, MainActivity2.class);
            intent.putExtra(
"KEY_DANE", text);
           
getResult.launch(intent); // Jawne uruchomienie drugiej aktywności
       
});
    }
}

 

 

MainActivity2.java

 

package com.example.dwie_aktywnosci;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import com.example.dwie_aktywnosci.databinding.ActivityMain2Binding;

public class MainActivity2 extends AppCompatActivity {
   
private ActivityMain2Binding binding;
   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
       
binding= ActivityMain2Binding.inflate(getLayoutInflater());
        setContentView(
binding.getRoot());

       
//odbieranie danych z pierwszej aktywności
       
Intent intent= getIntent();
        String dane = intent.getStringExtra(
"KEY_DANE");
       
binding.editTextText.setText(dane);
       
       
binding.button.setOnClickListener(new View.OnClickListener() {
           
@Override
           
public void onClick(View view) {
                String odpowiedz =
binding.editTextText.getText().toString();

                Intent resultIntent =
new Intent();
                //Wstawianie wartości do intencji wyniku
               
resultIntent.putExtra("RESULT_KEY", odpowiedz);

               
// Ustaw wynik i zakończ aktywność
               
setResult(Activity.RESULT_OK, resultIntent);
                finish();
            }
        });
    }
}

 

 

-----------------------------------------------------------------------------------------------------------------------

ü Interfejs Parcelable

 

W Androidzie Parcelable to interfejs, który pozwala na szybkie i efektywne przesyłanie obiektów między komponentami aplikacji (np. między Activity lub Fragment) za pomocą Intentów lub Bundle.

 

·       Obiekt implementujący Parcelable może być „spakowany” w Intencję i wysłany do innej aktywności.

·       Android zamienia obiekt na specjalny strumień bajtów i odtwarza go w miejscu docelowym.

·       Jest szybszy niż Serializable, dlatego jest rekomendowany w Androidzie.

 

Przykład wykorzystania interfejsu Parcelable do przesyłania danych w aktywnościach.

 

package com.example.dwie_aktywnosci;

import android.os.Parcel;
import android.os.Parcelable;

// Klasa Osoba implementująca Parcelable – pozwala przesyłać obiekty między Activity lub Fragment
public class Osoba implements Parcelable {
   
private String imie;  // Pole przechowujące imię osoby
   
private int wiek;     // Pole przechowujące wiek osoby

    // Konstruktor główny – używany do tworzenia nowego obiektu klasy Osoba
   
public Osoba(String imie, int wiek) {
       
this.imie = imie;
       
this.wiek = wiek;
    }

   
// Konstruktor odczytujący dane z Parcel
    // Android używa go przy odtwarzaniu obiektu z Intencji lub Bundle
   
protected Osoba(Parcel in) {
       
// Kolejność odczytu musi odpowiadać kolejności zapisu w writeToParcel()
       
imie = in.readString();
       
wiek = in.readInt();
    }

   
// Metoda writeToParcel – pakowanie danych obiektu do Parcel
    // Parcel to strumień bajtów używany do przesyłania danych między komponentami
   
@Override
   
public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(
imie); // zapis imienia
       
dest.writeInt(wiek);    // zapis wieku
   
}

   
// Metoda describeContents
    // Zwykle zwraca 0, chyba że obiekt zawiera FileDescriptor (rzadko używane)
   
@Override
   
public int describeContents() {
       
return 0;
    }

   
// CREATOR – wymagany przez Androida do odtworzenia obiektu z Parcel
    // Tworzy nowy obiekt Osoba z Parcel oraz tablice obiektów
   
public static final Creator<Osoba> CREATOR = new Creator<Osoba>() {
        @Override
        public Osoba createFromParcel(Parcel in) {
            // Wywołuje konstruktor odczytujący z Parcel
            return new Osoba(in);
        }

        @Override
        public Osoba[] newArray(int size) {
            // Tworzy tablicę obiektów Osoba
            return new Osoba[size];

        }
    };

   
// Gettery – umożliwiają odczyt danych z obiektu
   
public String getImie() { return imie; }
   
public int getWiek() { return wiek; }
}

 

Wysyłanie danych w pierwszej aktywności:

Osoba osoba = new Osoba("Jan", 25);
Intent intent = new Intent(MainActivity.this, MainActivity2.class);
intent.putExtra("KEY_OSOBA", osoba);
startActivity(intent);

 

Odbieranie obiektu klasy Osoba w drugiej aktywności:

//odbieranie danych z pierwszej aktywności
Intent intent = getIntent();
Osoba osoba = intent.getParcelableExtra("KEY_OSOBA");
String imie = osoba.getImie();
int wiek = osoba.getWiek();

 

Wysyłanie dużej ilości obiektów

// Tworzymy dużą listę obiektów Osoba
ArrayList<Osoba> listaOsob = new ArrayList<>();
for (int i = 1; i <= 100; i++) {
    listaOsob.add(new Osoba("Osoba " + i, 20 + i));
}
// Tworzymy Intent do drugiej aktywności
Intent intent = new Intent(MainActivity.this, MainActivity2.class);

// Przekazujemy listę Osób jako ParcelableArrayList
intent.putParcelableArrayListExtra("KEY_LISTA_OSOB", listaOsob);

startActivity(intent);

 

Odbieranie dużej ilości obiektów:

Intent intent = getIntent();
ArrayList<Osoba> listaOsob = intent.getParcelableArrayListExtra("KEY_LISTA_OSOB");

if (listaOsob != null && !listaOsob.isEmpty()) {
    StringBuilder builder = new StringBuilder();
    for (Osoba o : listaOsob) {
        builder.append(o.getImie()).append(" - ").append(o.getWiek()).append("\n");
    }
    binding.textView.setText(builder.toString());
} else {
    binding.textView.setText("Brak danych do wyświetlenia");
}

 

putParcelableArrayListExtra jest specjalnie przystosowane do przesyłania list Parcelable.

 

Dla bardzo dużych danych (setki lub tysiące obiektów) lepiej rozważyć:

Dzięki Parcelable przesyłanie 100-200 obiektów działa płynnie, jest znacznie szybsze niż Serializable.

 

ü  StringBuilder

 

StringBuilder w Javie to klasa służąca do efektywnego tworzenia i modyfikowania łańcuchów tekstowych.

·       Pozwala dodawać (append), wstawiać (insert), usuwać (delete) lub zamieniać (replace) tekst w jednym obiekcie.

·       Szybszy niż konkatenacja Stringów (+) w pętli, bo String w Javie jest niezmienny (immutable).

·       Po zakończeniu modyfikacji można zamienić na zwykły String:

 

String wynik = stringBuilder.toString();

 

Przykład użycia:

StringBuilder builder = new StringBuilder();
builder.append("Jan");
builder.append(" ");
builder.append("Kowalski");
builder.append(" ma ");
builder.append(25);
builder.append(" lat.");

    String wynik = builder.toString();
System.out.println(wynik); // Jan Kowalski ma 25 lat.

 

4. Zadania

 

Zadanie 1.

Napisz aplikację wg własnego pomysłu składającą się z trzech aktywności.

·        Pierwsza powinna umożliwić uruchomienie drugiej przekazując jej cztery wartości różnego typu pobrane z komponentów takich jak EditText, CheckBox oraz RadioButton.

·        W pierwszej aktywności powinna znaleźć się również metoda uruchamiająca aktywność trzecią.

                   Aplikacja powinna umożliwić przesyłanie co najmniej jednej wartości z pierwszej aktywności do trzeciej oraz kilka z trzeciej do pierwszej.

Przekazane wartości przedstaw w kontrolkach aktualnych aktywności.

 

Zadanie 2.

Napisz aplikację przekazująca dane z pierwszej aktywności do drugiej. Dane powinny być reprezentowane przez klasę Punkt, w której występują takie składowe jak zmienna x, y (int) oraz kolor (int), metodę zwracającą ciąg znaków w postaci np. „x=100 y=200 kolor=112233”. Utwórz 100 obiektów w aktywności pierwszej oraz prześlij ją do aktywności drugiej. Wynik wyświetl w polu tekstowych TextView.