Уважаемые пользователи Голос!
Сайт доступен в режиме «чтение» до сентября 2020 года. Операции с токенами Golos, Cyber можно проводить, используя альтернативные клиенты или через эксплорер Cyberway. Подробности здесь: https://golos.io/@goloscore/operacii-s-tokenami-golos-cyber-1594822432061
С уважением, команда “Голос”
GOLOS
RU
EN
UA
vp-webdev
6 лет назад

Пишем программу для Android, рассказывающую анекдоты

В этой статье я расскажу как написал приложение для Android, которое рассказывает вслух анекдоты, используя синтезированный голос от Google.

Примечание редактора

Дорогие подписчики, представляю вам очередной материал автора @pythono. В этой статье автор не только расскажет вам о своей работе, но и продемонстрирует приложение, загруженное в Google Play. Это реально круто!


Приложение удобно тем, что можно слушать анекдоты в наушниках, не глядя в экран, например во время ходьбы, или каких-то повседневных дел, вроде приготовления пищи, или поездки в общественном транспорте.

На момент написания статьи, программа выложена и одобрена в Google Play.

Скачать программу с Google Play

https://play.google.com/store/apps/details?id=ru.pythono.funspeak

Для работы программы также требуется установить синтезатор речи от Google и включить синтез речи в настройках вашего Android устройства.

Интерфейс программы очень прост и состоит из двух больших кнопок - "Расскажи анекдот" и "Остановить синтез речи".



Когда мы нажимаем на кнопку "Рассказать анекдот", программа дает запрос к PHP скрипту на моём сайте, в ответ скрипт высылает ей случайный анекдот, спарсенный из интернета. Программа принимает текст анекдота и читает его вслух с помощью синтезатора речи. Можно было реализовать парсинг анекдота прямо на устройстве Android, но это оказалось медленнее, чем парсинг PHP скриптом, поэтому я выбрал именно скриптовый вариант решения проблемы.

Листинг PHP скрипта fun.php:

<?
include 'phpQuery.php'; // Подключаем phpQuery

