Пишем справочник по математике под Android, подключаем рекламу Begun

Здравствуйте, уважаемые Хабровчане! Вы видели немало постов на тему разработки под android. В данном посте я попытаюсь наиболее подробно изложить свой небольшой опыт разработки под эту ОС.

Небольшое вступление


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


Структура приложения


О создании приложения такого плана на Хабре уже писали в посте Пишем шпаргалку на Android. Разумеется есть некоторые отличия. Первое и главное из них в том, что в нашем приложении нужно будет сделать чуть побольше Activity, второе — добавление в приложение социальных возможностей, таких как отправить письмо разработчику и самостоятельно поучаствовать в создании приложения любому желающему, также добавим в приложение меню опций и несколько диалоговых окон, ну и собственно подключим к нему рекламу Begun, чтобы хоть как-то оправдать затраты на приобретение аккаунта разработчика на маркете.

Activity

MainActivity

При запуске приложения пользователь будет видеть экран MainActivity:
image
Он содержит три кнопки, при нажатии на которые осуществляется переход на MatanActivity, GeomActivity, или TerverActivity, содержащие в своих файлах-разметки элементы ListView, представляющие набор соответствующих тем по нужному предмету. Подробный код MainActivity представлен ниже:

public class MainActivity extends Activity {
AdView ad;
//Объявление идентификатора диалогового окна HELP и диалогового окна Exit
static final int EXIT_DIALOG=0;
static final int HELP_DIALOG=1;
 
 
   //Вызов меню опций с одной кнопкой About
    Override
   public boolean onCreateOptionsMenu(Menu menu) {
       MenuInflater inflater = getMenuInflater();
       inflater.inflate(R.menu.gameoptions, menu);
       menu.findItem(R.id.about_menu_item);
       menu.findItem(R.id.btn_email);
       return true;
   }
  //обработка нажатий на эл-ты меню опций
   //Вызов диалога HELP из меню опций при нажатии на "О приложении" и переход на EmailActivity при нажатии на "свяжитесь с нами"
    Override
   public boolean onOptionsItemSelected(MenuItem item) {
   switch (item.getItemId()) {
    case R.id.about_menu_item:
        showDialog(HELP_DIALOG);
        return true;
    case R.id.btn_email:
     startActivity(new Intent(getApplicationContext(),EmailActivity.class));
        return true;
    default:
        return super.onOptionsItemSelected(item);
    }
   }
 
/** Called when the activity is first created. */
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); //скрываем заголовок
setContentView(R.layout.second);   
 
  //подключение рекламы
// Получаем вид
ad = (AdView)findViewById(R.id.ad);
ad.onDebug = true; 
// Устанавливаем слушатели событий
// callback — слушатель, благодаря которому можно получить информацию
// о событиях в библиотеке. Пока доступны следующие листенеры: AdLoaded, AdClickThru
// и AdStopped. Для инициализации необходимо передать параметр environmentVars,
// который содержит информацию о зарегистрированной площадке в системе
// (BEGUN_PAD_ID, BEGUN_BLOCK_ID).
// Для начала инициализации необходимо вызвать метод ad.init. Затем дождаться
// callback со статусом adLoaded и только после этого вызвать метод
// ad.api("initAd",al);
ad.setOnApiListener(new Callback() {
Override
public void init() {
Log.d("BEGUN_AD""ad.api|initAd"); 
ArrayList<RequestParam> al = new ArrayList<RequestParam>();
RequestParam rp = new RequestParam();
rp.name = "environmentVars";
rp.value = "pad_id:261629112|block_id:261629500";
al.add(rp);
ad.api("initAd", al);
Log.d("BEGUN_AD""CALLBACK params: " + al.toString()); 
}
Override
public void callback(String c) {
Log.d("BEGUN_AD""CALLBACK API : " + c); 
if (c.equals("AdLoaded")) {
Log.d("BEGUN_AD""startAd " + c);
ad.api("startAd");
}
}
});
        Log.d("BEGUN_AD""ad.init"); 
