вторник, 7 мая 2013 г.

BroadcastReceiver в Android

Продолжаем разбирать полезные вещи в Android и сегодняшний урок я хотел бы посвятить такой вещи как BroadcastReceiver.
BroadcatReceiver(приемник широковещательных сообщений) - это компонент для получения внешних событий и реакции на них. BroadcastReceiver это объект, который начинает выполнять действия, по получению какого нибудь сигнала (Intent). Сервис в отличии от BroadcastReceiver работает сразу после того как его запустили. У данного класса только один метод onReceive.

 void onReceive(Context curContext, Intent broadcastMsg)   

Когда широковещательное сообщение прибывает для получателя сообщения, Android вызывает его методом onReceive() и передает в него объект Intent, содержащий сообщение. Приемник широковещательных сообщений является активным только во время выполнения этого метода.

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

Рассмотрим такой пример : 
 import android.os.Bundle;  
 import android.app.Activity;  
 import android.content.BroadcastReceiver;  
 import android.content.Context;  
 import android.content.Intent;  
 import android.content.IntentFilter;  
 import android.widget.ProgressBar;  
 import android.widget.TextView;  
 public class BatteryIndicatorActivity extends Activity {  
   private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver() {  
     @Override      
     public void onReceive(Context c, Intent i) {  
       int level = i.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);  
       ProgressBar pb = (ProgressBar) findViewById(R.id.progressbar);  
       pb.setProgress(level);  
       TextView tv = (TextView) findViewById(R.id.textfield);  
       tv.setText("Battery Level: " + Integer.toString(level) + "%");  
     }  
   };  
   @Override  
   public void onCreate(Bundle savedInstanceState) {  
     super.onCreate(savedInstanceState);  
     setContentView(R.layout.main);  
     registerReceiver(mBatInfoReceiver, new IntentFilter(  
         Intent.ACTION_BATTERY_CHANGED));  
   }  
 }  

Так а теперь разберемся что я здесь "накалякал". Создаем обьект mBatInfoReceiver , в onReceive получаем уровень батареи через системный Intent  BatteryManager.EXTRA_LEVEL и после этого отображаем информацию в ProgressBar и TextView .  Для того чтобы данный "ресивер" заработал его нужно зарегить. Делается это двумя способами или в onCreate (как сделано у меня выше) или в AndroidManifest.

 <receiver android:name=".SimpleBroadcater" android:label="Simple">  
    <intent-filter>  
     <action android:name="android.intent.action.BATTERY_CHANGED"/>  
    </intent-filter>  
   </receiver>  

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

воскресенье, 5 мая 2013 г.

Подгрузка категорий через AsyncTask

Сегодня как и обещал хотел посвятить статью работой с AsyncTask. AsyncTask - это класс который предназначен для выполнения операций отдельно от UI потока и передача результатов выполнения в основной поток.
Продолжим реализацию CategoryActivity , мы хотим подгрузить категории и отобразить их в ListView.


 private class AsyncCaller extends AsyncTask<Void, Void, Void> {  
           ProgressDialog pdLoading = new ProgressDialog(CategoryActivity.this);  
           @Override  
           protected void onPreExecute() {  
                super.onPreExecute();  
                pdLoading.setMessage("\tЗагрузка...");  
                pdLoading.show();  
           }  
           @Override  
           protected Void doInBackground(Void... params) {  
                api = new API();  
                categoriesArr = api.getCategoryQuiz();  
                Log.d("size", categoriesArr.size() + "");  
                for (int i = 0; i < categoriesArr.size(); i++) {  
                     Map<String, String> category = new HashMap<String, String>();  
                     category.put("category_id",  
                               String.valueOf(categoriesArr.get(i).getCategoryId()));  
                     category.put("category_name", categoriesArr.get(i)  
                               .getCategoryName());  
                     categoryList.add(category);  
                }  
                return null;  
           }  
           @Override  
           protected void onPostExecute(Void v) {  
                pdLoading.dismiss();  
                SimpleAdapter sAdapter = new SimpleAdapter(CategoryActivity.this,  
                          categoryList, android.R.layout.simple_list_item_1,  
                          new String[] { "category_name" },  
                          new int[] { android.R.id.text1 });  
                lvCategory.setAdapter(sAdapter);  
           }  
      }  

