Электронная библиотека » Тимур Машнин » » онлайн чтение - страница 10


  • Текст добавлен: 16 октября 2020, 07:59


Автор книги: Тимур Машнин


Жанр: Компьютеры: прочее, Компьютеры


Возрастные ограничения: +12

сообщить о неприемлемом содержимом

Текущая страница: 10 (всего у книги 20 страниц)

Шрифт:
- 100% +

Activity + IntentService + ResultReceiver

Использование класса ResultReceiver еще один способ получения данных из сервиса для их обработки в методе onReceiveResult класса ResultReceiver.

Использование класса ResultReceiver аналогично использованию объекта PendingIntent.

В методе onCreate активности создается объект класса ResultReceiver, который передается в объект Intent, запускающий сервис.

В сервисе объект ResultReceiver извлекается, в него записываются данные, и он отсылается обратно в активность методом send. После этого системой вызывается метод onReceiveResult объекта ResultReceiver, в котором записанные в сервисе данные извлекаются.

Код активности будет иметь следующий вид:

package com. application;


import android. os. Handler;

import android.content.Intent;

import android. os. Bundle;

import android.support. v7.app. AppCompatActivity;

import android.view.Menu;

import android.view.MenuItem;

import android. widget. TextView;


public class MainActivity extends AppCompatActivity {


public static final String EXTRA_PARAM = "com.application.extra.PARAM»;

public final static String PARAM_RESULT = «Result»;

public final static int RESULT_CODE = 1;


public WebReceiver webReceiver;


@Override

protected void onCreate (Bundle savedInstanceState) {

super. onCreate (savedInstanceState);

setContentView(R.layout.activity_main);

webReceiver = new WebReceiver (new Handler ());


webReceiver.setReceiver (new WebReceiver.Receiver () {

@Override

public void onReceiveResult (int resultCode, Bundle resultData) {

if (resultCode == RESULT_CODE) {

String responseString=resultData.getString(MainActivity.PARAM_RESULT);

TextView textView = (TextView) findViewById(R.id.textView);

textView.setText (responseString);

}

}

});

Intent intent = new Intent(MainActivity.this, WebIntentService.class);

intent. putExtra (EXTRA_PARAM, "http://api.openweathermap.org/data/2.5/weather?q=London,uk");

intent. putExtra («receiver», webReceiver);

startService (intent);


}


public static class WebReceiver extends android.os.ResultReceiver {


public interface Receiver {

public void onReceiveResult (int resultCode, Bundle resultData);

}

private Receiver receiver;


public WebReceiver (android. os. Handler handler) {

super (handler);

}


public void setReceiver (Receiver receiver) {

this.receiver = receiver;

}


@Override

protected void onReceiveResult (int resultCode, Bundle resultData) {

if (receiver!= null) {

receiver. onReceiveResult (resultCode, resultData);

}

}

}


@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);

}

}

Здесь ResultReceiver представлен внутренним классом WebReceiver активности, экземпляр которого создается в методе onCreate. Затем экземпляр ResultReceiver передается в объект Intent, запускающий сервис.

Код IntentService при этом будет иметь следующий вид:

package com. application;


import android.app.IntentService;

import android.app.PendingIntent;

import android.content.Intent;

import android.content.Context;

import android.content.SharedPreferences;

import android.net.ConnectivityManager;

import android.net.NetworkInfo;

import android. os. Bundle;

import android.os.ResultReceiver;

import org. json. JSONObject;

import java.io.BufferedReader;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.net.HttpURLConnection;

import java.net. URL;

import java.text.SimpleDateFormat;

import java.util.Calendar;


