Архив метки: Android

Обновление Google Play services 7.0

Сегодня будут обновлены сервисы Google Play, предоставляющие разработчикам возможность взаимодействовать с сервисами Google. Обновление улучшает работу настроек геопозиции, добавляет новое API для работы с сервисами определения местоположения, работы с  фитнес данными, автоматическое добавление рекламы AdMob и Google аналитики, а так же обновлённое взаимодействие с Google Games.

Диалог настройки местоположения

Так как нынешнее API определения местоположения использует все возможные в устройстве датчики, точность местоположения зависит от того, какие настройки активированы в данный момент (использование Wi-Fi, GPS, режим полёта и т.д.). В Google Play services 7.0 представлен стандартный механизм проверки необходимости задействовать тот или иной датчик устройства. Если есть необходимость задействовать дополнительный датчик, необходимый для выполнения конкретного запроса, появляется возможность предоставить пользователю диалоговое окно с настройками, не покидая самого приложения.

API данных о местах

Местоположение может исчисляться большим количеством параметров, чем по широте и долготе, потому новое API предоставляет возможность получать данные о местах из базы данных Google. С этим обновлением можно получать детали о местах, такие как : имя, адрес, телефон, сайт и многое другое. 
Если вы разрабатываете приложение с собственным интерфейсом (то-есть не используете GoogleMap в качестве части приложения), getCurrentPlace () вернёт вам данные о всех ближайших местах, занесённых в базу данных Google. Так же это API предоставляет возможность прогнозирования автозаполнения, для улучшения взаимодействия с пользовательским интерфейсом.
Так же появляется функционал добавления любимых мест пользователя и его текущего местоположения (addPlace() ). 
В данные момент данное API выпущено только для платформы Android, но уже ведётся бета-тестирование для iOS устройств, на которое можно подать заявку и использовать в своих приложениях.

Google Fit

В данной версии Google Play services прошлая версия Fitness.API была заменена на более новую Google Fit Android API с добавлением ряда интерфейсов : 
  • SENSORS_API — для получения текущих показателей датчика
  • RECORDING_API — для записи полученных данных 
  • HISTORY_API — для чтения,удаления и редактирования собранных данных в Google Fit
  • SESSIONS_API — для управления сессиями пользователя
  • BLE_API — для взаимодействия с устройствами подключенными по протоколу Bluetooth Low Energy (фитнес трекеры, браслеты, умные часы)
  • CONFIG_API — для доступа к пользовательским типам данных и настройке Google Fit
Данное обновление существенно снижает расход памяти приложениями, которые взаимодействуют с Google Fit сервисом. Как обычно предыдущая версия API все еще продолжает поддерживаться, но рекомендовано как можно быстрее переходить на использование новой версии.
Так же данное обновление существенно расширяет возможности по управлению с пользовательскими данными, например возможно добавление таких параметров как процентное соотношение жира и качество сна.

Google Mobile Ads 

В прошлом году сервис аналитики от Google был объединён и интегрирован в сервис AdMob. Новое обновление позволяет автоматически интегрировать аналитику в вашу кампанию мобильной рекламы и получать такие пользовательские данные как количество пользователей использующие приложение и их запущенные сессии, длительность сессии, версия операционной системы, модель устройства, а так же географические данные пользователя.

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

Google Play Games

В новые игровые сервисы включено Nearby Connections API, для определения запущенных неподалёку игр использующих Google Play Games, например для лёгкого и плавного подключения к ним, используя ваш смартфон или планшет в качестве второго экрана (контроллера) при игре на смарт TV.

App Indexing

Индексация приложений позволяет индексировать данные из вашего приложение, так же как индексируются обычные веб-сайты, что позволяет получать дополнительный приток пользователей непосредственно из поисковой выдачи Google. 
 

Автор: Taras Neduiev

Улучшенный алгоритм поиска мобильного контента от Google

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

