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


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


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


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


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

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

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

Шрифт:
- 100% +

});


$ (» <div/>», {

«class»: «list-group»,

html: items.join (»»)

}).appendTo (".col_3»);


$ (".btn-map» ).click (function () {

var route = $(this).attr (’data-route’).split (»,»);

var title = $(this).attr (’data-title’);

for (var i = 0; i <route. length; i++) {


var latLng =new google.maps.LatLng(route[i+1].replace («lat:»,»»), route[i].replace («lng:»,»»));

var marker = new google.maps.Marker ({

position: latLng,

title: title,

map: map

});

map.setCenter (latLng);

i=i+1;

}


});


$ (".btn-mapTrack» ).click (function () {

var route = $(this).attr (’data-route’).split (»,»);


var title = $(this).attr (’data-title’).split (»,»);

var j=0;

for (var i = 0; i <route. length; i++) {


var latLng =new google.maps.LatLng (route [i], route [i+1]);

var marker = new google.maps.Marker ({

position: latLng,

title: title [j],

map: map

});

map.setCenter (latLng);

i=i+1;

j=j+1;

}


});


$ (".btn-state» ).click (function () {

var name = $(this).attr (’data-name’);


var url = 'http://buisness-control.appspot.com/puttaskstate/?callback=?';


$.ajax ({

type: «GET»,

url: url,

data: {

state:’old’,

name: name

},

async: false,

jsonpCallback: ’putTaskState’,

contentType: ’application/json’,

dataType: ’jsonp’,

success: function (json) {

location.reload ();

}

});


});


$ (".btn-del-task» ).click (function () {

var name = $(this).attr (’data-name’);


var url = 'http://buisness-control.appspot.com/deletetask/?callback=?';


$.ajax ({

type: «GET»,

url: url,

data: {

name: name

},

async: false,

jsonpCallback: ’deleteTask’,

contentType: ’application/json’,

dataType: ’jsonp’,

success: function (json) {

location.reload ();

}

});


});

}

});

</script>


</div>

<div class=«clearfix»> </div>

</div>


<div class=«copy»>

<p> Copyright &copy; 2015 TM SoftStudio </p>

</div>

</div>

</div>

<! – /#page-wrapper – >

</div>

<! – /#wrapper – >

<! – Bootstrap Core JavaScript – >

<script src=«js/bootstrap. min. js»> </script>

</body>

</html>



Страница «Архив Заданий» позволяет просмотреть задания со статусом «old», включая трекинги и отчеты о его выполнении, присланные сотрудниками.

<!DOCTYPE HTML>

<html>

<head>

<title> Business Control </title>

<meta name=«viewport» content=«width=device-width, initial-scale=1»>

<meta http-equiv=«Content-Type» content=«text/html; charset=utf-8» />

<script type=«application/x-javascript»> addEventListener («load», function () {setTimeout (hideURLbar, 0);}, false); function hideURLbar () {window.scrollTo (0,1);} </script>

<! – Bootstrap Core CSS – >

<link href=«css/bootstrap. min. css» rel=’stylesheet’ type=’text/css’ />

<! – Custom CSS – >

<link href=«css/style. css» rel=’stylesheet’ type=’text/css’ />

<link href=«css/font-awesome. css» rel=«stylesheet»>

<! – jQuery – >

<script src=«js/jquery. min. js»> </script>

<! – – webfonts – ->

<link href='//fonts.googleapis.com/css? family=Roboto:400,100,300,500,700,900» rel=’stylesheet’ type=’text/css’>

<! – Nav CSS – >

<link href=«css/custom. css» rel=«stylesheet»>

<! – Metis Menu Plugin JavaScript – >

<script src=«js/metisMenu. min. js»> </script>

<script src=«js/custom. js»> </script>

<! – Calendar – >

<script type=«text/javascript» src=«js/bootstrap-datepicker. js»> </script>

<script type=«text/javascript» src="js/bootstrap-datepicker.ru.js» charset=«UTF-8»> </script>

<link href=«css/datepicker. css» rel=«stylesheet»>

<! – Editor – >

<script src="//cdn.tinymce.com/4/tinymce. min. js»> </script>