public class WebIntentService extends IntentService {


public WebIntentService () {

super («WebIntentService»);

}


@Override

protected void onHandleIntent (Intent intent) {

if (intent!= null) {

final String param = intent.getStringExtra (MainActivity. EXTRA_PARAM);

ResultReceiver receiver = intent.getParcelableExtra («receiver»);

handleAction (param, receiver);

}

}


/**

* Handle action in the provided background thread with the provided

* parameters.

*/

private void handleAction (String param, ResultReceiver receiver) {

ConnectivityManager connMgr = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);

NetworkInfo networkInfo = connMgr.getActiveNetworkInfo ();

if (networkInfo!= null && networkInfo.isConnected () && networkInfo.isAvailable ()) {

InputStream is = null;

URL url = null;

try {

url = new URL (param);

HttpURLConnection conn = (HttpURLConnection) url. openConnection ();

conn.setReadTimeout (10000 /* milliseconds */);

conn.setConnectTimeout (15000 /* milliseconds */);

conn.setRequestMethod («GET»);

conn.setDoInput (true);

conn.connect ();

int response = conn.getResponseCode ();

is = conn.getInputStream ();

// Convert the InputStream into a string

BufferedReader br = null;

StringBuilder sb = new StringBuilder ();

String line;

br = new BufferedReader (new InputStreamReader (is));

while ((line = br.readLine ())!= null) {

sb. append (line);

}

String contentAsString=sb.toString ();

is.close ();

conn. disconnect ();


JSONObject reader = new JSONObject (contentAsString);

JSONObject main = reader.getJSONObject («main»);

String temp = main.getString («temp»);

Calendar c = Calendar.getInstance ();

SimpleDateFormat df = new SimpleDateFormat («yyyy-MM-dd HH: mm: ss»);

String formattedDate = df.format(c.getTime ());

String result=formattedDate + " temp: " +temp;


Bundle bundle = new Bundle ();

bundle.putString(MainActivity.PARAM_RESULT, result);

receiver.send(MainActivity.RESULT_CODE, bundle);


Context context = this;

SharedPreferences sharedPref = context.getSharedPreferences("com.application.PREFERENCE_FILE_KEY",Context.MODE_PRIVATE);

SharedPreferences. Editor editor = sharedPref. edit ();

editor. putString («temp», temp);

editor. putString («date», formattedDate);

editor.commit ();

} catch (Exception e) {

e.printStackTrace ();

}

} else {

Context context = this;

SharedPreferences sharedPref = context.getSharedPreferences("com.application.PREFERENCE_FILE_KEY», Context.MODE_PRIVATE);

String date=sharedPref.getString («date», «unknown date»);

String temp=sharedPref.getString («temp», «unknown temp»);

String result=date + " temp: " +temp;

Bundle bundle = new Bundle ();

bundle.putString(MainActivity.PARAM_RESULT, result);

receiver.send(MainActivity.RESULT_CODE, bundle);

}

}

}

Здесь, при запуске сервиса, проверяется наличие соединения с Интернетом, затем получаются данные в JSON-формате по указанному URL адресу.

Далее необходимые данные извлекаются и передаются в объект Bundle в виде строки.

Объект Bundle передается в объект ResultReceiver, который отправляется обратно в создавшую его активность методом send.

Извлеченные данные записываются в настройки SharedPreferences.

Если же соединение с Интернетом отсутствует, тогда данные извлекаются из настроек SharedPreferences и передаются в объект Bundle в виде строки.

Для отключения соединения с Интернетом в эмуляторе можно нажать F8.

Activity + Service + Binder

При создании Bound-сервиса, сервис запускается из активности методом bindService. При этом в сервисе вызывается метод onBind, возвращающий объект IBinder, который обеспечивает доступ к экземпляру сервиса и соответственно методам сервиса.

Методы сервиса при том выполняются в основном потоке.

Если же требуется выполнение задачи в фоновом потоке и возврат результата из него обратно в активность, можно передать сервису объект Handler для отправки и получения данных из фонового потока.

Код Bound-сервиса будет следующим:

package com. application;


import android.app.Service;

import android.content.Context;

import android.content.Intent;

import android.content.SharedPreferences;

import android.net.ConnectivityManager;

import android.net.NetworkInfo;

import android.os.Binder;

import android. os. Bundle;

import android. os. IBinder;

import android. os. Handler;

import android.os.Message;

import org. json. JSONObject;

import java.io.BufferedReader;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.net.HttpURLConnection;

import java.net. URL;

import java.text.SimpleDateFormat;

import java.util.Calendar;