Не так давно компания Google представила инструменты для тестирования сайтов на предмет удобства использования на мобильных устройствах, где просто указав url вашего сайта можно узнать насколько он адаптирован и как его видит googlebot, а так же настроить его отображение в инструментах для веб-разработчика.

Сегодня же компания Google изменила алгоритм индексации сайтов оптимизированных для мобильного использования, а так же опубликованных приложений, который базируется на двух главных принципах :

  1. Начиная с 21-го апреля вступают в силу новые правила ранжирования сайтов в поисковой выдаче в зависимости от их адаптированности для мобильных устройств. Эти изменения коснутся всех языков по всему миру и значительно изменят позиции при поиске с мобильного устройства. Следовательно пользователи будут получать более релевантную и оптимизированную информацию для их конкретных устройств. 
  • Для тестирования сайта на пригодность использования при отображении на смартфонах можно воспользоваться вот этим тестом.
  • Если вы являетесь администратором сайта, вы можете узнать все недочёты для мобильного юзабилити в инструментах для веб-мастеров Google.
  1. Начиная с сегодняшнего дня, данные из установленных мобильных приложений начинают использоваться как фактор ранжирования в поисковой выдаче, но скорей всего используются данные только из тех приложений, в которых пользователи залогинились под своим Google аккаунтом. Для того чтобы узнать, используется ли данные приложения для его индексирования, а так же сделать так, чтоб пользователи могли переходить к данным установленного у них приложения прямо из поисковой выдачи, необходимо ознакомится с руководством индексирования приложений в поисковой выдаче.

Автор: Taras Neduiev

Google представила новую программу "Android for Work"

Более миллиарда людей во всем мире используют смартфоны, которые стали для нас неотъемлемой частью жизни.

К сожалению для множества людей смартфоны еще не открыли весь свой потенциал для полноценного использования в работе. Потому сегодня Google анонсировал свою новую программу «Android for work» для раскрытия всего потенциала карманных гаджетов. Данный проект позволяет привлечь больше устройств в своем бизнесе и обеспечивает возможность управления бизнесом и увеличения его инновационного потенциала используя платформу Android.

Android for work включает в себя 4 базовых компонента:

  • Рабочие профили — построены на базе принципа шифрования по умолчанию, более жестких мер безопасности  SELinux, а так же поддержку нескольких пользователей при использовании Android 5.0 Lollipop. Теперь возможно создавать рабочий профиль и хранить рабочие данные на одном устройстве с личными данными и быть уверенным в их сохранности, а так же в сохранности личных данных, так как владелец/управляющий/работодатель не сможет просмотреть или очистить ваши данные.
  • Приложение Android for work — для устройств работающих на базе Ice cream sandwich и KitKat или устройств которые не поддерживают работу с профилями. Это приложение предоставляет безопасную работу с почтой, календарём, контактами, документами, а так же приложениями которые были отмечены как рабочие.
  • Google Play для работы — позволяет владельцам бизнеса безопасно управлять приложениями для всех пользователей использующих Android for work, а так же распределения (удалённую установку) приложений своим сотрудникам.
  • Встроенные инструменты повышения производительности — набор приложений для повседневных бизнес задач включающий в себя приложения для почты, контактов, календаря и обеспечивает обмен заметками между рабочими устройствами, а так же совместное редактирование документов и таблиц.
Более подробно узнать о данной программе можно на её официальном сайте.

Автор: Taras Neduiev

Как использовать RecyclerView в Android

С выходом новой версии Android и привнесением в мир нового течения Material Design-а, появились и обновлённые, более современные версии старых вьюшек. Одно из таких обновлений затронуло и привычны вид отображения списка — ListView, на замену которого пришёл более быстрый и многофункциональный RecyclerView.

Главным отличием RecyclerView является создания всех элементов списка единожды, в отличии от ListView, где каждая View в списке создавалась отдельно для каждого из элементов списка, что в свою очередь приводило к огромному использованию памяти при создании достаточно больших списков.