<script>tinymce.init ({selector: «#editor’}); </script>


</head>

<body>

<div id=«wrapper»>

<! – Navigation – >

<nav class=«top1 navbar navbar-default navbar-static-top» role=«navigation» style=«margin-bottom: 0»>

<div class=«navbar-header»>

<button type=«button» class=«navbar-toggle» data-toggle=«collapse» data-target=".navbar-collapse»>

<span class=«sr-only»> Toggle navigation </span>

<span class=«icon-bar»> </span>

<span class=«icon-bar»> </span>

<span class=«icon-bar»> </span>

</button>

<a class=«navbar-brand» href=«#»> Архив Заданий </a>

</div>

<! – /.navbar-header – >


<div class=«navbar-default sidebar» role=«navigation»>

<div class=«sidebar-nav navbar-collapse»>

<img src="img/logo.png» />

<ul class=«nav» id=«side-menu»>

<li>

<a href="index.html»> <i class=«fa fa-dashboard fa-fw nav_icon»> </i> Dashboard </a>

</li>

<li>

<a href=«#»> <i class=«fa fa-users»> </i> Сотрудники <span class=«fa arrow»> </span> </a>

<ul class=«nav nav-second-level»>

<li>

<a href="groups-list.html»> Группы </a>

</li>

<li>

<a href="users-list.html»> Общий список </a>

</li>

</ul>

<! – /.nav-second-level – >

</li>

<li>

<a href=«#»> <i class=«fa fa-truck»> </i> Маршрут <span class=«fa arrow»> </span> </a>

<ul class=«nav nav-second-level»>

<li>

<a href="route.html»> Выбрать маршрут </a>

</li>

<li>

<a href=«#»> Маршруты <span class=«fa arrow»> </span> </a>

<ul class=«nav nav-second-level»>

<li>

<a href="new-routes.html»> Новые </a>

</li>

<li>

<a href="old-routes.html»> Архив </a>

</li>

</ul>

</li>

</ul>

<! – /.nav-second-level – >

</li>

<li>

<a href=«#»> <i class=«fa fa-file»> </i> Задание <span class=«fa arrow»> </span> </a>

<ul class=«nav nav-second-level»>

<li>

<a href="task.html»> Создать задание </a>

</li>

<li>

<a href=«#»> Задания <span class=«fa arrow»> </span> </a>

<ul class=«nav nav-second-level»>

<li>

<a href="new-tasks.html»> Новые </a>

</li>

<li>

<a href="old-tasks.html»> Архив </a>

</li>

</ul>

</li>

</ul>

<! – /.nav-second-level – >

</li>

<li>

<a href=«#»> <i class=«fa fa-file-text»> </i> Текст задания <span class=«fa arrow»> </span> </a>

<ul class=«nav nav-second-level»>

<li>

<a href="desc.html»> Создать описание </a>

</li>

<li>

<a href=«#»> Описания <span class=«fa arrow»> </span> </a>

<ul class=«nav nav-second-level»>

<li>

<a href="new-descs.html»> Новые </a>

</li>

<li>

<a href="old-descs.html»> Архив </a>

</li>

</ul>

</li>

</ul>

<! – /.nav-second-level – >

</li>

<li>

<a href=«#»> <i class=«fa fa-android»> </i> Мобильные приложения </a>


</li>


</ul>

</div>

<! – /.sidebar-collapse – >

</div>

<! – /.navbar-static-side – >

</nav>

<div id=«page-wrapper»>

<div class=«graphs»>

<div class = «col_3»>


<div class=«clearfix»> </div>

</div>


<div class=«col_1»>

<div class=«col-md-6»>

<div class=«refresh» style=«cursor: pointer; margin-left:22%"> <i class=«fa fa-refresh»> </i> </div>

<div class=«datepicker»> </div>


<script type=«text/javascript»>

var dp = $ (». datepicker’).datepicker ({

language: «ru-RU»

});

$ (".refresh» ).click (function () {

dp. datepicker (’update’);

});

dp. on (’changeDate’, function (ev) {


});

</script>


</div>

<div class=«clearfix»> </div>

</div>


<div class=«span_11»>

<div class=«col-md-12»>

<div id=«map» style=«height:500px;"> </div>


<script>

var map;

function initMap () {

map = new google.maps.Map(document.getElementById (’map’), {

zoom: 15

});

var infoWindow = new google.maps.InfoWindow ({map: map});


if (navigator.geolocation) {

navigator.geolocation.getCurrentPosition (function (position) {

var pos = {

lat: position.coords.latitude,

lng: position.coords. longitude

};

infoWindow.setPosition (pos);

map.setCenter (pos);

}, function () {

handleLocationError (true, infoWindow, map.getCenter ());

});

} else {

// Browser doesn’t support Geolocation

handleLocationError (false, infoWindow, map.getCenter ());

}


}


function handleLocationError (browserHasGeolocation, infoWindow, pos) {

infoWindow.setPosition (pos);

infoWindow.setContent (browserHasGeolocation?

«Error: The Geolocation service failed.» :

«Error: Your browser doesn’t support geolocation.»);

}


</script>


<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCb9Iir38HyF_E3_hmf3mHHum_tJbgvjXs&callback=initMap"

async defer> </script>


<script>

var url = 'http://buisness-control.appspot.com/tasks/?callback=?';


$.ajax ({

type: «GET»,

url: url,

data: {

state:’old’

},

async: true,

jsonpCallback: ’getNewTasks’,

contentType: «application/json»,

dataType: ’jsonp’,

success: function (json) {

var items = [];

$.each (json. tasks, function (key, val) {


var track=«»;

var trackRoute=«»;

var trackAccount=«»;


if (val.track===undefined) {

track=«»;

trackRoute=«»;

trackAccount=«»;

} else {

$.each (val.track, function (key, subval) {

track=track+"n"+subval.account+" Дата: "+subval. date+" Координаты: "+subval.lat+" "+subval. lng;

if(trackRoute=="")trackRoute=subval.lat+»,»+subval. lng;

trackRoute=trackRoute+","+subval.lat+»,»+subval. lng;

if(trackAccount=="")trackAccount=subval.account;

trackAccount=trackAccount+","+subval.account;

});

}


var subitems= [];

if (val.reports!==undefined) {

$.each (val.reports, function (key, subval) {

var reportAccount=subval.account;

var reportText=subval.report;

var reportPhotos=subval.photos;


var subsubitems= [];

if (reportPhotos!==undefined) {

$.each (reportPhotos, function (key, subsubval) {

var url=subsubval.servingUrl;

var key=subsubval. blobKey;

subsubitems. push (» <br/> <image class=’img-responsive’ src="+url+" alt=«»> <br/>»);

});

}


subitems. push (» <div class=’row’> <div class=’col-sm-12»> <br/> <p class=’label label-success’> Отчет: </p> <p>"+reportAccount+"</p> <p> <textarea class='form-control'>"+reportText+"</textarea></p><p>"+subsubitems.join (»») +"</p> </div> </div>»);


});

}


items. push (» <br/> <a href=«#» class=’list-group-item’ data-toggle=’collapse’ data-target=«#» + val.name.replace (/ [.,:,/,, (,),=,?, -,@] /g,»») + «»>" + val.name + «</a> <div id=„“ + val.name.replace (/ [.,:,/,, (,),=,?, -,@] /g,»») + «» class=’collapse’> <div class=’col-sm-12»>»+val. date+"</div> <div class=’col-sm-12»> <br/> <p class=’label label-success’> Описание: </p> <textarea class='form-control'>"+JSON.stringify(val.descs).replace (/ [" []] /g,»») +"</textarea> </div> <div class=’col-sm-12»> <br/> <p class=’label label-success’> Сотрудники: </p> <textarea class='form-control'>"+JSON.stringify(val.users).replace (/ [" []] /g,»») +"</textarea> </div> <div class=’col-sm-12»> <br/> <p class=’label label-success’> Маршрут: </p> <textarea class='form-control'>"+JSON.stringify(val.routes).replace (/ [" [] {}] /g,»») +"</textarea> </div> <div class=’row’> <div class=’col-sm-4»> <button type=’button’ class=’btn btn-primary btn-map’ data-title=«»+val. date+«» data-route='"+JSON.stringify(val.routes).replace (/ [" [] {}] /g,»») +«»> Показать на карте </button> </div> </div> <br/> <div class=’col-sm-12»> <br/> <p class=’label label-success’> Отслеживание: </p> <textarea class=’form-control’>"+track+"</textarea> </div> <br/> <div class=’row’> <div class=’col-sm-4»> <button type=’button’ class=’btn btn-primary btn-mapTrack’ data-title=«»+trackAccount+«» data-route=«»+trackRoute+«»> Показать на карте</button></div></div><br/>"+subitems.join (»») +"<br/> <div class=’row’> <div class=’col-sm-4»> <button type=’button’ class=’btn btn-primary btn-state’ data-name='"+val.name+«»> Новое задание </button> </div> <div class=’col-sm-4»> <button type=’button’ class=’btn btn-danger btn-del’ data-name='"+val.name+«»> Удалить </button> </div> </div> </div>»);


});


$ (» <div/>», {

«class»: «list-group»,

html: items.join (»»)

}).appendTo (".col_3»);


$ (".btn-mapTrack» ).click (function () {

var route = $(this).attr (’data-route’).split (»,»);


var title = $(this).attr (’data-title’).split (»,»);

var j=0;

for (var i = 0; i <route. length; i++) {


var latLng =new google.maps.LatLng (route [i], route [i+1]);

var marker = new google.maps.Marker ({

position: latLng,

title: title [j],

map: map

});

map.setCenter (latLng);

i=i+1;

j=j+1;

}


});


$ (".btn-map» ).click (function () {

var route = $(this).attr (’data-route’).split (»,»);

var date = $(this).attr (’data-date’);

for (var i = 0; i <route. length; i++) {


var latLng =new google.maps.LatLng(route[i+1].replace («lat:»,»»), route[i].replace («lng:»,»»));

var marker = new google.maps.Marker ({

position: latLng,

title: date,

map: map

});

map.setCenter (latLng);

i=i+1;

}


});


$ (".btn-state» ).click (function () {

var name = $(this).attr (’data-name’);


var url = 'http://buisness-control.appspot.com/puttaskstate/?callback=?';


$.ajax ({

type: «GET»,

url: url,

data: {

state:’new’,

name: name

},

async: false,

jsonpCallback: ’putTaskState’,

contentType: ’application/json’,

dataType: ’jsonp’,

success: function (json) {

location.reload ();

}

});


});


$ (".btn-del» ).click (function () {

var name = $(this).attr (’data-name’);


var url = 'http://buisness-control.appspot.com/deletetask/?callback=?';


$.ajax ({

type: «GET»,

url: url,

data: {

name: name

},

async: false,

jsonpCallback: ’deleteTask’,

contentType: ’application/json’,

dataType: ’jsonp’,

success: function (json) {

location.reload ();

}

});


});

}

});