public class WebBoundService extends Service {


private final IBinder binder = new LocalBinder ();


public WebBoundService () {

}


@Override

public IBinder onBind (Intent intent) {

return binder;

}


public class LocalBinder extends Binder {

WebBoundService getService () {

return WebBoundService.this;

}

}


public void getResult (String str, Handler hlr) {

final Handler handler=hlr;

final String urlString=str;

final Context context = this;


new Thread (new Runnable () {

public void run () {

try {

ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

NetworkInfo networkInfo = connMgr.getActiveNetworkInfo ();

if (networkInfo!= null && networkInfo.isConnected () && networkInfo.isAvailable ()) {

InputStream is = null;

URL url = null;

url = new URL (urlString);

HttpURLConnection conn = (HttpURLConnection) url. openConnection ();

conn.setReadTimeout (10000 /* milliseconds */);

conn.setConnectTimeout (15000 /* milliseconds */);

conn.setRequestMethod («GET»);

conn.setDoInput (true);

conn.connect ();

is = conn.getInputStream ();

// Convert the InputStream into a string

BufferedReader br = null;

StringBuilder sb = new StringBuilder ();

String line;

br = new BufferedReader (new InputStreamReader (is));

while ((line = br.readLine ())!= null) {

sb. append (line);

}

String contentAsString = sb.toString ();

is.close ();

conn. disconnect ();


JSONObject reader = new JSONObject (contentAsString);

JSONObject main = reader.getJSONObject («main»);

String temp = main.getString («temp»);

Calendar c = Calendar.getInstance ();

SimpleDateFormat df = new SimpleDateFormat («yyyy-MM-dd HH: mm: ss»);

String formattedDate = df.format(c.getTime ());

String msg = formattedDate + " temp: " + temp;


Message msgObj = handler. obtainMessage ();

Bundle b = new Bundle ();

b. putString («message», msg);

msgObj.setData (b);

handler.sendMessage (msgObj);


SharedPreferences sharedPref = context.getSharedPreferences("com.application.PREFERENCE_FILE_KEY», Context.MODE_PRIVATE);

SharedPreferences. Editor editor = sharedPref. edit ();

editor. putString («temp», temp);

editor. putString («date», formattedDate);

editor.commit ();


} else {

SharedPreferences sharedPref = context.getSharedPreferences("com.application.PREFERENCE_FILE_KEY», Context.MODE_PRIVATE);

String date = sharedPref.getString («date», «unknown date»);

String temp = sharedPref.getString («temp», «unknown temp»);

String msg=date + " temp: " +temp;


Message msgObj = handler. obtainMessage ();

Bundle b = new Bundle ();

b. putString («message», msg);

msgObj.setData (b);

handler.sendMessage (msgObj);

}

} catch (Exception e) {

e.printStackTrace ();

}

}

}).start ();

}

}

Здесь, в метод сервиса передается URL-адрес для получения данных и объект Handler для отправки полученных данных.

В фоновом потоке метода проверяется наличие соединения с Интернетом, затем получаются данные в JSON-формате по указанному URL адресу.

Далее необходимые данные извлекаются и передаются в объект Handler в виде строки.

Извлеченные данные записываются в настройки SharedPreferences.

Если же соединение с Интернетом отсутствует, тогда данные извлекаются из настроек SharedPreferences и передаются в объект Handler.

Код активности, запускающей сервис, будет следующим:

package com. application;


import android.content.ComponentName;

import android.content.Intent;

import android.content.ServiceConnection;

import android. os. Bundle;

import android. os. Handler;

import android. os. IBinder;

import android.os.Message;

import android.support. v7.app. AppCompatActivity;

import android.view.Menu;

import android.view.MenuItem;

import android. widget. TextView;


public class MainActivity extends AppCompatActivity {


private ServiceConnection sConn;

private boolean bound = false;

private WebBoundService service;


@Override

protected void onCreate (Bundle savedInstanceState) {

super. onCreate (savedInstanceState);

setContentView(R.layout.activity_main);

sConn = new ServiceConnection () {

public void onServiceConnected (ComponentName name, IBinder binder) {

WebBoundService. LocalBinder localBinder = (WebBoundService. LocalBinder) binder;

service = localBinder.getService ();

Handler handler = new Handler () {

@Override

public void handleMessage (Message msg) {

super. handleMessage (msg);

Bundle b = msg.getData ();

String responseString=b.getString («message»);

TextView textView = (TextView) findViewById(R.id.textView);

textView.setText (responseString);

}

};


http://api.openweathermap.org/data/2.5/weather?q=London,uk",tResult (»service.ge handler);

bound = true;

}

public void onServiceDisconnected (ComponentName name) {

bound = false;

}

};

Intent intent = new Intent(MainActivity.this, WebBoundService.class);

bindService (intent, sConn, this.BIND_AUTO_CREATE);


}


@Override

protected void onDestroy () {

super. onDestroy ();

if (bound) {

unbindService (sConn);

bound = false;

}

}


@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);

}

}