ad.init();
 
    //Запуск MatanActivity
    Button b=(Button)this.findViewById(R.id.btn_mathan);
        b.setOnClickListener(new OnClickListener(){
         public void onClick(View arg0){
         startActivity(new Intent(getApplicationContext(),MatanActivity.class));
         }
        }); 
 
           //Запуск GeomActivity
     Button d=(Button)this.findViewById(R.id.btn_geom);
        d.setOnClickListener(new OnClickListener(){
         public void onClick(View arg0){
         startActivity(new Intent(getApplicationContext(),GeomActivity.class));
         }
        }); 
 
           //Запуск TerverActivity
 
     Button c=(Button)this.findViewById(R.id.btn_terver);
        c.setOnClickListener(new OnClickListener(){
         public void onClick(View arg0){
         startActivity(new Intent(getApplicationContext(),TerverActivity.class));
         }
        });
 
    }
 
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
Log.d("BEGUN_AD""resumeAd");
ad.api("resumeAd");
} 
 
 
//Создание диалоговых окон HELP_DIALOG и EXIT_DIALOG
      Override
      protected Dialog onCreateDialog(int id)
{
     switch (id) 
{
case HELP_DIALOG:
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.help,
                               (ViewGroup) findViewById(R.id.root));
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(layout)
       .setCancelable(true)
       .setTitle("О приложении")
       .setNeutralButton("ОК"new DialogInterface.OnClickListener() 
       {
           public void onClick(DialogInterface dialog, int id) 
           {
                dialog.cancel();
           }  
       });
    AlertDialog alert = builder.create();
    return builder.create();
 
 
case EXIT_DIALOG:
AlertDialog.Builder builder3 = new AlertDialog.Builder(this);
                builder3.setMessage("Уверены, что хотите выйти?")
                        .setCancelable(false)
                        .setPositiveButton("Да"new DialogInterface.OnClickListener() {
                       public void onClick(DialogInterface dialog, int id) {
                            SecondActivity.this.finish();
                       }
                   })
                   .setNegativeButton("Нет"new DialogInterface.OnClickListener() {
                       public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                       }
 
                   });
            AlertDialog alert3 = builder3.create();
            return builder3.create();
 
default:
return null;
}
 
    }
 
 
     //Вызов диалога EXIT_DIALOG при нажатии на клавишу back смартфона
           Override
          public void onBackPressed (){
          showDialog(EXIT_DIALOG);    
      }
 
    }
 


Диалоговое окно «О приложении»
image

Диалоговое окно выхода из приложения
image

Реклама добавлена в приложение больше из интереса, чем из коммерческих соображений, т.к. очевидно, что на русском приложении много не заработать. Поэтому я подключил в него чисто русскую рекламу системы Begun, до этого на Хабре многое писалось про подключение рекламы, но в основном это были зарубежные «конторы».

Плюсы использования рекламы Бегун

1. Удобный, качественный API.
2. Удобный вывод денег на WebMoney.
3. Хорошая служба поддержки, стабильно отвечающая на любые ваши вопросы.

Минусы использования рекламы Бегун

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

Как подключить рекламу BEGUN

1. Заходим на сайт бегуна в раздел партнерам.
2. Жмем «Стать партнером».
3. Заполняем анкету.
4. Жмем зарегестрироваться.
5. Далее входим в свой кабинет на сайте.
6. В правом верхнем углу жмете «Написать» (Перейдете в меню написания письма в службу поддержки).
7. Пишите в службу поддержки о том, что у вас есть android-приложение и вы бы хотели подключить в него рекламу Begun, вам вышлют ваш pad_id и block_id, которые в ы и вставляете в код, написанный выше, вместо тегов <Ваш pad_id> <Ваш block_id>.

Интеграция рекламы Begun в приложение

1. В classpath проекта необходимо добавить jar — библиотеку рекламы, доступную
по адресу appsmobile.begun.ru/begunAdView.jar.
2. Необходимо добавить в layout следующий блок:

<ru.begun.adlib.AdView
android:id="@+id/ad"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
/>


В качестве родительского слоя рекомендуется использовать RelativeLayout.
3. Файл манифеста необходимо добавить следующие разрешения:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>


4. Инициализация библиотеки происходит следующим образом:

import ru.begun.adlib.AdView;
import ru.begun.adlib.Callback;
import ru.begun.adlib.RequestParam;
AdView ad;
// Получаем вид
ad = (AdView)findViewById(R.id.ad);
// Устанавливаем слушатели событий
// callback — слушатель, благодаря которому можно получить информацию
// о событиях в библиотеке. Пока доступны следующие листенеры: AdLoaded, AdClickThru
// и AdStopped. Для инициализации необходимо передать параметр environmentVars,
// который содержит информацию о зарегистрированной площадке в системе
// (BEGUN_PAD_ID, BEGUN_BLOCK_ID).
// Для начала инициализации необходимо вызвать метод ad.init. Затем дождаться
// callback со статусом adLoaded и только после этого вызвать метод
// ad.api("initAd",al);
ad.setOnApiListener(new Callback() {
Override
public void init() {
ArrayList<RequestParam> al = new ArrayList<RequestParam>();
RequestParam rp = new RequestParam();
rp.name = "environmentVars";
rp.value = "pad_id:<BEGUN_PAD_ID>|block_id:<BEGUN_BLOCK_ID>";
al.add(rp);
ad.api("initAd", al);
}
Override
public void callback(String c) {
if (c.equals("AdLoaded")) {
ad.api("startAd");
}
}
});
ad.init();


Для возобновления показа рекламных объявлений после того, как библиотека была остановлена,
необходимо вызвать метод ad.api с параметром resumeAd.

Все, реклама подключена и работает!

main.xml

Файл-разметки MainActivity.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:weightSum="1" 
    android:background="@drawable/main_1">
 
    <Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@layout/button_selector_leftcorner"/>
 
    <Button android:textStyle="bold" android:textColor="#FFC000" android:background="@layout/button_selector" android:layout_height="wrap_content" android:layout_width="173dp" android:text="Ан. геометрия и лин. алгебра" android:id="@+id/btn_geom" android:layout_above="@+id/btn_terver" android:layout_alignLeft="@+id/btn_terver" android:layout_marginBottom="16dp"></Button>
    <Button android:textStyle="bold" android:textColor="#FFC000" android:background="@layout/button_selector"  android:layout_height="wrap_content" android:layout_width="173dp" android:text="Математический      анализ" android:id="@+id/btn_mathan" android:layout_above="@+id/btn_geom" android:layout_alignLeft="@+id/btn_geom" android:layout_marginBottom="15dp"></Button>
    <Button android:textStyle="bold" android:textColor="#FFC000" android:background="@layout/button_selector"  android:layout_height="wrap_content" android:layout_width="173dp" android:text="Теория                      вероятностей" android:id="@+id/btn_terver" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="186dp"></Button>
    <ImageView android:id="@+id/imageView1" android:src="@drawable/andro" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_above="@+id/btn_mathan" android:layout_centerHorizontal="true"></ImageView>
       <RelativeLayout android:layout_height="wrap_content" android:layout_width="fill_parent">
          <ImageView android:id="@+id/imageView2" android:layout_height="wrap_content" android:layout_width="wrap_content" android:src="@drawable/title" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="18dp"></ImageView>
       </RelativeLayout>             
   <ru.begun.adlib.AdView
      android:id="@+id/ad"
      android:orientation="vertical"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:layout_alignParentBottom="true"
    />
 
   <ImageView
    android:id="@+id/splashscreen"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:src="@drawable/splashscreen" android:background="#000"> 
    </ImageView>
 
 
 
 
</RelativeLayout>
 


MatanActivity, GeomActivity и TerverActivity


image

После клика по элементам списка в MatanActivity, GeomActivity или TerverActivity будет осуществляться переход на соответствующую деятельность отображения материала по данной теме ViewMatanActivity, ViewGeomActivity или ViewTerverActivity

image

Код этих активити аналогичен указанным в посте Пишем шпаргалку на Android.

Единственное замечание во всех ViewActivity вместо кода:

WebView myWebView = (WebView) findViewById(R.id.webview);
String summary = "<html><body>" + text + "</body></html>";
myWebView.loadData(summary, "text/html""utf-8"); //загружаем текст в webview


лучше писать так:

WebView myWebView = (WebView) findViewById(R.id.webview);
String summary = "<html><body>" + text + "</body></html>";  
myWebView.loadDataWithBaseURL("x-data://base",summary, "text/html""utf-8"null);


В противном случае код будет некорректно работать на устройствах с android 3.2. и некоторых других.

EmailActivity