</script>


</div>

<div class=«clearfix»> </div>

</div>


<div class=«copy»>

<p> Copyright &copy; 2015 TM SoftStudio </p>

</div>

</div>

</div>

<! – /#page-wrapper – >

</div>

<! – /#wrapper – >

<! – Bootstrap Core JavaScript – >

<script src=«js/bootstrap. min. js»> </script>

</body>

</html>


Использование Material Design в Eclipse

При создании Android проектов, работающих с Material Design, в среде Eclipse, в проект необходимо добавить библиотеки andoid design support и recyclerview.

Для добавления библиотеки andoid design support в среде Eclipse импортируем с сохранением папку android-sdksextrasandroidsupportdesign.



В свойствах библиотеки в разделе Android в Project Build Target отметим последнюю версию API и добавим зависимость от библиотеки appcompat_v7.



Для добавления библиотеки recyclerview в среде Eclipse импортируем с сохранением папку android-sdksextrasandroidsupportv7recyclerview.

В свойствах библиотеки в разделе Android в Project Build Target отметим последнюю версию API и добавим зависимость от библиотеки appcompat_v7.

Создадим проект Android приложения на основе шаблона Blank Activity.

В свойствах проекта в разделе Android в Project Build Target добавим зависимость от библиотек appcompat_v7, andoid design support и recyclerview.