Здесь в методе handleMessage объекта Handler, отправленные сервисом данные извлекаются и отображаются.

Код манифеста AndroidManifest. xml:

<?xml version=«1.0» encoding=«utf-8»? >

<manifest xmlns: android="http://schemas.android.com/apk/res/android"

package="com.tmsoftstudio. application»>


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

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


<application

android: allowBackup=«true»

android: icon="@mipmap/ic_launcher»

android: label="@string/app_name»

android: theme="@style/AppTheme»>

<activity

android:name=".MainActivity»

android: label="@string/app_name»>

<intent-filter>

<action android:name="android.intent.action.MAIN» />

<category android:name="android.intent.category.LAUNCHER» />

</intent-filter>

</activity>


<service

android: name=». WebBoundService»

android: enabled=«true»

android: exported=«true»>

</service>

</application>


</manifest>

Activity + Service + Messenger

Класс Messenger обеспечивает еще один способ обмена данными между активностью и Bound-сервисом, только при этом находящимися в разных процессах.

К объекту Messenger прикрепляется обработчик Handler, отвечающий за обработку поступающих сообщений.

В классе активности для отправки сообщения сервису, в методе обратного вызова onServiceConnected создается объект Messenger на основе объекта IBinder, передаваемого из сервиса.

После того создается объект Message, в который записываются данные.

В объект Message записывается объект Messenger, к которому прикреплен обработчик Handler, отвечающий за обработку сообщений от сервиса.

Объект Message отправляется сервису с помощью объекта Messenger, созданного на основе объекта IBinder.

В сервисе вызывается метод handleMessage обработчика Handler, связанного с объектом Messenger, из которого получается объект IBinder, отправляемый активности.

В методе handleMessage из сообщения извлекается объект Messenger, с помощью которого данные отправляются обратно активности.

Код активности будет следующим:

package com. application;


import android.content.ComponentName;

import android.content.Intent;

import android.content.ServiceConnection;

import android. os. Bundle;

import android. os. Handler;

import android. os. IBinder;

import android.os.Message;

import android.os.Messenger;

import android.os.RemoteException;

import android.support. v7.app. AppCompatActivity;

import android.view.Menu;

import android.view.MenuItem;

import android. widget. TextView;


public class MainActivity extends AppCompatActivity {


private ServiceConnection sConn;

private boolean bound = false;

private Messenger mMessenger;


@Override

protected void onCreate (Bundle savedInstanceState) {

super. onCreate (savedInstanceState);

setContentView(R.layout.activity_main);

sConn = new ServiceConnection () {

public void onServiceConnected (ComponentName name, IBinder binder) {

mMessenger = new Messenger (binder);

Message msg = Message. obtain (null, WebBoundService.MSG_TO_SERVICE);

msg.replyTo = new Messenger (new ActivityHandler ());

Bundle bundle = new Bundle ();

bundle. putString («url», "http://api.openweathermap.org/data/2.5/weather?q=London,uk");

msg.setData (bundle);

try {

mMessenger.send (msg);

} catch (RemoteException e) {

e.printStackTrace ();

}


bound = true;

}


public void onServiceDisconnected (ComponentName name) {

mMessenger = null;

bound = false;

}

};

Intent intent = new Intent(MainActivity.this, WebBoundService.class);

bindService (intent, sConn, this.BIND_AUTO_CREATE);

}


class ActivityHandler extends Handler {

@Override

public void handleMessage (Message msg) {

switch (msg. what) {

case WebBoundService.MSG_FROM_SERVICE: {

Bundle b = msg.getData ();

String responseString=b.getString («respData»);

TextView textView = (TextView) findViewById(R.id.textView);

textView.setText (responseString);

}

break;

default:

super. handleMessage (msg);

}

}

}


@Override

protected void onDestroy () {

super. onDestroy ();

if (bound) {

unbindService (sConn);

bound = false;

}

}


@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);

}

}

Код Bound-сервиса:

package com. application;


import android.app.Service;

import android.content.Context;

import android.content.Intent;

import android.content.SharedPreferences;

import android.net.ConnectivityManager;

import android.net.NetworkInfo;

import android. os. Bundle;

import android. os. IBinder;

import android. os. Handler;

import android.os.Message;

import android.os.Messenger;

import org. json. JSONObject;

import java.io.BufferedReader;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.net.HttpURLConnection;

import java.net. URL;

