Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion receiver/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Activities" />
android:theme="@style/Theme.Activities" >

<activity
android:name=".ReceiverActivity"
android:exported="true">

<!-- Intent-filter для приёма ACTION_SEND text/plain -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>

</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,44 @@ package otus.gpb.homework.activities.receiver

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.graphics.drawable.Drawable
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources

class ReceiverActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_receiver)

val titleTextView = findViewById<TextView>(R.id.titleTextView)
val yearTextView = findViewById<TextView>(R.id.yearTextView)
val descriptionTextView = findViewById<TextView>(R.id.descriptionTextView)
val posterImageView = findViewById<ImageView>(R.id.posterImageView)

// Достаём extras из Intent
val title = intent.getStringExtra("title") ?: ""
val year = intent.getStringExtra("year") ?: ""
val description = intent.getStringExtra("description") ?: ""

// Заполняем текстовые поля
titleTextView.text = title
yearTextView.text = year
descriptionTextView.text = description

// - В зависимости от названия фильма отобразите картинку которая лежит в ресурсах(*res/drawable*) в `posterImageView`
val posterResId = when (title) {
"Славные парни" -> R.drawable.niceguys
"Интерстеллар" -> R.drawable.interstellar
else -> android.R.drawable.ic_menu_gallery // заглушка
}
// можно так, работает на всех версиях
// posterImageView.setImageResource(posterResId)
// делаем так по условию (с импортом Drawable):
val drawable = AppCompatResources.getDrawable(this, posterResId)
// Передаём Drawable в ImageView
drawable?.let { posterImageView.setImageDrawable(it) }

}
}
21 changes: 18 additions & 3 deletions sender/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="otus.gpb.homework.activities.sender"> <!-- package обязательно должен совпадать с namespace из build.gradle (otus.gpb.homework.activities.sender). Без него система не найдёт класс .SenderActivity -->
<uses-feature
android:name="android.hardware.location.gps"
android:required="false"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<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/Theme.Activities" />
android:theme="@style/Theme.Activities" >
<!-- Без этой части <intent-filter>: Без блока с MAIN и LAUNCHER Android Studio не поймёт, что эту Activity нужно запускать первой -->
<activity
android:name=".SenderActivity"
android:exported="true"> <!-- Для главной Activity это обязательно (иначе будет ошибка при запуске) -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package otus.gpb.homework.activities.sender

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.widget.Button
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat

//import otus.gpb.homework.activities.sender.databinding.ActivitySenderBinding

class SenderActivity : AppCompatActivity() {
// Координаты по умолчанию (центр Москвы), если GPS не отдаст ничего
private var geoLatitude = 55.7558
private var geoLongitude = 37.6176
private val intentGM = Intent(Intent.ACTION_VIEW, Uri.parse("geo:$geoLatitude,$geoLongitude?q=Рестораны"))
private val geoPermisson = registerForActivityResult(ActivityResultContracts.RequestPermission()) {
isGranted ->
if (isGranted) {
Toast.makeText(
this,
"Получено разрешение на геолокацию",
Toast.LENGTH_LONG
).show()
// TODO geo из телефона
startActivity(intentGM)
} else {
Toast.makeText(
this,
"Для работы карт нужно разрешение на геолокацию",
Toast.LENGTH_LONG
).show()
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sender)

// Находим кнопки
val buttonGM = findViewById<Button>(R.id.buttonGM)
val buttonSE = findViewById<Button>(R.id.buttonSE)
val buttonOR = findViewById<Button>(R.id.buttonOR)

// --- Обработчик для Google Maps ---
buttonGM.setOnClickListener {
// проверим права
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
// openMapsWithLastLocation()
Toast.makeText(
this,
"Права на geo есть",
Toast.LENGTH_LONG
).show()
// TODO geo из телефона
startActivity(intentGM)
} else {
Toast.makeText(
this,
"Необходимы разрешения на геолокацию",
Toast.LENGTH_LONG
).show()
geoPermisson.launch(Manifest.permission.ACCESS_FINE_LOCATION)
}
}

// --- Обработчик для Send Email (РЕАЛИЗАЦИЯ) ---
buttonSE.setOnClickListener {
val email = "android@otus.ru"
// val ccEmail = "fortoke@jenv.ru"
val subject = "Test homework"
val body = "This homework complete"

val intent = Intent(Intent.ACTION_SEND)
intent.type = "message/rfc822" // MIME-тип для email, чтобы отфильтровать только почтовые клиенты

intent.putExtra(Intent.EXTRA_EMAIL, arrayOf(email))
// intent.putExtra(Intent.EXTRA_CC, arrayOf(ccEmail))
intent.putExtra(Intent.EXTRA_SUBJECT, subject)
intent.putExtra(Intent.EXTRA_TEXT, body)

// Проверка: есть ли приложение, которое может обработать этот Intent
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent)
} else {
// Если почтовых клиентов нет надо бы сообщить
Toast.makeText(
this,
"На устройстве не найдено приложение для отправки почты",
Toast.LENGTH_LONG
).show()
}
}

// --- Обработчик для Open Receiver ---

buttonOR.setOnClickListener {
val movies = listOf(
mapOf(
"title" to "Славные парни",
"year" to "2016",
"description" to "Что бывает, когда напарником брутального костолома становится субтильный лопух? " +
"Наемный охранник Джексон Хили и частный детектив Холланд Марч вынуждены работать в паре, " +
"чтобы распутать плевое дело о пропавшей девушке, которое оборачивается преступлением века."
),
mapOf(
"title" to "Интерстеллар",
"year" to "2014",
"description" to "Когда засуха, пыльные бури и вымирание растений приводят человечество к продовольственному кризису, " +
"коллектив исследователей и учёных отправляется сквозь червоточину, чтобы найти планету " +
"с подходящими для человечества условиями."
)
)

// Выбираем случайный фильм
var selectedMovie = movies.random()
Toast.makeText(this, "{$selectedMovie[\"title\"]}", Toast.LENGTH_SHORT).show()
val intent = Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
addCategory(Intent.CATEGORY_DEFAULT)
putExtra("title", selectedMovie["title"])
putExtra("year", selectedMovie["year"])
putExtra("description", selectedMovie["description"])
}

startActivity(intent)

}
}

}
55 changes: 55 additions & 0 deletions sender/src/main/res/layout/activity_sender.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SenderActivity">
<!--
В app:layout_constraintVertical_bias не нужно писать проценты. Этот атрибут принимает дробное число от 0 до 1, где:
0 — элемент прижат к верхнему ограничению (началу),
1 — к нижнему (концу),
0.5 — ровно по центру (это значение по умолчанию).
Проценты Значение для bias
0% 0.0
25% 0.25
50% 0.5
75% 0.75
100% 1.0
-->
<Button
android:id="@+id/buttonGM"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="To Google Maps"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.25" />

<Button
android:id="@+id/buttonSE"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send Email"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.5" />

<Button
android:id="@+id/buttonOR"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Open Receiver"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.75" />
</androidx.constraintlayout.widget.ConstraintLayout>