Как начать работать с RecyclerView.

Для начала необходимо подключить библиотеку RecyclerView. Сделать это можно либо прописав зависимости в Gradle файл, либо же нажав кнопку F4 на нашем проекте и перейдя в вкладку «Dependencies». Так же подключим библиотеку CardView, так как элементы списка будем отображать в виде карточек и библиотеку Picasso, с помощью которой подгрузим изображения.

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
compile 'com.android.support:cardview-v7:21.0.3'
compile 'com.android.support:recyclerview-v7:21.0.3'
compile 'com.squareup.picasso:picasso:2.3.2'
}

Теперь создадим отображение нашего списка, поместив в layout  активности наш RecyclerView.
activity_main.xml

    public String getUniverse(){return universe;}
public String getImage() {return image;}

}

Создавать элементы списка нам будет наш кастомный адаптер, который будет создавать представление элементов для всего списка сразу, а не для для каждого по отдельности и работа с которым не отличается от работы с кастомными адаптерами при использовании ListView.
HeroAdapter.java

package com.awesomedevelop.recyclerview;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.picasso.Picasso;

import java.util.ArrayList;

/**
* Created by Taras on 30.01.2015.
*/
public class HeroAdapter extends RecyclerView.Adapter {

private ArrayList heroDataSet;
public Context mContext;
private int lastPosition = -1;
public static class MyViewHolder extends RecyclerView.ViewHolder {
TextView textName;
TextView textUniverse;
ImageView imageHero;

public MyViewHolder(View itemView){
super (itemView);
this.imageHero = (ImageView)itemView.findViewById(R.id.image);
this.textName = (TextView)itemView.findViewById(R.id.hero_name);
this.textUniverse = (TextView)itemView.findViewById(R.id.hero_universe);
}
}



public HeroAdapter(Context context, ArrayList heroes){
this.heroDataSet= heroes;
mContext=context;
}


@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.hero_card, parent, false);
MyViewHolder myViewHolder = new MyViewHolder(view);

return myViewHolder;
}




@Override
public void onBindViewHolder(final MyViewHolder holder, final int listPosition) {

final TextView textViewName = holder.textName;
final TextView textViewUniverse = holder.textUniverse;
ImageView imageViewHero = holder.imageHero;
textViewName.setText(heroDataSet.get(listPosition).getName());
textViewUniverse.setText(heroDataSet.get(listPosition).getUniverse());

String src = heroDataSet.get(listPosition).getImage();
Picasso.with(mContext)
.load("file:///android_asset/images/"+src+".jpg")
.resize(300, 300)
.into(imageViewHero);
}

@Override
public int getItemCount() {
return heroDataSet.size();
}

}

В данном примере используются изображения, хранящиеся в папке асетов, но использовать можно (по необходимости) любое расположение. Например если используя библиотеку Picasso вы укажете путь к онлайновому расположению изображений, они будут подгружаться только для тех элементов списка, которые будут отображены на экране в данный момент, а не для всего списка сразу  при его построении.

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

package com.awesomedevelop.recyclerview;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Menu;
import android.view.MenuItem;

import java.util.ArrayList;


public class MainActivity extends ActionBarActivity {
private static ArrayList heroes;
private static RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
private static RecyclerView.Adapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);

fetchHeroes(); //Заполняем массив
adapter = new HeroAdapter(MainActivity.this,heroes); //Инициализируем наш адаптер
recyclerView.setAdapter(adapter); // Устанавливаем адаптер

}

//Заполняем массив
public void fetchHeroes(){
heroes = new ArrayList();

heroes.add(new HeroData("Зелёный Фонарь","DC comics","greenlantern"));
heroes.add(new HeroData("Джокер","DC comics","joker"));
heroes.add(new HeroData("Джона Хекс","DC comics","jonah-hex"));
heroes.add(new HeroData("Папа Миднайт","DC comics","glav"));
heroes.add(new HeroData("Ворона","DC comics","raven"));
heroes.add(new HeroData("Чёрная Вдова","Marvel","glavnaya"));
heroes.add(new HeroData("Капитан Америка","Marvel","cap_america"));
heroes.add(new HeroData("Космический Халк","Marvel","cosmic_hulk"));
heroes.add(new HeroData("Призрачный Гонщик","Marvel","ghost_rider"));


}





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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}