Как видим данный класс имеет три основных метода onPreExecute(выполняется перед doInBackground, имеет доступ к UI), doInBackground(выполняется в новом потоке, здесь мы и выполняем основную работу), onPostExecute(после выполнения doInBackground,не выполняется если AsyncTask отменен).
В нашем примере мы получаем данные в doInBackground и onPostExecute создаем SimpleAdapter для ListView. Затем в onCreate запускаем наш AsyncTask и делаем обработчик для ListView :


 @Override  
      protected void onCreate(Bundle savedInstanceState) {  
           super.onCreate(savedInstanceState);  
           setContentView(R.layout.category);  
           lvCategory = (ListView) findViewById(R.id.lvCategories);  
           lvCategory.setOnItemClickListener(new OnItemClickListener() {  
                @Override  
                public void onItemClick(AdapterView<?> parent, View view,  
                          int position, long id) {  
                     Toast.makeText(getApplicationContext(),  
                               categoryList.get(position).get("category_id"),  
                               Toast.LENGTH_SHORT).show();  
              }  
           });  
           new AsyncCaller().execute();  
      }  

В общем как-то так . Это лишь небольшая часть информации которая посвящена работе с AsyncTask , но и ее будет достаточно для выполнения большинства тривиальных задач. 

суббота, 4 мая 2013 г.

Взаимодействие с API и как правильно разбирать JSON в Android

Вообще этот проект я делал для диплома , который еще кстати не защитил :) Так для начала опишу серверную часть .
Имеем БД MySQL с таблицей categories внутри , чтобы получить содержимое таблицы и закодировать в JSON выполним следующее

function getCategories(){
  if(isset($_GET['format']) && intval($_GET['num'])) { 
          $format = strtolower($_GET['format']); 
          $num = intval($_GET['num']); 
  mysql_query('SET NAMES \'UTF8\''); 
  $result = mysql_query('SELECT * FROM categories ORDER BY `category_id` DESC      LIMIT ' . $num) or die('MySQL Error.'); 
  if($format == 'json') { 
      $сategories = array(); 
  while($category = mysql_fetch_array($result, MYSQL_ASSOC)) { 
       $categories[] = array('category'=>$category); } 
       $output = json_encode($categories); echo $output; 
  }
 } 
}

if($_REQUEST['function']=='getCategories') 
   getCategories();



То есть чтобы сделать запрос и получить ответ в JSON в браузере делаем следующее :
http://superquiz.zz.mu/api.php?format=json&num=10&function=getCategories

Так теперь перейдем к клиентской части. Я делал общий класс API у которого будут методы для получения категорий , списка тестов , статистики и т.д . Опишу метод получения категорий.


public class API {    
     private HttpClient client; 
     private HttpGet httpGet; 
     private BufferedReader in; 
     private JSONObject mainJsonObject, innerJsonObject; 
     private ArrayList<Categories> categoriesArr = new ArrayList<Categories>(); 
     private static final String TAG_CATEGORY = "category"; 
     private static final String TAG_CATEGORY_ID = "category_id"; 
     private static final String TAG_CATEGORY_NAME = "category_name"; 
    
     public API() { 
        client = new DefaultHttpClient(); 
     } 
    
     public ArrayList getCategoryQuiz() { 
          httpGet = new HttpGet( "http://superquiz.zz.mu/api.php?  format=json&num=10&function=getCategories"); 
    
     try { 
           HttpResponse response = client.execute(httpGet); 
           in = new BufferedReader(new InputStreamReader(response.getEntity() .getContent())); 
           StringBuffer sb = new StringBuffer(""); 
           String line = ""; 
           while ((line = in.readLine()) != null) { 
                 sb.append(line + "\n"); 
           } 
           in.close(); 
           String result = sb.toString(); 
          
           JSONArray jsonMainArr = new JSONArray(result); 
           for (int i = 0; i < jsonMainArr.length(); i++) { 
           mainJsonObject = jsonMainArr.getJSONObject(i); 
           innerJsonObject = mainJsonObject.getJSONObject(TAG_CATEGORY); 
           int id = Integer.parseInt(innerJsonObject.getString(TAG_CATEGORY_ID));                             String name =  innerJsonObject.getString(TAG_CATEGORY_NAME); 
           categoriesArr.add(new Categories(id, name)); } 
     } catch (Exception e) { 
          e.printStackTrace(); 
     } return categoriesArr; 
 }

Теперь разберем что мы здесь наделали. Делаем GET запрос и получаем JSON ответ записывая его в StringBuilder. Затем формируем JSONArray из нашего ответа. После этого "растаскиваем" наш JSONArray на объекты и добавляем его в ArrayList из категорий. Кому не понятно как создать класс категорий выкладываю. 


public class Categories { 
   private int categoryId; 
   private String categoryName; 
  
   public Categories(int categoryId, String categoryName) { 
       this.categoryId = categoryId; 
       this.categoryName = categoryName; 
   } 

   public int getCategoryId() { 
       return categoryId; 
   } 
  
   public void setCategoryId(int categoryId) { 
       this.categoryId = categoryId; 
   } 
  
   public String getCategoryName() { 
      return categoryName; 
   } 
  