// Функция получения текста страницы для phpQuery
function getpage($url)
{
    $curl = curl_init($url); // Инициализируем curl по указанному адресу
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // Записать http ответ в переменную, а не выводить в буфер
    curl_setopt ($curl, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt ($curl, CURLOPT_SSL_VERIFYHOST, 0); // Этот параметр нужен для работы HTTPS
    $page = curl_exec($curl); // Получаем в переменную $page HTML код страницы
    $document = phpQuery::newDocument($page); // Загружаем полученную страницу в phpQuery
    return $document;
};

$elements = getpage('http://anekdotme.ru/random')->find('.anekdot_text'); // Делаем выборку по классу
foreach ($elements as $el) {
    $elem_pq = pq($el); // pq - аналог $ в jQuery
    $otvet = trim($elem_pq->text()); // Получим текст анекдота
};

echo($otvet);   // Выдаем ответ сервера


Для парсинга в PHP скрипте используется curl и библиотека phpQuery

Если мы обратимся к данному скрипту по адресу http://pythono.ru/alina/fun.php, он выдаст нам случайный анекдот.

Задача нашей программы - получить анекдот от скрипта при нажатии на кнопку, и произнести его вслух.

Интерфейс программы - это две кнопки ImageButton, которые расположены одна над другой. При включении программы на первой кнопке отображается картинка "Загрузка".






Когда программа инициализирует синтезатор речи и будет готова произносить фразы вслух, картинка на первой кнопке сменяется на "Расскажи анекдот".



Листинг интерфейса activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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="fill_parent"
    android:layout_gravity="center_vertical"
    android:orientation="vertical"
    tools:context="ru.pythono.funspeak.MainActivity">

<RelativeLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:layout_gravity="center_vertical"
    >
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:orientation="vertical">

        <ImageButton
            android:id="@+id/fun"
            android:layout_width="300px"
            android:layout_height="300px"
            android:layout_marginTop="10dp"
            android:scaleType="fitCenter"
            android:src="@drawable/loading" />

        <ImageButton
            android:id="@+id/stopbutton"
            android:layout_width="300px"
            android:layout_height="300px"
            android:layout_marginTop="10dp"
            android:scaleType="fitCenter"
            android:src="@drawable/mute" />
    </LinearLayout>
</RelativeLayout>
</FrameLayout>



В AndroidManifest.xml пропишем разрешения на подключение к интернету и запрет поворота в альбомный режим:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="ru.pythono.funspeak">
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="Анекдоты вслух"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            android:configChanges="orientation|screenSize"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>


Java код программы для получения анекдота использует библиотек jsoup, хотя при желании, можно было обойтись без неё. Но так как я изначально хотел парсить анекдоты на стороне клиента, то эту библиотеку я использовал для получения анекдота от PHP скрипта, просто указав в качестве цели для парсинга знак звездочки.

Листинг Java кода MainActivity.java:

package ru.pythono.funspeak;
import java.util.Locale;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.app.Activity;
import android.speech.tts.TextToSpeech;
import android.view.View;
import android.os.AsyncTask;
import android.widget.ImageButton;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import android.widget.ArrayAdapter;

public class MainActivity extends Activity implements TextToSpeech.OnInitListener  {

    protected static final int RESULT_SPEECH = 1;
    private ImageButton fun; // кнопка Анекдот
    private ImageButton stopbutton; // кнопка Тихо!
    private TextToSpeech mTTS; // Объект синтезатора речи
    public final static String EXTRA_MESSAGE = "EXTRA_MESSAGE";
    public Elements anekdot;
    public String otvet="Сервер не отвечает"; // Фраза, в случае ошибок сервера
    private ArrayAdapter<String> adapter;
    public Integer stopflag=0;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTTS = new TextToSpeech(this, this);
        stopbutton = (ImageButton) findViewById(R.id.stopbutton);
        fun = (ImageButton) findViewById(R.id.fun);
        fun.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                fun.setImageResource(R.drawable.loading);
                stopflag=1;
                mTTS.stop();
                new Serverzapros().execute();
            }
        });
        
        // Ловим нажатие кнопки Тихо!
        stopbutton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopflag=1;
                mTTS.stop();
            }
        });
    }

    // Устанавливаем русский язык для синтеза речи
    @Override
    public void onInit(int status) {
        if (status == TextToSpeech.SUCCESS) {
            Locale locale = new Locale("ru");
            int result = mTTS.setLanguage(locale);
        }
        fun.setImageResource(R.drawable.anekdot);
    }

    // При выключении программы выключаем синтезатор речи
    @Override
    public void onDestroy() {
        if (mTTS != null) {
            mTTS.stop();
            mTTS.shutdown();
        }
        super.onDestroy();
    }

    // Даём запрос к серверу на PHP чтобы получить очередной анекдот
    public class Serverzapros extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... arg) {
            Document doc;
            try {
                    doc = Jsoup.connect("http://pythono.ru/alina/fun.php").get();
                        anekdot = doc.select("*");
                        // Парсим с помощью Jsop Ответ сервера и выделяем текст из div c классом content
                        for (Element titles : anekdot) { otvet = titles.text(); }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        // Читаем вслух полученный анекдот
        @Override
        protected void onPostExecute(String result) {
                fun.setImageResource(R.drawable.anekdot);
                mTTS.speak(otvet, TextToSpeech.QUEUE_ADD, null);
        }
    }
}



Если вы захотите протестировать приложение, не забудьте скачать и настроить синтез русской речи от Google. На многих телефонах он настроен по умолчанию.

Тема о данной программе на 4pda.ru находится здесь:

http://4pda.ru/forum/index.php?showtopic=884149

Парсинг анекдотов на стороне PHP позволяет быть независимым от источника анекдотов, если сайт, который я сейчас использую в качестве поставщика контента отвалится, я всегда могу заменить его на другой, не выкатывая обновления для Android программы.

С помощью подобных приемов можно легко создать программу, читающую вслух новости, погоду, курсы валют и многое другое.

Материал подготовлен автором @pythono

14
136.697 GOLOS
На Golos с August 2017
Комментарии (1)
Сортировать по:
Сначала старые