В Android Studio создадим проект на основе шаблона Navigation Drawer Activity.

Скопируем содержимое папок appsrcmain Android Studio проекта в Eclipse проект.

Push уведомления

Android + Google Cloud Messaging (GCM)

В консоли Google Cloud Platform создадим проект.

Включим Google Cloud Messaging API для этого проекта.

Создадим server API key для Google Cloud Messaging.

В среде Eclipse создадим проект Android приложения, в который добавим библиотеку Google Play Services https://developers.google.com/android/guides/setup#add_google_play_services_to_your_project.

В файл манифеста добавим разрешения.

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

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

<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE» />

<permission android:name="com.tmsoftstudio.breakingnews. C2D_MESSAGE»

android: protectionLevel=«signature» />

<uses-permission android:name="com.tmsoftstudio.breakingnews. C2D_MESSAGE» />

Для регистрации Android приложения в сервисе GCM в класс активности добавим код:

private String regid;

private String PROJECT_NUMBER = «1222…»;

private SharedPreferences mSettings;

private Context context;

final int REQUEST_CODE = 0;

public final static int RESULT_CODE = 1;

public final static String PARAM_PINTENT = «PendingIntent»;

public final static String PARAM_RESULT = «Result»;


@Override

protected void onCreate (Bundle savedInstanceState) {

super. onCreate (savedInstanceState);

setContentView(R.layout.activity_main);

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

setSupportActionBar (toolbar);


context = this;

mSettings = getSharedPreferences («APP_PREFERENCES», Context.MODE_PRIVATE);


if (!mSettings.contains («SENDER_ID»)) {

SharedPreferences. Editor editor = mSettings. edit ();

editor. putString («SENDER_ID», PROJECT_NUMBER);

editor.commit ();

}


if (!mSettings.contains («REG_ID»)) {

PendingIntent pi;

pi = createPendingResult (REQUEST_CODE, new Intent (), 0);

Intent intent = new Intent (context, InstanceIDIntentService.class);

intent. putExtra (PARAM_PINTENT, pi);

startService (intent);

}


FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);