EmailActivity реализует отправку письма со своими пожеланиями и предложениями разработчикам, а также представляет возможность перехода на страницу приложения в маркете.
image

public class EmailActivity extends Activity {
 Button send;
  EditText address, subject, emailtext;
 
   Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE); //скрываем заголовок
    setContentView(R.layout.email);
 
    Button b=(Button)this.findViewById(R.id.btn_market);
        b.setOnClickListener(new OnClickListener(){
         public void onClick(View arg0){
         Uri address=Uri.parse("market.android.com/details?id=com.mathhelper.math");
         Intent surf=new Intent(Intent.ACTION_VIEW, address);
         startActivity(surf);
         }
        }); 
 
    // Наши поля и кнопка
    send = (Button) findViewById(R.id.emailsendbutton);
    address = (EditText) findViewById(R.id.emailaddress);
    //subject = (EditText) findViewById(R.id.emailsubject);
    emailtext = (EditText) findViewById(R.id.emailtext);
 
    send.setOnClickListener(new OnClickListener() {
 
       Override
      public void onClick(View v) {
 
        final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
 
        emailIntent.setType("plain/text");
        // Кому
        emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,new String[] { address.getText().toString() });
 
        // О чём
        emailIntent.putExtra(android.content.Intent.EXTRA_TEXT,emailtext.getText().toString());
 
        EmailActivity.this.startActivity(Intent.createChooser(emailIntent,
            "Отправка письма"));
      }
    });
  }
}


email.xml


Файл разметки EmailActivity

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:weightSum="1">
 
    <ScrollView 
    android:scrollbars="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">    
    <LinearLayout android:orientation="vertical" android:id="@+id/linearLayout2" android:background="@drawable/metall" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_marginTop="40dp" android:layout_width="fill_parent" android:layout_height="197dp">
        <TextView android:layout_width="wrap_content" android:text="Напишите нам:" android:layout_height="wrap_content" android:id="@+id/textView1" android:gravity="left"  android:textSize="10pt" android:textStyle="normal"></TextView>
        <EditText android:id="@+id/emailaddress" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="svdsoftware@gmail.com"></EditText>
        <EditText android:id="@+id/emailtext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Ваш отзыв..."></EditText>
        <RelativeLayout android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/relativeLayout1">
            <TextView android:id="@+id/textView1" android:text="Отправить нам email →" android:layout_width="wrap_content" android:gravity="left" android:layout_height="wrap_content" android:textSize="9pt" android:textStyle="normal" android:layout_centerVertical="true"></TextView>
            <Button android:id="@+id/emailsendbutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@layout/button_selector_email" android:layout_alignParentTop="true" android:layout_alignParentRight="true"></Button>
        </RelativeLayout>
        <RelativeLayout android:id="@+id/relativeLayout2" android:layout_height="wrap_content" android:layout_width="fill_parent">
            <Button android:id="@+id/btn_market" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@layout/button_selector_am" android:layout_alignParentTop="true" android:layout_alignParentRight="true"></Button>
            <TextView android:id="@+id/textView1" android:text="Оценить на маркете  →" android:layout_width="wrap_content" android:gravity="left" android:layout_height="wrap_content" android:textSize="9pt" android:textStyle="normal" android:layout_centerVertical="true" ></TextView>
        </RelativeLayout>
    </LinearLayout>
    </ScrollView>
 
</RelativeLayout>
 


Заключение


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