   public void setCategoryName(String categoryName) { 
      this.categoryName = categoryName; 
   } 
 }

Чтобы потом воспользоваться данным методом который мы написали делаем следующее.  API api = new API(); categoriesArr = api.getCateroiesQuiz();
Вроде все что хотел написал , за серверную часть не пинать :) В PHP особо никогда не углублялся , поэтому написал просто , без аутентификаций и т.д. В следующем уроке планирую разобрать AsyncTask и как отобразить полученные данные в ListView.

I`ll be back :)

Уже почти год ничего сюда не писал . За этот год скилл повысился , однако я так и не работал в офисе . Работал на удаленке. У данной работы есть много плюсов , кроме одного . Когда ты один разработчик под данную платформу , то часто бывает что не с кем посоветоваться как реализовать ту или иную фичу . Смотрел свои предыдущие посты в блоге , и писал что буду брать Galaxy S3 , но в итоге взял HTC One X . Еще ни разу не пожалел. Сейчас хочу написать урок по взаимодействию с простейшим самописным API на PHP с помощью Android.

вторник, 19 июня 2012 г.

Батл Samsung Galaxy S3 vs HTC One X

Хочу к концу лета взять себе новый телефон вот думаю между Samsung Galaxy S3 или HTC One X. Оба аппарата довольно интересные , но безусловно у каждого есть свои плюсы и минусы
Далее хочу представить обзор в котором сравниваются данные аппараты.



P.S Лично я наверно склонюсь все таки к Samsung Galaxy S3 , так как у него более емкая батарея , что для меня немаловажно , а у HTC как обычно больное место батарея :( . Хотя может к концу лета выйдет более интересный вариант и буду уже рассматривать его.

понедельник, 18 июня 2012 г.

Создание Splash


Необходимой часть приложения является Splash , который является заставкой в нашем приложении. Вот пример который можете использовать в своем приложении:

public class Splash extends Activity{

   private final int SPLASH_DISPLAY_LENGTH = 4000;  

   @Override  
   protected void onCreate(Bundle savedInstanceState) {  
         super.onCreate(savedInstanceState);  
         requestWindowFeature(Window.FEATURE_NO_TITLE);  
         setContentView(R.layout.splash);  
         
         new Handler().postDelayed(new Runnable() {  
            @Override
              public void run() {  
                 Intent mainIntent = new Intent(Splash.this,Main.class);                   Splash.this.startActivity(mainIntent);  
                 Splash.this.finish();  
              }  
         },SPLASH_DISPLAY_LENGTH);
   } 
}
 
Тут константа SPLASH_DISPLAY_LENGTH задается для определения времени показа данной Activity. Также мы указываем наш layout.

    Intent mainIntent = new Intent(Splash.this,Main.class);  
    Splash.this.startActivity(mainIntent);  
    Splash.this.finish(); 

Здесь переход от Splash к Main Activity. Работу с Intent мы разбирали в предыдущем уроке

P.S картинка Splash которая используется в данном уроке относится к первому приложению которое я написал на данной платформе, однако до сих пор не выложил в маркет :)  

воскресенье, 17 июня 2012 г.

Работа с Intent

Intent класс в Android который позволяет обмениваться данными между разными Activity внутри конкретного приложения , а также между приложениями в самой системе. Для того чтобы перейти от Activity1 к Activity2 необходимо выполнить следующее

Intent testIntent = new Intent(Activity1.this,Activity2.class);
startActivity(testIntent);


Часто нужно передать данные между Activity поэтому в данном классе предусмотрены методы putExtra (String name, Parcelable[] value) и много методов для извлечения данных в зависимости от типа передаваемых данных. Давайте рассмотрим следующий пример :

String login = "Bart";
testIntent.putExtra("login",login);


Здесь мы ложим в наш testIntent переменную типа String. Для того чтобы теперь Activity2 получило данные которые "лежат" в testIntent необходимо использовать метод getStringExtra

String username;
Intent testIntent = getIntent();
username = testIntent.getStringExtra("login");


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

Intent dialIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + "123456789"));
startActivity(dialIntent)

Также необходимо указать в AndroidManifest.xml permission для совершения данного действия

<uses-permission android:name="android.permission.CALL_PHONE" />

Для вызова стандартного активити для отправки смс:

Intent smsIntent = new Intent(Intent.ACTION_VIEW);
smsIntent.setType("vnd.android-dir/mms-sms");
smsIntent.putExtra("sms_body", "Some SMS text");
startActivity(smsIntent);


Для открытия ссылки в браузере :

Intent browseIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
startActivity(browseIntent);


При этом приложение предложит выбрать браузер в котором просматривать данную ссылки. Если это будет ссылка на YouTube то можно будет открыть через него. На этом наверно завершу знакомство Intent. Хочу сказать что это далеко не все возможности класса Intent. Более подробно поговорим в последующих уроках.