return super.onOptionsItemSelected(item);
}
}

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

Проект на github.

Автор: Taras Neduiev

Собственная база данных на Android с возможностью обновления

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

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

Почему не работает обычный способ.

В примерах которые можно найти в интернете в большем обилии, при обращении к вашей БД, приходится вызывать её с помощью метода createDatabase(), которая копирует вашу заранее созданную базу в папку приложения. Но при вызове данного метода Android не обращается к методу onUpdate() , потому даже если вы измените версию базы, ничего не произойдёт, так как не произойдёт сравнение её версий. 
Метод onUpdate() вызывается только в случае обращения к базе данных с помощью методов getWritableDatabase() или getReadableDatabase(), в этом случае база создается и копируется если не существовала ранее и вызывается метод onUpdate(),если база уже существовала. Но если вы попробуете в методе onUpdate() удалить прошлую версию БД — приложение закроется с крешем, так как метод обновления будет вызван (а значит и база будет удалена) раньше чем будет создана новая, а потому получить доступ к несуществующей в этот момент базе не удастся.

Как обновить собственную базу данных.

Для того, чтобы удалить старую и обновить БД  придется вручную контролировать её версию и сделать это до вызова метода onUpdate(), чтобы избежать попытки её открытия до её фактического создания. Для этого будем использовать собственный метод обновления, а версии хранить и контролировать с помощью SharedPreferences.
Для использования собственной базы данных в Android создайте новый класс ExternalDbOpenHelper и поместите в него приведённый ниже код.



import android.content.Context;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.preference.PreferenceManager;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
* Created by AwesomeDevelop on 24.12.2014.
*/
public class ExternalDbOpenHelper extends SQLiteOpenHelper
{
private static final String DATABASE_NAME = "db.sqlite3"; // Название файла с БД
private static final int DATABASE_VERSION = 1; //Версия БД
private static final String SP_KEY_DB_VER = "db_ver";
private final Context mContext;

public ExternalDbOpenHelper(Context context, String DB_NAME) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
mContext = context;
initialize();
}

/**
* Инициализация БД. Создание новой если ранее не существовала.
*/
private void initialize() {
if (databaseExists()) {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(mContext);
int dbVersion = prefs.getInt(SP_KEY_DB_VER, 1);
if (DATABASE_VERSION != dbVersion) {
File dbFile = mContext.getDatabasePath(DATABASE_NAME);
if (!dbFile.delete()) {
// Log.w(TAG, "Невозможно обновить БД");
}
}
}
if (!databaseExists()) {
createDatabase();
}
}

/**
* Проверка существования файла БД. Если существует - возвращает true.
* @return
*/
private boolean databaseExists() {
File dbFile = mContext.getDatabasePath(DATABASE_NAME);
return dbFile.exists();
}