import java.text.SimpleDateFormat;

import java.util.Calendar;


public class WebBoundService extends Service {


final Context context = this;

static final int MSG_TO_SERVICE = 1;

static final int MSG_FROM_SERVICE = 2;


public WebBoundService () {

}


Messenger mMessenger = new Messenger (new ServiceHandler ());


// Incoming messages Handler

class ServiceHandler extends Handler {

@Override

public void handleMessage (Message msg) {

switch (msg. what) {

case MSG_TO_SERVICE: {

final Messenger messenger=msg.replyTo;

Bundle bundle = msg.getData ();

final String urlString = (String) bundle.get («url»);

new Thread (new Runnable () {

public void run () {

try {

ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

NetworkInfo networkInfo = connMgr.getActiveNetworkInfo ();

if (networkInfo!= null && networkInfo.isConnected () && networkInfo.isAvailable ()) {

InputStream is = null;

URL url = null;

url = new URL (urlString);

HttpURLConnection conn = (HttpURLConnection) url. openConnection ();

conn.setReadTimeout (10000 /* milliseconds */);

conn.setConnectTimeout (15000 /* milliseconds */);

conn.setRequestMethod («GET»);

conn.setDoInput (true);

conn.connect ();

is = conn.getInputStream ();

// Convert the InputStream into a string

BufferedReader br = null;

StringBuilder sb = new StringBuilder ();

String line;

br = new BufferedReader (new InputStreamReader (is));

while ((line = br.readLine ())!= null) {

sb. append (line);

}

String contentAsString = sb.toString ();

is.close ();

conn. disconnect ();

JSONObject reader = new JSONObject (contentAsString);

JSONObject main = reader.getJSONObject («main»);

String temp = main.getString («temp»);

Calendar c = Calendar.getInstance ();

SimpleDateFormat df = new SimpleDateFormat («yyyy-MM-dd HH: mm: ss»);

String formattedDate = df.format(c.getTime ());

String data = formattedDate + " temp: " + temp;

Message resp = Message. obtain (null, MSG_FROM_SERVICE);

Bundle bResp = new Bundle ();

bResp. putString («respData», data);

resp.setData (bResp);

messenger.send (resp);

SharedPreferences sharedPref = context.getSharedPreferences("com.application.PREFERENCE_FILE_KEY», Context.MODE_PRIVATE);

SharedPreferences. Editor editor = sharedPref. edit ();

editor. putString («temp», temp);

editor. putString («date», formattedDate);

editor.commit ();

} else {

SharedPreferences sharedPref = context.getSharedPreferences("com.application.PREFERENCE_FILE_KEY», Context.MODE_PRIVATE);

String date = sharedPref.getString («date», «unknown date»);

String temp = sharedPref.getString («temp», «unknown temp»);

String data = date + " temp: " + temp;

Message resp = Message. obtain (null, MSG_FROM_SERVICE);

Bundle bResp = new Bundle ();

bResp. putString («respData», data);

resp.setData (bResp);

messenger.send (resp);

}

} catch (Exception e) {

e.printStackTrace ();

}

}

}).start ();

}

break;

default:

super. handleMessage (msg);

}

}

}


@Override

public IBinder onBind (Intent intent) {

return mMessenger.getBinder ();

}

}

Код манифеста:

<?xml version=«1.0» encoding=«utf-8»? >

<manifest xmlns: android="http://schemas.android.com/apk/res/android"

package="com.tmsoftstudio. application»>


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

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


<application

android: allowBackup=«true»

android: icon="@mipmap/ic_launcher»

android: label="@string/app_name»

android: theme="@style/AppTheme»>

<activity

android:name=".MainActivity»

android: label="@string/app_name»>

<intent-filter>

<action android:name="android.intent.action.MAIN» />

<category android:name="android.intent.category.LAUNCHER» />

</intent-filter>

</activity>


<service

android: name=». WebBoundService»

android: enabled=«true»

android: exported=«true»

android: process=":webservice»

>

</service>

</application>


</manifest>

Здесь атрибут android: process=":webservice» указывает на запуск сервиса в отдельном процессе.


Страницы книги >> Предыдущая | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | Следующая
  • 0 Оценок: 0

Правообладателям!

Это произведение, предположительно, находится в статусе 'public domain'. Если это не так и размещение материала нарушает чьи-либо права, то сообщите нам об этом.


Популярные книги за неделю


Рекомендации