Ta
sẽ làm một ứng dụng lấy thông tin thời tiết trên mạng.
Tạo
một project với tên bất kỳ, trong file Manifest.xml, thêm quyền internet.
<uses-permission android:name="android.permission.INTERNET"
/>
Thêm
vào khai báo của class Main.
android:screenOrientation="portrait" android:theme="@android:style/Theme.Holo.Light.Dialog.NoActionBar"
Sửa
minSdk thành.
android:minSdkVersion="11"
Trong
file strings.xml của thẻ values, thêm đoạn sau vào.
<string name="change_city">Change city</string>
<!-- Put your own APP ID here -->
<string name="open_weather_maps_app_id">abaf05e51e3c176324d5c6b5f0696e46</string>
<string name="weather_sunny"></string>
<string name="weather_clear_night"></string>
<string name="weather_foggy"></string>
<string name="weather_cloudy"></string>
<string name="weather_rainy"></string>
<string name="weather_snowy"></string>
<string name="weather_thunder"></string>
<string name="weather_drizzle"></string>
<string name="place_not_found">Sorry, no weather data
found.</string>
Muốn
dùng API key khác bạn vào trang này để đăng ký rồi tạo API key.
Trong
file main.xml của thẻ main, thay đoạn sau vào.
<item
android:id="@+id/change_city"
android:orderInCategory="1"
android:title="@string/change_city"
app:showAsAction="never"/>
Trong
folder layout, tạo một file fragment_weather.xml
như sau
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="ah.hathi.simpleweather.WeatherActivity$PlaceholderFragment"
>
<TextView
android:id="@+id/city_field"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:textColor="#ffffff"
/>
<TextView
android:id="@+id/updated_field"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/city_field"
android:layout_centerHorizontal="true"
android:textColor="#ffffff"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="13sp"
/>
<TextView
android:id="@+id/weather_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/current_temperature_field"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textColor="#ffffff"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="70sp"
/>
<TextView
android:id="@+id/current_temperature_field"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/updated_field"
android:layout_centerHorizontal="true"
android:textColor="#ffffff"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="40sp"
/>
<TextView
android:id="@+id/details_field"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:textColor="#ffffff"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
</RelativeLayout>
File
activity_main.xml như sau.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="260dp"
android:layout_height="300dp"
tools:context="ah.ha.simpleweather.WeatherActivity"
tools:ignore="MergeRootFrame"
android:background="#FF0099CC"
/>
Tải
font thời tiết về tại đây.
Ấn
nút Clone or download để tải, lấy file weathericons-regular-webfont.ttf
ở trong font cho vào thư mục fonts trong thư mục assets, sửa tên thành weather.ttf.
Tạo
một class có tên CityPreference.
import android.app.Activity;
import
android.content.SharedPreferences;
public class CityPreference {
SharedPreferences prefs;
public CityPreference(Activity activity){
prefs
= activity.getPreferences(Activity.MODE_PRIVATE);
}
String getCity(){
return prefs.getString("city", "Hanoi, VN");
}
void setCity(String city){
prefs.edit().putString("city", city).commit();
}
}
Tạo
một class có tên RemoteFetch.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import org.json.JSONObject;
import android.content.Context;
public class RemoteFetch {
private static final String OPEN_WEATHER_MAP_API =
"http://api.openweathermap.org/data/2.5/weather?q=%s&units=metric";
public static JSONObject getJSON(Context context, String city){
try {
URL url = new URL(String.format(OPEN_WEATHER_MAP_API, city));
HttpURLConnection connection =
(HttpURLConnection)url.openConnection();
connection.addRequestProperty("x-api-key",
context.getString(R.string.open_weather_maps_app_id));
BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
StringBuffer json = new StringBuffer(1024);
String tmp="";
while((tmp=reader.readLine())!=null)
json.append(tmp).append("\n");
reader.close();
JSONObject data = new JSONObject(json.toString());
// This value will be 404 if the request was not
// successful
if(data.getInt("cod") != 200){
return null;
}
return data;
}catch(Exception e){
return null;
}
}
}
Tạo
một class có tên WeatherFragment.
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import org.json.JSONObject;
import android.app.Fragment;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class WeatherFragment extends Fragment {
Typeface weatherFont;
TextView cityField;
TextView updatedField;
TextView detailsField;
TextView currentTemperatureField;
TextView weatherIcon;
Handler handler;
public WeatherFragment(){
handler
= new Handler();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
weatherFont = Typeface.createFromAsset(getActivity().getAssets(), "fonts/weather.ttf");
updateWeatherData(new
CityPreference(getActivity()).getCity());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_weather, container, false);
cityField = (TextView)rootView.findViewById(R.id.city_field);
updatedField = (TextView)rootView.findViewById(R.id.updated_field);
detailsField = (TextView)rootView.findViewById(R.id.details_field);
currentTemperatureField = (TextView)rootView.findViewById(R.id.current_temperature_field);
weatherIcon = (TextView)rootView.findViewById(R.id.weather_icon);
weatherIcon.setTypeface(weatherFont);
return rootView;
}
private void updateWeatherData(final String city){
new Thread(){
public void run(){
final JSONObject json = RemoteFetch.getJSON(getActivity(),
city);
if(json == null){
handler.post(new Runnable(){
public void run(){
detailsField.setText( "No internet
connection!");
}
});
} else {
handler.post(new Runnable(){
public void run(){
renderWeather(json);
}
});
}
}
}.start();
}
private void renderWeather(JSONObject json){
try {
cityField.setText(json.getString("name").toUpperCase(Locale.US) +
", " +
json.getJSONObject("sys").getString("country"));
JSONObject details = json.getJSONArray("weather").getJSONObject(0);
JSONObject main = json.getJSONObject("main");
detailsField.setText(
details.getString("description").toUpperCase(Locale.US) +
"\n" + "Humidity: " + main.getString("humidity") + "%" +
"\n" + "Pressure: " + main.getString("pressure") + "
hPa");
currentTemperatureField.setText(
String.format("%.2f", main.getDouble("temp"))+ "
℃");
DateFormat df = DateFormat.getDateTimeInstance();
String updatedOn = df.format(new
Date(json.getLong("dt")*1000));
updatedField.setText("Last
update: " + updatedOn);
setWeatherIcon(details.getInt("id"),
json.getJSONObject("sys").getLong("sunrise") * 1000,
json.getJSONObject("sys").getLong("sunset") * 1000);
}catch(Exception e){
Log.e("SimpleWeather", "One or more fields not found in the JSON
data");
}
}
private void setWeatherIcon(int actualId, long sunrise, long sunset){
int id = actualId / 100;
String icon = "";
if(actualId == 800){
long currentTime = new Date().getTime();
if(currentTime>=sunrise && currentTime<sunset) {
icon = getActivity().getString(R.string.weather_sunny);
} else {
icon = getActivity().getString(R.string.weather_clear_night);
}
} else {
switch(id) {
case 2 : icon =
getActivity().getString(R.string.weather_thunder);
break;
case 3 : icon =
getActivity().getString(R.string.weather_drizzle);
break;
case 7 : icon =
getActivity().getString(R.string.weather_foggy);
break;
case 8 : icon =
getActivity().getString(R.string.weather_cloudy);
break;
case 6 : icon =
getActivity().getString(R.string.weather_snowy);
break;
case 5 : icon =
getActivity().getString(R.string.weather_rainy);
break;
}
}
weatherIcon.setText(icon);
}
public void changeCity(String city) {
updateWeatherData(city);
}
}
Class
MainActivity như sau.
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.InputType;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new WeatherFragment())
.commit();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is
present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.change_city) {
showInputDialog();
return false;
}
return super.onOptionsItemSelected(item);
}
private void showInputDialog(){
AlertDialog.Builder builder
= new AlertDialog.Builder(this);
builder.setTitle("Change city");
final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_CLASS_TEXT);
builder.setView(input);
builder.setPositiveButton("Go", new
DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
changeCity(input.getText().toString());
}
});
builder.show();
}
public void changeCity(String city){
WeatherFragment wf =
(WeatherFragment)getFragmentManager()
.findFragmentById(R.id.container);
wf.changeCity(city);
new CityPreference(this).setCity(city);
}
}
Chạy
thử để thấy ứng dụng hoạt động nếu có kết nối mạng.
Ấn
nút Menu, Change city để đổi thành phố. Nhập vào dalat để có thời tiết của
thành phố Đà Lạt.
If you're attempting to lose pounds then you need to try this totally brand new tailor-made keto plan.
ReplyDeleteTo create this keto diet, licensed nutritionists, fitness trainers, and top chefs have joined together to develop keto meal plans that are effective, painless, cost-efficient, and enjoyable.
Since their launch in January 2019, thousands of individuals have already remodeled their body and health with the benefits a certified keto plan can provide.
Speaking of benefits: clicking this link, you'll discover eight scientifically-certified ones given by the keto plan.
Easy "water hack" burns 2 lbs OVERNIGHT
ReplyDeleteMore than 160 thousand women and men are losing weight with a easy and secret "liquid hack" to burn 1-2lbs each night in their sleep.
It is very easy and works on anybody.
This is how you can do it yourself:
1) Take a glass and fill it with water half the way
2) Then learn this proven hack
so you'll become 1-2lbs lighter the very next day!