/**
* Создание БД, копирование файла из Assets.
*/
private void createDatabase() {
String parentPath = mContext.getDatabasePath(DATABASE_NAME).getParent();
String path = mContext.getDatabasePath(DATABASE_NAME).getPath();

File file = new File(parentPath);
if (!file.exists()) {
if (!file.mkdir()) {
// Log.w(TAG, "Невозможно создать папку БД");
return;
}
}

InputStream is = null;
OutputStream os = null;
try {
is = mContext.getAssets().open(DATABASE_NAME);
os = new FileOutputStream(path);

byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
os.flush();
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(mContext);
SharedPreferences.Editor editor = prefs.edit();
editor .putInt(SP_KEY_DB_VER, DATABASE_VERSION);
editor.commit();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

@Override
public void onCreate(SQLiteDatabase db) {
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion,
int newVersion) {
}
}


Для работы данного класса, вам необходимо только указать название файла с созданной вами базой данных и её версию. Как только версия БД будет увеличена — старая её версия будет удалена, а новый файл БД скопирован. Но не пробуйте понизить версию, как и при обычном использовании будет получена ошибка о невозможности выполнить DownGrade и приложение будет закрыто. 
Работа с БД осуществляется стандартными для Android способами, потому вы можете работать с ней, как с стандартной Sqlite базой.
Открытие БД.

ExternalDbOpenHelper dbOpenHelper = new ExternalDbOpenHelper(this, DB_NAME);

SQLiteDatabase database= dbOpenHelper.getWritableDatabase();

Получить данные можно, к примеру, вот так:

data = new ArrayList();

Cursor dataCursor = database.query(
TABLE_NAME,
new String[] { DATA_NAME,DATA_IMAGE},
null, null, null, null,
DATA_NAME);
dataCursor.moveToFirst();


if(!dataCursor.isAfterLast()){
do {
String image =dataCursor.getString(1);
String name = dataCursor.getString(0);
data.add(new BrandData(name,image));

} while (dataCursor.moveToNext());
}
dataCursor.close();

И так, для использование заранее созданной базы данных необходимо:
  1. Создать файл базы данных Sqlite с любым наполнением, о том как это сделать можно прочитать тут, а для создания использовать Navicat .
  2. Поместить созданный файл в папку Assets.
  3. Создать класс ExternalDbOpenHelper и поместить в него код, приведённый в статье.
  4. Использовать вашу БД стандартными способами, описанными в официальной документации

Автор: Taras Neduiev

Самый быстрый эмулятор Android. Установка и настройка Genymotion.

Если вы только начинаете или собираетесь начать разрабатывать приложения для OS Android, вам следует обратить внимание на этот скоростной эмулятор.

Не секрет, что устройства под этой операционной системой имеют огромную фрагментацию, существует огромнейшее количество устройств с различными размерами экрана, разрешениями экрана, различной комплектацией и производительности. Поэтому при разработке приложений возникает необходимость тестировать приложение на различных устройства. Естественно у вас не может оказаться под рукой такого количества различных устройств для теста и тогда на спасение приходят эмуляторы. Стандартный эмулятор, который включен в комплект SDK, мягко говоря далек от совершенства, работа с ним, даже в виде одного устройства, вызывает непередаваемо огромное количество эмоций и все они ,к сожалению, негативны. Ожидание запуска в несколько минут (в лучшем случае минут 3-5), ожидание отклика при нажатии любого элемента, заторможенность, все это делают его непригодным для работы.

К счастью несколько дней назад на свет появился эмулятор Genymotion базирующийся на VirtualBox-е, с которым разработка и тестирование приложений станет сплошным наслаждением.

Установка Genymotion.

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

После регистрации качаем сам Genymotion перейдя на страницу загрузки или выбрав соответствующий пункт меню на сайте. Далее вбираем репозиторий для вашей операционной системы. Если у вас ранее не был установлен VirtulBox – не переживайте, он будет загружен и установлен вместе с эмулятором.

После загрузки репозитория приступаем к его установке. В процессе установки проблем возникнуть не должно, все сведется к соглашению со всем и нажатием кнопки “далее”, единственным непривычным моментом может стать появление окна безопасности, в котором необходимо разрешить устанавливать продукты Oracle.

После полной установки, запускаем Genymotion и входим под логином и паролем, которые регистрировали на сайте.

Как только вход в систему будет выполнен, появится возможность добавлять новые устройства, этими виртуальными устройствами вы и будете пользоваться в дальнейшем. Для добавления выбираем нужное устройство и нажимаем кнопку “Add”.

Далее везде нажимаем “Next” и дожидаемся загрузки файлов для виртуального устройства.

Настройка Genymotion.

Для корректного взаимодействия эмулятора и в