fab.setOnClickListener (new View. OnClickListener () {

@Override

public void onClick (View view) {

Snackbar.make (view, «Replace with your own action», Snackbar. LENGTH_LONG)

.setAction («Action», null).show ();

}

});


DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);

ActionBarDrawerToggle toggle = new ActionBarDrawerToggle (

this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);

drawer.addDrawerListener (toggle);

toggle.syncState ();


NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);

navigationView.setNavigationItemSelectedListener (this);

}


@Override

protected void onActivityResult (int requestCode, int resultCode, Intent data) {

if (requestCode == REQUEST_CODE) {

if (resultCode == RESULT_CODE) {

regid=data.getStringExtra(MainActivity.PARAM_RESULT);

View view = (View) findViewById(R.id.content);

Snackbar.make (view, regid, Snackbar.LENGTH_LONG).setAction («Action», null).show ();

SharedPreferences. Editor editor = mSettings. edit ();

editor. putString («REG_ID», regid);

editor.commit ();


}

}

}

Здесь PROJECT_NUMBER это номер созданного проекта в Google Cloud Platform.

Объект PendingIntent создается методом createPendingResult активности для получения уникального регистрационного токена из сервиса регистрации для его сохранения в методе обратного вызова onActivityResult активности.

Создадим сервис регистрации.

<service android:name=".InstanceIDIntentService» android: exported=«false»/>

import java.io.BufferedWriter;

import java.io.OutputStream;

import java.io.OutputStreamWriter;

import java.net.HttpURLConnection;

import java.net. URL;


import com.google.android.gms. gcm. GoogleCloudMessaging;

import com.google.android.gms.iid.InstanceID;


import android.app.IntentService;

import android.app.PendingIntent;

import android.content.Context;

import android.content.Intent;

import android.content.SharedPreferences;

import android.net. Uri;

import android. os. Handler;

import android. os. Looper;

import android.widget.Toast;


