Пишем термометр для Android
Предисловие
На написание данного материала меня сподвиг данный пост, так как месяцев 5 назад для себя писал почти такое-же приложение, но с немного другим функционалом, и столкнулся с различными трудностями.
Отличия от этого приложения:
- Наличие виджета
- Парсинг данных и обработка ошибок сайта bashkirenergo.ru/weather/ufa/index.asp (часто бывает, что с датчиков не приходит температура, и при отсутствии данных приложение может упасть) происходит на стороне сервера, за счет чего в разы уменьшается входящий трафик на телефоне
- Цвет фона приложения меняется в зависимости от температуры
- Подгрузка сторонних шрифтов
Принцип таков:
- Класс — провайдер информации для самого приложения и виджета.
- Два layout'а — для виджета и приложения.
Так как цикл разработки с нуля уже описан тут, то перейдем сразу к делу.
Класс провайдер информации
Создаем класс InetConn.java, который будет предоставлять информацию для виджета и приложения. Класс взят из поста.
<font color="black">package com.example.helloandroid; import java.io.BufferedReader; import java.io.InputStreamReader; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.conn.<font color="#0000ff">params</font>.ConnRoutePNames; import org.apache.http.impl.client.DefaultHttpClient; <font color="#0000ff">public</font> <font color="#0000ff">class</font> InetConn { <font color="#008000">//откуда получаем данные</font> <font color="#0000ff">public</font> <font color="#2B91AF">String</font> USER_URL = <font color="#A31515">"http://2sane.ru/weather/index.php"</font>; <font color="#0000ff">public</font> <font color="#2B91AF">String</font> RESULT_OK = <font color="#A31515">"ok"</font>; <font color="#0000ff">public</font> <font color="#2B91AF">String</font> RESULT_SERVER = <font color="#A31515">"server"</font>; <font color="#0000ff">public</font> <font color="#2B91AF">String</font> RESULT_USER_NOT_FOUND = <font color="#A31515">"not_found"</font>; <font color="#0000ff">public</font> <font color="#2B91AF">String</font> RESULT_NETWORK = <font color="#A31515">"network"</font>; <font color="#0000ff">public</font> <font color="#2B91AF">String</font> getInet() { <font color="#2B91AF">String</font> result = <font color="#A31515">""</font>; <font color="#2B91AF">String</font> url = USER_URL; <font color="#2B91AF">String</font> proxyHost = android.net.Proxy.getDefaultHost(); <font color="#0000ff">int</font> proxyPort = android.net.Proxy.getDefaultPort(); HttpClient httpClient = <font color="#0000ff">new</font> DefaultHttpClient(); <font color="#0000ff">if</font> (proxyPort > 0) { HttpHost proxy = <font color="#0000ff">new</font> HttpHost(proxyHost, proxyPort); httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); } HttpGet httpGet = <font color="#0000ff">new</font> HttpGet(url); <font color="#0000ff">try</font> { HttpResponse response = httpClient.execute(httpGet); <font color="#0000ff">if</font> (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { <font color="#008000">//BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), Charset.forName("CP1251")));</font> BufferedReader reader = <font color="#0000ff">new</font> BufferedReader(<font color="#0000ff">new</font> InputStreamReader(response.getEntity().getContent())); <font color="#2B91AF">StringBuilder</font> sb = <font color="#0000ff">new</font> <font color="#2B91AF">StringBuilder</font>(); <font color="#2B91AF">String</font> line = <font color="#0000ff">null</font>; <font color="#0000ff">while</font> ((line = reader.readLine()) != <font color="#0000ff">null</font>) { sb.append(line); } sb.append(<font color="#A31515">'°'</font>); <font color="#2B91AF">String</font> answer = sb.toString(); result = answer; } } <font color="#0000ff">catch</font> (Exception e) { } <font color="#0000ff">return</font> result; } } </font> <font color="gray">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><font color="gray">Source Code Highlighter</font></a>.</font>
Серверная часть на PHP
<font color="black">$url1 = <font color="#A31515">'http://www.bashkirenergo.ru/weather/ufa/index.asp'</font>; $url2 = <font color="#A31515">'http://www.bashkirenergo.ru/weather/ufa/index.asp?delta=1'</font>; <font color="#0000ff">if</font>(file_get_contents($url1)){ $weather = file_get_contents($url1); $weather_utf = iconv(<font color="#A31515">"CP1251"</font>, <font color="#A31515">"UTF-8"</font>, $weather); $ind = stripos($weather_utf, <font color="#A31515">"Дом"</font>); $tempt = intval(substr($weather_utf, $ind-20, 3)); <font color="#008000">//если текущая температура недоступна, то пытаемся взять температуру часом ранее по этому адресу: <a href="http://www.bashkirenergo.ru/weather/ufa/index.asp?delta=1">www.bashkirenergo.ru/weather/ufa/index.asp?delta=1</a></font> <font color="#0000ff">if</font>(!isset($tempt)){ $weather = file_get_contents($url2); $weather_utf = iconv(<font color="#A31515">"CP1251"</font>, <font color="#A31515">"UTF-8"</font>, $weather); $ind = stripos($weather_utf, <font color="#A31515">"Дом"</font>); $tempt = intval(substr($weather_utf, $ind-20, 3)); <font color="#0000ff">if</font>(!isset($tempt)){$tempt = <font color="#A31515">"+0"</font>;} } } <font color="#0000ff">else</font>{ $tempt = <font color="#A31515">"+0"</font>; } print $tempt; </font> <font color="gray">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><font color="gray">Source Code Highlighter</font></a>.</font>
Код приложения
<font color="black">package com.example.helloandroid; import android.app.Activity; import android.content.Intent; import android.graphics.Color; import android.graphics.Typeface; import android.net.<font color="#2B91AF">Uri</font>; import android.os.Bundle; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import android.view.View; import android.view.View.OnClickListener; <font color="#0000ff">public</font> <font color="#0000ff">class</font> HelloAndroid extends Activity { <font color="#0000ff">private</font> TextView txt; <font color="#0000ff">private</font> TextView txt2; <font color="#0000ff">private</font> ImageView logo; <font color="#0000ff">private</font> RelativeLayout mScreen; <font color="#0000ff">private</font> <font color="#0000ff">int</font> col = 0; <font color="#0000ff">private</font> <font color="#0000ff">int</font> num = 0; <font color="#008000">//Массив цветов фона:</font> <font color="#0000ff">private</font> <font color="#2B91AF">String</font>[] colors = { <font color="#A31515">"#15ADFF"</font>, <font color="#A31515">"#1BAFF"</font>, <font color="#A31515">"#21B1FF"</font>, <font color="#A31515">"#27B3FF"</font>, <font color="#A31515">"#2DB5FF"</font>, <font color="#A31515">"#33B7FF"</font>, <font color="#A31515">"#39B9FF"</font>, <font color="#A31515">"#3FBBFF"</font>, <font color="#A31515">"#45BDFF"</font>, <font color="#A31515">"#4BBFFF"</font>, <font color="#A31515">"#51C1FF"</font>, <font color="#A31515">"#57C3FF"</font>, <font color="#A31515">"#5DC5FF"</font>, <font color="#A31515">"#63C7FF"</font>, <font color="#A31515">"#69C9FF"</font>, <font color="#A31515">"#6FCBFF"</font>, <font color="#A31515">"#75CDFF"</font>, <font color="#A31515">"#7BCFF"</font>, <font color="#A31515">"#81D1FF"</font>, <font color="#A31515">"#87D3FF"</font>, <font color="#A31515">"#8DD5FE"</font>, <font color="#A31515">"#93D7FE"</font>, <font color="#A31515">"#99D9FE"</font>, <font color="#A31515">"#9FDBFE"</font>, <font color="#A31515">"#A5DDFE"</font>, <font color="#A31515">"#ABDFFE"</font>, <font color="#A31515">"#B1E1FE"</font>, <font color="#A31515">"#B7F3FE"</font>, <font color="#A31515">"#BDF5FE"</font>, <font color="#A31515">"#C3E7FE"</font>, <font color="#A31515">"#C9E9FE"</font>, <font color="#A31515">"#CFEBFE"</font>, <font color="#A31515">"#D5EDFE"</font>, <font color="#A31515">"#DBEFFE"</font>, <font color="#A31515">"#E1F1FE"</font>, <font color="#A31515">"#E7F3FE"</font>, <font color="#A31515">"#EDF5FE"</font>, <font color="#A31515">"#F3F7FE"</font>, <font color="#A31515">"#F9F9FE"</font>, <font color="#A31515">"#FFFBFE"</font>, <font color="#A31515">"#FFFBFE"</font>, <font color="#A31515">"#FFF8F7"</font>, <font color="#A31515">"#FFF4F1"</font>, <font color="#A31515">"#FFF1EA"</font>, <font color="#A31515">"#FFEEE4"</font>, <font color="#A31515">"#FFEADD"</font>, <font color="#A31515">"#FFE7D7"</font>, <font color="#A31515">"#FFE4D0"</font>, <font color="#A31515">"#FFE0CA"</font>, <font color="#A31515">"#FFDDC3"</font>, <font color="#A31515">"#FFDABD"</font>, <font color="#A31515">"#FFD6B6"</font>, <font color="#A31515">"#FFD3B0"</font>, <font color="#A31515">"#FFD0A9"</font>, <font color="#A31515">"#FFCCA3"</font>, <font color="#A31515">"#FFC99C"</font>, <font color="#A31515">"#FFC696"</font>, <font color="#A31515">"#FFC28F"</font>, <font color="#A31515">"#FFBF89"</font>, <font color="#A31515">"#FFBC82"</font>, <font color="#A31515">"#FFB87C"</font>, <font color="#A31515">"#FFB575"</font>, <font color="#A31515">"#FFB26F"</font>, <font color="#A31515">"#FFAE68"</font>, <font color="#A31515">"#FFAB62"</font>, <font color="#A31515">"#FFA85B"</font>, <font color="#A31515">"#FFA455"</font>, <font color="#A31515">"#FFA14E"</font>, <font color="#A31515">"#FF9E48"</font>, <font color="#A31515">"#FF9A41"</font>, <font color="#A31515">"#FF973B"</font>, <font color="#A31515">"#FF9434"</font>, <font color="#A31515">"#FF902E"</font>, <font color="#A31515">"#FF8D27"</font>, <font color="#A31515">"#FF8A21"</font>, <font color="#A31515">"#FF861A"</font>, <font color="#A31515">"#FF8314"</font>, <font color="#A31515">"#FF800D"</font>, <font color="#A31515">"#FF7C07"</font>, <font color="#A31515">"#FF7900"</font>, <font color="#A31515">"#FF7900"</font>}; @Override <font color="#0000ff">public</font> <font color="#0000ff">void</font> onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); txt = (TextView) findViewById(R.id.TextView01); txt2 = (TextView) findViewById(R.id.TextView02); logo = (ImageView) findViewById(R.id.ImageView01); <font color="#008000">//получаем данные от класса:</font> InetConn <font color="#0000ff">in</font> = <font color="#0000ff">new</font> InetConn(); <font color="#2B91AF">String</font> tempt = <font color="#0000ff">in</font>.getInet(); <font color="#008000">//Преобразуем данные в число, для определения цвета фона:</font> <font color="#0000ff">if</font> (tempt.length() > 3) num = 3; <font color="#0000ff">else</font> num = 2; <font color="#0000ff">if</font> (tempt.substring(0, 1).equals(<font color="#A31515">"+"</font>)) { col = Integer.parseInt(tempt.substring(1, num)); } <font color="#0000ff">else</font> { col = Integer.parseInt(tempt.substring(0, num)); } mScreen = (RelativeLayout) findViewById(R.id.myScreen); mScreen.setBackgroundColor(Color.parseColor(colors[40+(col)])); <font color="#008000">//Подгружаем наш шрифт</font> Typeface digitalFont = Typeface.createFromAsset(<font color="#0000ff">this</font>.getAssets(), <font color="#A31515">"fonts/HELVETCB.OTF"</font>); txt.setTypeface(digitalFont); txt2.setTypeface(digitalFont); txt.setText(tempt); logo.setOnClickListener(logoListener); } <font color="#008000">//обработка клика по логотипу и открытие браузера:</font> <font color="#0000ff">private</font> OnClickListener logoListener = <font color="#0000ff">new</font> OnClickListener() { <font color="#0000ff">public</font> <font color="#0000ff">void</font> onClick(View arg0) { <font color="#008000">// TODO Auto-generated method stub</font> Intent intent = <font color="#0000ff">new</font> Intent(Intent.ACTION_VIEW, <font color="#2B91AF">Uri</font>.parse(<font color="#A31515">"http://www.atmateam.ru"</font>)); startActivity(intent); } }; } </font> <font color="gray">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><font color="gray">Source Code Highlighter</font></a>.</font>
Layout виджета
<font color="black"><font color="#0000ff"><?</font><font color="#800000">xml</font> <font color="#ff0000">version</font><font color="#0000ff">="1.0"</font> <font color="#ff0000">encoding</font><font color="#0000ff">="utf-8"</font>?<font color="#0000ff">></font> <font color="#0000ff"><</font><font color="#800000">LinearLayout</font> <font color="#ff0000">xmlns:android</font><font color="#0000ff">="http://schemas.android.com/apk/res/android"</font> <font color="#ff0000">android:layout_width</font><font color="#0000ff">="fill_parent"</font> <font color="#ff0000">android:orientation</font><font color="#0000ff">="vertical"</font> <font color="#ff0000">android:layout_gravity</font><font color="#0000ff">="center"</font> <font color="#ff0000">android:background</font><font color="#0000ff">="@drawable/widget_bg_normal"</font> <font color="#ff0000">android:layout_height</font><font color="#0000ff">="wrap_content"</font><font color="#0000ff">></font> <font color="#0000ff"><</font><font color="#800000">TextView</font> <font color="#ff0000">android:id</font><font color="#0000ff">="@+id/widget_textview"</font> <font color="#ff0000">android:text</font><font color="#0000ff">="@string/widget_text"</font> <font color="#ff0000">android:layout_height</font><font color="#0000ff">="wrap_content"</font> <font color="#ff0000">android:layout_width</font><font color="#0000ff">="wrap_content"</font> <font color="#ff0000">android:layout_gravity</font><font color="#0000ff">="center_horizontal|center"</font> <font color="#ff0000">android:layout_marginTop</font><font color="#0000ff">="5dip"</font> <font color="#ff0000">android:padding</font><font color="#0000ff">="15dip"</font> <font color="#ff0000">android:textSize</font><font color="#0000ff">="16dip"</font> <font color="#ff0000">android:textColor</font><font color="#0000ff">="@android:color/black"</font><font color="#0000ff">/></font> <font color="#0000ff"></</font><font color="#800000">LinearLayout</font><font color="#0000ff">></font> </font> <font color="gray">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><font color="gray">Source Code Highlighter</font></a>.</font>
Настройки виджета
<font color="black"><font color="#0000ff"><?</font><font color="#800000">xml</font> <font color="#ff0000">version</font><font color="#0000ff">="1.0"</font> <font color="#ff0000">encoding</font><font color="#0000ff">="utf-8"</font>?<font color="#0000ff">></font> <font color="#0000ff"><</font><font color="#800000">appwidget-provider</font> <font color="#ff0000">xmlns:android</font><font color="#0000ff">="http://schemas.android.com/apk/res/android"</font> <font color="#ff0000">android:minWidth</font><font color="#0000ff">="64dip"</font> <font color="#ff0000">android:minHeight</font><font color="#0000ff">="64dip"</font> <font color="#ff0000">android:updatePeriodMillis</font><font color="#0000ff">="1800000"</font> <font color="#ff0000">android:initialLayout</font><font color="#0000ff">="@layout/widget"</font> <font color="#0000ff">/></font> </font> <font color="gray">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><font color="gray">Source Code Highlighter</font></a>.</font>
Код виджета
Больше всего проблем при написании виджета, я получил с его обновлением, стандартными методами ничего не выходило, сработало только с применением таймера.
<font color="black">package com.example.helloandroid; import java.util.Timer; import java.util.TimerTask; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.widget.RemoteViews; <font color="#0000ff">public</font> <font color="#0000ff">class</font> HelloWidget extends AppWidgetProvider { @Override <font color="#0000ff">public</font> <font color="#0000ff">void</font> onReceive(Context context, Intent intent) { <font color="#008000">// v1.5 fix that doesn't call onDelete Action</font> final <font color="#2B91AF">String</font> action = intent.getAction(); <font color="#0000ff">if</font> (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) { final <font color="#0000ff">int</font> appWidgetId = intent.getExtras().getInt( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); <font color="#0000ff">if</font> (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) { <font color="#0000ff">this</font>.onDeleted(context, <font color="#0000ff">new</font> <font color="#0000ff">int</font>[] { appWidgetId }); } } <font color="#0000ff">else</font> { super.onReceive(context, intent); } } @Override <font color="#0000ff">public</font> <font color="#0000ff">void</font> onUpdate(Context context, AppWidgetManager appWidgetManager, <font color="#0000ff">int</font>[] appWidgetIds) { <font color="#008000">//Устанавливаем таймер обновления виджета, раз в 30 минут</font> Timer timer = <font color="#0000ff">new</font> Timer(); timer.scheduleAtFixedRate(<font color="#0000ff">new</font> MyTime(context, appWidgetManager), 1, 1800000); } <font color="#0000ff">private</font> <font color="#0000ff">class</font> MyTime extends TimerTask { RemoteViews remoteViews; AppWidgetManager appWidgetManager; ComponentName thisWidget; <font color="#0000ff">public</font> MyTime(Context context, AppWidgetManager appWidgetManager) { <font color="#0000ff">this</font>.appWidgetManager = appWidgetManager; remoteViews = <font color="#0000ff">new</font> RemoteViews(context.getPackageName(), R.layout.widget); thisWidget = <font color="#0000ff">new</font> ComponentName(context, HelloWidget.<font color="#0000ff">class</font>); } @Override <font color="#0000ff">public</font> <font color="#0000ff">void</font> run() { InetConn <font color="#0000ff">in</font> = <font color="#0000ff">new</font> InetConn(); remoteViews.setTextViewText(R.id.widget_textview, <font color="#0000ff">in</font>.getInet()); appWidgetManager.updateAppWidget(thisWidget, remoteViews); } } } </font> <font color="gray">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><font color="gray">Source Code Highlighter</font></a>.</font>
Финал
Правим AndroidManifest.xml
<font color="black"><?xml version=<font color="#A31515">"1.0"</font> encoding=<font color="#A31515">"utf-8"</font>?> <manifest xmlns:android=<font color="#A31515">"http://schemas.android.com/apk/res/android"</font> package=<font color="#A31515">"com.example.helloandroid"</font> android:versionCode=<font color="#A31515">"1"</font> android:versionName=<font color="#A31515">"1.0"</font>> <application android:icon=<font color="#A31515">"@drawable/icon"</font> android:label=<font color="#A31515">"@string/app_name"</font>> <activity android:name=<font color="#A31515">".HelloAndroid"</font> android:label=<font color="#A31515">"@string/app_name"</font>> <intent-filter> <action android:name=<font color="#A31515">"android.intent.action.MAIN"</font> /> <category android:name=<font color="#A31515">"android.intent.category.LAUNCHER"</font> /> </intent-filter> </activity> <!-- Broadcast Receiver that will process AppWidget updates --> <receiver android:name=<font color="#A31515">".HelloWidget"</font> android:label=<font color="#A31515">"@string/app_name"</font>> <intent-filter> <action android:name=<font color="#A31515">"android.appwidget.action.APPWIDGET_UPDATE"</font> /> </intent-filter> <meta-data android:name=<font color="#A31515">"android.appwidget.provider"</font> android:resource=<font color="#A31515">"@xml/hello_widget_provider"</font> /> </receiver> <receiver android:name=<font color="#A31515">".HelloWidget"</font> android:label=<font color="#A31515">"@string/app_name"</font>> <intent-filter> <action android:name=<font color="#A31515">"android.appwidget.action.APPWIDGET_UPDATE"</font> /> <data android:scheme=<font color="#A31515">"karma_widget"</font> /> </intent-filter> <meta-data android:name=<font color="#A31515">"android.appwidget.provider"</font> android:resource=<font color="#A31515">"@xml/hello_widget_provider"</font> /> </receiver> </application> <uses-permission android:name=<font color="#A31515">"android.permission.INTERNET"</font>></uses-permission> </manifest> </font> <font color="gray">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><font color="gray">Source Code Highlighter</font></a>.</font>
Архив с исходным кодом и apk файлом.
Использованные материалы:
- Пишем виджет ХабраКарма ex-CarmaWidget для Android
- Android Developers
- Mastering Android Widget Development
Так как это мой первый опыт разработки на Java и Android, в комментариях приветствуется критика и предложения.
0 комментариев