Комментарии 27

    0
    Молодцы!

    Идея с рекламой 100% оправдает затраченное время во время экзаменов и сессий.
      +17
      И, если не секрет, как у вас с заработками в Бегуне?
        +2
        Отформатируйте пожалуйста код и разметку. А то… кхм… тяжко

        А что можете сказать про бегун кроме описанного в посте?
        Есть статистика использования, какова стоимость просмотра и т.д.?
          0
          Если честно, пока с заработком не очень, т.к. платят только за переходы по рекламе, все обещают, что вот-вот запустят систему с платой за показы, но пока ждем. Да и закачек приложения на маркете пока немного, около 1200, т.к. я особо не занимался рекламой своего приложения.
            +13
            Все ваше приложение можно было бы уложить в несколько html-страничек и показывать их через webkit-объект.
              –2
              возможно, не спорю, но писать столько html-кода это уж слишком, да и я думаю, что предложенный вами вариант функционировал бы медленнее чем данный.
                0
                возможно, не спорю, но писать столько html-кода это уж слишком, да и я думаю, что предложенный вами вариант функционировал бы медленнее чем данный.
                  +5
                  Учебник по математике с рекламой. На мой взгляд это извращение.
                    0
                    реклама только в главном меню, да и в начале любого учебника имеется реклама (издательство такое-то,
                    с нами сотрудничают такие-то, зайдите на нашу страничку в интернете, купите еще книги и т.д.)

                    И я уже писал в посте, что реклама подключена больше из интереса, чем из коммерческой выгоды.
                      0
                      А можно скриншот с рекламой? Как он выглядит в приложении. И все же, люди кликают по рекламе?
                        0
                        вот пожалуйста:

                        image

                        клики есть, но не так много, как хтелось бы, все-таки платы за показы не хватает.
                          0
                          Интересно, какой процент из них — клики по ошибке (случайные клики) :)
                            0
                            Хотя бы на пиво по пятницам хватает? ))
                            А можно там настраивать вид рекламы. Тут недавно на Хабре был пост, когда вдруг в рекламе пошла откровенная эротика (кажется, от рекламной сети гугла), что негативно повлияло на имидж
                              0
                              сайт знакомств вполне может быть контекстной, специально ориентированной рекламой для тех кто читает этот справочник по математике)
                            0
                            этого мы к сожалению узнать не можем.
                              0
                              ТЕЛЕФОННЫЕ ВЫЗОВЫ
                              ПОЛУЧЕНИЕ ДАННЫХ О СОСТОЯНИИ И ИДЕНТИФИКАТОРАХ ТЕЛЕФОНА
                              Приложение сможет получать доступ к функциям телефона на устройстве. Приложение с таким разрешением может определить номер телефона и серийный номер устройства, наличие активного вызова, номер вызываемого/вызывающего абонента и т. п.


                              А зачем вот это в приложении?
                                0
                                для библиотеки бегуна судя по всему.
                                0
                                Не могу понять, зачем сливать в статью весь код проекта и xml файлов? он шаблонный на 90%
                                И постарайтесь больше не делать диалоги вида «вы действительно хотите выйти?» в андроиде выходят кнопкой назад, а подобные диалоги в большинстве случаев раздражают
                                  0
                                  Добрый день. А не можете интересу ради показать график активных пользователей в статистике гугл? Вызывает интерес, как быстро он рос. Я сам пытаюсь начать разрабатывать для андроида, поэтому крайне интересны такие посты.
                                  Хотя да, диалог «Уверены, чот хотите выйти» лучше убрать, тем более, что в андроиде активности не обязательно помирают, когда из них выходишь, и, скорее всего, зайдя снова — попадешь туда, на чем остановился.
                                    0
                                    Если деньги с проекта пойдут, я бы посоветовал нанять дизайнера для оформления всего этого…
                                      0
                                      Подумаем над этим.
                                      +1
                                      График активных пользователей, как просили:

                                      image
                                        0
                                        Спасибо!
                                        Слушайте ну неслабо он у вас растет, поздравляю. Значит народу нравится, это здорово.
                                        Как-либо раскручивали приложение? Публикация на Хабре не в счет, она как я понял — 3 ноября, это в самом конце графика…
                                          +1
                                          Приложение особо не рекламировал, но заметил, что оно появляется на сайтах, занимающихся распространением приложений, это же в интересах любого подобного сайта — добавлять себе в «коллекцию» новые приложения, чтобы привлечь народ. Вот и вся раскрутка, т.о. получается, что любое приложение раскручивается в основном сторонними сайтами, которые делают это не для того, чтобы помочь разработчику, а для того, чтобы не потерять своих пользователей.

                                          P.S. Также заметил сообщения в Twitter'e, указывающие на ссылку, где можно скчать приложение.
                                            0
                                            А где взяли материал для справочника? Как решается вопрос с правами? Есть ли ссылки на источник?
                                              0
                                              источники все разные, но вроде все в свободном доступе, кое-что исправлял и корректировал, кое-что добавлял от себя.
                                                0
                                                Можете сделать апдейт по результатам установок и дохода от рекламы?

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

                                                Самое читаемое