public class InstanceIDIntentService extends IntentService {


// abbreviated tag name

private static final String TAG = «InstanceIDIntentService»;

private SharedPreferences mSettings;


public InstanceIDIntentService () {

super (TAG);

}


@Override

protected void onHandleIntent (Intent intent) {

InstanceID instanceID = InstanceID.getInstance (this);

mSettings = getSharedPreferences («APP_PREFERENCES», Context.MODE_PRIVATE);

String senderId = mSettings.getString («SENDER_ID», «»);

try {

String token = instanceID.getToken (senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE);

int code=sendRegistrationToServer (token);

if (code==200) {

PendingIntent pi = intent.getParcelableExtra(MainActivity.PARAM_PINTENT);

Intent intentResult = new Intent().putExtra(MainActivity.PARAM_RESULT, token);

pi.send(InstanceIDIntentService.this,MainActivity.RESULT_CODE, intentResult);

} else {

Handler handler = new Handler(Looper.getMainLooper ());

handler.post (new Runnable () {

@Override

public void run () {Toast.makeText(InstanceIDIntentService.this.getApplicationContext (),«Registration failed!",Toast.LENGTH_SHORT).show ();

}

});

}


} catch (Exception e) {

e.printStackTrace ();

}

}


private int sendRegistrationToServer (String token) {

URL url;

HttpURLConnection conn=null;

int code=0;

try {

url = new URL (»http://backend.appspot.com/backend");

conn = (HttpURLConnection) url. openConnection ();

conn.setReadTimeout (10000);

conn.setConnectTimeout (15000);

conn.setRequestMethod («POST»);

conn.setDoInput (true);

conn.setDoOutput (true);


Uri. Builder builder = new Uri. Builder ()

.appendQueryParameter («token», token);

String query = builder.build().getEncodedQuery ();


OutputStream os = conn.getOutputStream ();

BufferedWriter writer = new BufferedWriter (

new OutputStreamWriter (os, «UTF-8»));

writer. write (query);

writer. flush ();

writer.close ();

os.close ();

code=conn.getResponseCode ();

} catch (Exception e) {

e.printStackTrace ();

} finally {

if (conn!= null) {

conn. disconnect ();

}

}

return code;

}

}

Здесь с помощью номера проекта создается запрос к сервису GCM и в ответ получается уникальный регистрационный токен, который затем отсылается на сервер и передается с помощью объекта PendingIntent обратно в активность.

Для создания серверной части в среде Eclipse создадим проект Web Application Project, в файле appengine-web. xml которого укажем идентификатор проекта Google Cloud Platform.

В сервлет GAE приложения добавим код сохранения токена.

import java.io.IOException;

import javax.servlet.http.*;


import com. google. appengine. api. datastore. DatastoreService;

import com. google. appengine. api. datastore. DatastoreServiceFactory;

import com. google. appengine. api. datastore. Entity;


@SuppressWarnings («serial»)

public class BackendServlet extends HttpServlet {

public void doPost (HttpServletRequest req, HttpServletResponse resp) throws IOException {

String token=req.getParameter («token»);

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService ();

Entity tokenEntity = new Entity («Token»);

tokenEntity.setProperty («token», token);

datastore. put (tokenEntity);

}

}

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

<service

android:name=".RefreshInstanceIDListenerService»

android: exported=«false»>

<intent-filter>

<action android:name="com.google.android.gms.iid.InstanceID»/>

</intent-filter>

</service>

import com.google.android.gms.iid.InstanceIDListenerService;

import android.content.Intent;


public class RefreshInstanceIDListenerService extends InstanceIDListenerService {


@Override

public void onTokenRefresh () {

// Fetch updated Instance ID token and notify of changes

Intent intent = new Intent (this, InstanceIDIntentService.class);

startService (intent);

}

}

Для отправки сообщения от сервера Android приложению, в папку lib и в Build Path проекта GAE приложения добавим библиотеки json-simple-1.1.jar (http://grepcode.com/snapshot/repo1.maven.org/maven2/com.googlecode.json-simple/json-simple/1.1) и gcm-server. jar (https://github.com/slorber/gcm-server-repository/tree/master/deployer).

В код сервлета добавим:

import java.io.IOException;

import javax.servlet.http.*;


import com.google.android.gcm.server.Message;

import com.google.android.gcm.server.Sender;

import com.google.android.gcm.server.Result;

import com. google. appengine. api. datastore. DatastoreService;

import com. google. appengine. api. datastore. DatastoreServiceFactory;

import com. google. appengine. api. datastore. Entity;


@SuppressWarnings («serial»)

public class BackendServlet extends HttpServlet {

private String SERVER_KEY=«AIza…»;


public void doPost (HttpServletRequest req, HttpServletResponse resp) throws IOException {

String token=req.getParameter («token»);

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService ();

Entity tokenEntity = new Entity («Token»);

tokenEntity.setProperty («token», token);

datastore. put (tokenEntity);


Sender sender = new Sender (SERVER_KEY);

Message message = new Message. Builder ()

.addData («sender», «Project Name»)

.addData («message», «this is the message»)

.build ();

Result result = sender.send (message, token, 1);

}

}

Здесь SERVER_KEY это созданный server API key для Google Cloud Messaging.

Для получения сообщения Android приложением, в файл манифеста добавим объявление сервиса, который будет обрабатывать GCM сообщение.

<receiver

android:name="com.google.android.gms. gcm. GcmReceiver»

android: exported=«true»

android:permission="com.google.android.c2dm.permission.SEND»>

<intent-filter>

<action android:name="com.google.android.c2dm.intent.RECEIVE» />

<category android:name="com.tmsoftstudio.breakingnews» />

</intent-filter>

<intent-filter>

<action android:name="com.google.android.c2dm.intent.REGISTRATION»/>

<category android:name="com.tmsoftstudio.breakingnews»/>

</intent-filter>

</receiver>

А также создадим сервис обработки входящего сообщения.

<service

android: name=». GcmMessageHandler»

android: exported=«false»>

<intent-filter>

<action android:name="com.google.android.c2dm.intent.RECEIVE» />

</intent-filter>

</service>

import com.google.android.gms. gcm. GcmListenerService;

import android.app.NotificationManager;

import android.content.Context;

import android. os. Bundle;

import android.support.v4.app.NotificationCompat;


public class GcmMessageHandler extends GcmListenerService {

public static final int MESSAGE_NOTIFICATION_ID = 123123;


@Override

public void onMessageReceived (String from, Bundle data) {

String title = data.getString («sender»);

String message = data.getString («message»);


Context context = getBaseContext ();

NotificationCompat. Builder mBuilder = new NotificationCompat. Builder (context) .setSmallIcon(R.drawable.ic_launcher).setContentTitle (title)

.setContentText (message);

NotificationManager mNotificationManager = (NotificationManager) context

.getSystemService(Context.NOTIFICATION_SERVICE);

mNotificationManager.notify (MESSAGE_NOTIFICATION_ID, mBuilder. build ());

}

}

Для рассылки topic сообщений в проекте GAE приложения заменим библиотеку gcm-server. jar (https://github.com/slorber/gcm-server-repository/tree/master/deployer) на библиотеку https://github.com/google/gcm.

Это позволит заменить строку sender.send (message, token, 1); на sender.send (message, "/topics/news», 1);

Для подписки Android приложения на topic сообщения в сервисе InstanceIDIntentService в методе onHandleIntent добавим код:

String token = instanceID.getToken (senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE);

GcmPubSub pubSub = GcmPubSub.getInstance (this);

pubSub.subscribe (token, "/topics/news», null);

Изменим сервис GcmMessageHandler.

import com.google.android.gms. gcm. GcmListenerService;

import android.app.NotificationManager;

import android.content.Context;

import android. os. Bundle;

import android.support.v4.app.NotificationCompat;


public class GcmMessageHandler extends GcmListenerService {

public static final int MESSAGE_NOTIFICATION_ID = 123123;


@Override

public void onMessageReceived (String from, Bundle data) {

String title = data.getString («sender»);

String message = data.getString («message»);


if (from.startsWith (»/topics/news»)) {

Context context = getBaseContext ();

NotificationCompat. Builder mBuilder = new NotificationCompat. Builder (context)

.setSmallIcon(R.drawable.ic_launcher).setContentTitle (title+«Topic: News»)

.setContentText (message);

NotificationManager mNotificationManager = (NotificationManager) context

.getSystemService(Context.NOTIFICATION_SERVICE);

mNotificationManager.notify (MESSAGE_NOTIFICATION_ID, mBuilder. build ());

} else {

Context context = getBaseContext ();

NotificationCompat. Builder mBuilder = new NotificationCompat. Builder (context)

.setSmallIcon(R.drawable.ic_launcher).setContentTitle (title)

.setContentText (message);

NotificationManager mNotificationManager = (NotificationManager) context

.getSystemService(Context.NOTIFICATION_SERVICE);

mNotificationManager.notify (MESSAGE_NOTIFICATION_ID, mBuilder. build ());

}

}

}


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

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

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


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


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