Android studio novice development: weather app (Baidu map api + wind weather api + city query + broken line display)

Posted by jej1216 on Sat, 27 Jun 2020 10:24:04 +0200

Android studio novice development: weather app (Baidu map api + wind weather api + city query + broken line display)

1. Content introduction

      In school b test, I happened to choose app development. Before that, I had only some experience in website development. I first contacted Android, from matching environment to running other people's demo to understanding and modifying step by step, and finally realizing the functions of locating weather query and displaying broken line chart. I installed my app on my mobile phone and felt full of achievements. I wrote down the main points and Strategies of this development, At the same time for other novice developers row some bug s. The interface is shown as follows:



2. Environment configuration

First download and install Android Studio and configure the virtual machine. The recommended reference link is as follows: AS configuration

3. Import another demo

When importing other as demos, there are often many headache bug s. Here we remind you to replace some configuration information of the demo itself and then use as open an existing Android studio project. The recommended reference link is as follows: Import another demo
In addition, if the long-term sync is not successful, it is likely that the reason for downloading the wall from google is the source directory build.gradle Alibaba cloud image replacement in the file

 //       google()
    //    jcenter()
        maven { url 'https://maven.aliyun.com/repository/google' }
        maven { url 'https://maven.aliyun.com/repository/jcenter' }
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }

4. AS project analysis

After successfully running other people's demo, the important thing is to analyze the project's architecture. Related information link: Project catalog analysis

Here again, I would like to highlight a few documents:
1. In app build.gradle All packages are introduced in. If the required package is missing or the version does not match, it needs to be modified in dependencies in the file

  dependencies {

        implementation fileTree(dir: 'libs', include: ['*.jar'])

//    implementation 'com.android.support:appcompat-v7:29.+'

        implementation 'com.android.support.constraint:constraint-layout:1.1.3'

        testImplementation 'junit:junit:4.12'

        androidTestImplementation 'com.android.support.test:runner:1.0.2'

        androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

        implementation 'com.github.PhilJay:MPAndroidChart:v3.0.1'

//    implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'

    }

2. App generated after running the project- debug.apk be located app.build.outputs.apk folder.

3. All source codes are located in app.main.src , where the working framework is java.activity Page layout in res.layout Medium. These two folders are the top priority of the project, covering the operation process and page design of the project, which need to be carefully understood.

4. Configuration file AndroidManife.XML The name and icon of the app are defined in to be modifiable.

<application
    android:name=".MainApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="Yin and Qing"
    android:roundIcon="@mipmap/ic_launcher"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

5. Weather project flow

Finally, we got to the main point. The weather app developed this time is named "Yin Qing". Open the app, the system first displays the weather information of the default city (Xi'an), and then the user can choose to carry out location query or freely choose the city: location query uses Baidu map api to locate the current city map information by applying for location permission, and caches the location city to sharereference , call the windy weather api to generate the weather information of the current city; freely select the city to query through the data table, call the windy weather api to generate and query the corresponding weather information of the city and display it. After that, the weather information will be saved to the cache sharereference, and the weather information of the city in the cache will be displayed the next time the app is opened. On the page display, save the weather query data to the shared preference, and select the broken line chart to display the highest and lowest temperature changes in the past seven days by establishing the chart. The flow chart is designed as follows:

6. Data exploration

1. Weather information acquisition
This time, the weather and air quality and other information are obtained from the free api we selected and provided by Hefeng weather. Every day, Hefeng weather provides 4000 free basic weather queries, which are sufficient for development and testing. Moreover, the air quality and other information it provides is comprehensive, and the JSON data type returned by Hefeng api interface is relatively simple, which is a project for our Android beginners It is convenient. The official website of the application process has a detailed tutorial. After the application is successful, the key is the key information of api call

3.2 api of location information acquisition
We chose to use the free API provided by Baidu http://lbsyun.baidu.com/apiconsole/key Because Android native location API is generally castrated in domestic mobile phones or due to domestic network restrictions, it is difficult to obtain location information by using Android native location API, which is related to mobile phone manufacturers and network environment. So in order to avoid the uncertainty of this situation, we chose to use the free status interface provided by Baidu, and its API application is as follows:

3.3 city information acquisition
Download the province and city information, establish the city list database, number each province and city, and use mysql to query and read. The data list is as follows:








7. Module architecture

1. City selcetor activity
Through the database query, query the selected province and city in turn. Through the callback function onActivityResult, get the callback of the selected city from the menu, save the city name to sharedpreference, and then transfer it to the weather query module to obtain the weather information.

/**
 * Query all provinces in the country, from the database
 */
private void queryProvinces() {
    ProvinceList.addAll(WeatherDB.loadProvinces(DBManager.getInstance().getDatabase()));
    data.clear();
    for (Province province : ProvinceList) {
        data.add(province.mProName);
    }
    currentLevel = LEVEL_PROVINCE;
    if(mAdapter==null)
    {
        initAdapter();
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
    }
    else mAdapter.notifyDataSetChanged();
}
/**
 * Query all cities in the selected province from the database
 */
private void queryCities() {
    CityList.addAll(WeatherDB.loadCities(DBManager.getInstance().getDatabase(), selectedProvince.mProSort));
    data.clear();
    for (City city:CityList)
    {
        data.add(city.mCityName);
    }
    currentLevel = LEVEL_CITY;
    mAdapter.notifyDataSetChanged();
    mRecyclerView.smoothScrollToPosition(0);
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == CitySelectorActivity.SelectorSuccessFromMenu) {
        //Callback from menu select city
        if (resultCode == RESULT_OK) {
            if (data == null) {
                return;
            }
            Bundle bundle = data.getExtras();
            //City name
            String cityName = bundle.getString("CityName");
            //After getting the city name, you can use it by yourself
            UpdataViewForMain(cityName);
        }
    }
}
private void UpdataViewForMain(String cityName)
{
    //Close sidebar
    mDrawerLayout.closeDrawer(mNavView);
    //Get OldCity to recover data when the new city is not loadable
    String OldCity = MySharedpreference.preferences.getString("City",null);
    //Save city
    editor.putString("City",cityName);
    editor.commit();
    //Update data
    mMainFragment.UpDataUi(OldCity);
    //RecyclerView back to top
    mMainFragment.mRecyclerView.smoothScrollToPosition(0);
}

2. Map activity module
By calling the baidu map api, read the current location and display the map, move to the current location through the definition method navigate to, and save the location city through the shared cache area sharedpreference, and transfer to the weather query module to obtain the weather information of the current city.

private void navigateTo(BDLocation location) {
      if (isFirstLocate) {
          LatLng ll = new LatLng(location.getLatitude(), location.getLongitude());
          MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);
          baiduMap.animateMapStatus(update);
          update = MapStatusUpdateFactory.zoomTo(16f);
          baiduMap.animateMapStatus(update);
          isFirstLocate = false;
      }
      MyLocationData.Builder locationBuilder = new MyLocationData.Builder();
      locationBuilder.latitude(location.getLatitude());
      locationBuilder.longitude(location.getLongitude());
      MyLocationData locationData = locationBuilder.build();
      baiduMap.setMyLocationData(locationData);
  }

  public class MyLocationListener implements BDLocationListener {
      public String city;

      private SharedPreferences.Editor  editor;       //Shared parameters

      public void onReceiveLocation(final BDLocation Location) {
          runOnUiThread(new Runnable() {

              @Override
              public void run() {


                  if (Location.getLocType() == BDLocation.TypeGpsLocation || Location.getLocType() == BDLocation.TypeNetWorkLocation) {
                      navigateTo(Location);
                      editor = MySharedpreference.getInstance(MapActivity.this);
                      city = Location.getCity();
                      editor.putString("City", city);
                      editor.commit();
                  }

                  button1 =(Button)findViewById(R.id.button);
                  button1.setOnClickListener(new View.OnClickListener(){
                      @Override
                      public void  onClick(View v){
                          editor = MySharedpreference.getInstance(MapActivity.this);
                          city = Location.getCity();
                          editor.putString("City", city);
                          editor.commit();
                          Intent intent=new Intent(MapActivity.this,MainActivity.class);
                          startActivity(intent);
                      }
                  });
                      }
                  });
              }
          }
      }

3. Weather information acquisition module (MultipleItemQuickAdapter)
In order to use GSON for parsing, first of all, the JSON data in the windy weather api interface is written as an entity class (NewWeatherBean), using the simulation request tool
Rest Client tests whether the api interface tool is normal. Finally, getHeWeather6 is used to get the data we need.

case MultipleItem.DetailsAirInfo://Air details
    try {
        helper.setText(R.id.air_aiq_tv, "Air index:  " + item.mAirBean
                .getHeWeather6().get(0).getAir_now_city().getAqi());
        helper.setText(R.id.air_qlty_tv, "air quality:  " + item.mAirBean
                .getHeWeather6().get(0).getAir_now_city().getQlty());
        helper.setText(R.id.air_main_pollutant_tv, "Main pollutants:  " + item.mAirBean
                .getHeWeather6().get(0).getAir_now_city().getMain());
        helper.setText(R.id.air_pm25_tv, "PM2.5 index:  " + item.mAirBean
                .getHeWeather6().get(0).getAir_now_city().getPm25());
        helper.setText(R.id.air_no2_tv, "Nitrogen dioxide index:  " + item.mAirBean
                .getHeWeather6().get(0).getAir_now_city().getNo2());
        helper.setText(R.id.air_so2_tv, "Sulfur dioxide index:  " + item.mAirBean
                .getHeWeather6().get(0).getAir_now_city().getSo2());
        helper.setText(R.id.air_co_tv, "Carbon monoxide index:  " + item.mAirBean
                .getHeWeather6().get(0).getAir_now_city().getCo());
        helper.setText(R.id.air_o3_tv, "Ozone index:  " + item.mAirBean
                .getHeWeather6().get(0).getAir_now_city().getO3());
    } catch (Exception e) {
    }
    break;

4. Chart information drawing module (Main2activity)
The weather is querying the data obtained from the highest temperature and minimum temperature in the last seven days through sharedpreference.

     for (int i = 1; i < 8; i++) {
                            tmp_max[i-1]=item.mNewWeatherBean.getHeWeather6()
                                    .get(0).getDaily_forecast().get(i-1).getTmp_max();
                            tmp_min[i-1]=item.mNewWeatherBean.getHeWeather6()
                                    .get(0).getDaily_forecast().get(i-1).getTmp_min();
                        }
                        SharedPreferences sp = mContext.getSharedPreferences("data", MODE_PRIVATE);
//Get editor
                        SharedPreferences.Editor editor = sp.edit();
//Save String data
                        editor.putString("tmp_max0", tmp_max[0]);
                        editor.putString("tmp_max1", tmp_max[1]);
                        editor.putString("tmp_max2", tmp_max[2]);
                        editor.putString("tmp_max3", tmp_max[3]);
                        editor.putString("tmp_max4", tmp_max[4]);
                        editor.putString("tmp_max5", tmp_max[5]);
                        editor.putString("tmp_max6", tmp_max[6]);
                        editor.putString("tmp_min0", tmp_min[0]);
                        editor.putString("tmp_min1", tmp_min[1]);
                        editor.putString("tmp_min2", tmp_min[2]);
                        editor.putString("tmp_min3", tmp_min[3]);
                        editor.putString("tmp_min4", tmp_min[4]);
                        editor.putString("tmp_min5", tmp_min[5]);
                        editor.putString("tmp_min6", tmp_min[6]);
private void initData()
{
    editor = MySharedpreference.getInstance(Main2Activity.this);
    ArrayList<WeatherItem> list= new ArrayList<WeatherItem>();
    SharedPreferences sp = getSharedPreferences("data", MODE_PRIVATE);
    list.add(new WeatherItem("1", Float.parseFloat(sp.getString("tmp_max0", ""))));
    list.add(new WeatherItem("2",Float.parseFloat(sp.getString("tmp_max1", ""))));
    list.add(new WeatherItem("3", Float.parseFloat(sp.getString("tmp_max2", ""))));
    list.add(new WeatherItem("4",Float.parseFloat(sp.getString("tmp_max3", ""))));
    list.add(new WeatherItem("5",Float.parseFloat(sp.getString("tmp_max4", ""))));
    list.add(new WeatherItem("6",Float.parseFloat(sp.getString("tmp_max5", ""))));
    list.add(new WeatherItem("7", Float.parseFloat(sp.getString("tmp_max6", ""))));
    chart1.SetTuView(list, "maximum temperature:");//Unit: Celsius
chart1.invalidate();
    ArrayList<WeatherItem> list1= new ArrayList<WeatherItem>();
    list1.add(new WeatherItem("",Float.parseFloat(sp.getString("tmp_min0", ""))));
    list1.add(new WeatherItem("",Float.parseFloat(sp.getString("tmp_min1", ""))));
    list1.add(new WeatherItem("", Float.parseFloat(sp.getString("tmp_min2", ""))));
    list1.add(new WeatherItem("",Float.parseFloat(sp.getString("tmp_min3", ""))));
    list1.add(new WeatherItem("", Float.parseFloat(sp.getString("tmp_min4", ""))));
    list1.add(new WeatherItem("",Float.parseFloat(sp.getString("tmp_min5", ""))));
    list1.add(new WeatherItem("",Float.parseFloat(sp.getString("tmp_min6", ""))));
   chart2.SetTuView(list1, "Minimum temperature:");
  chart2.invalidate();
}

8,sharedpreference

In order to save the setting parameters of the software, Android platform provides us with a SharedPreferences interface, which is a lightweight storage class, especially suitable for saving the software configuration parameters. Use SharedPreferences to save data. Behind it is an xml file to store data. The file is stored in / data/data//shared_prefs directory. Because this project does not use the server database to save data, it is particularly important for the shared preference to transfer the acquired city information among various activiti es. In addition to the above mentioned, after selecting a place to query, the location information will be transferred to the weather query module through storage to the sharedpreference, the location information will be transferred to the weather query module through the sharedpreference during positioning, and the temperature data will be transferred to the chart drawing module through the sharedpreference after the weather query is obtained, and the sharedpreference will be read each time the app is pulled down and refreshed and opened The city information in is updated to ensure that the last city weather queried before the last exit can be obtained every time you enter the app, which is very convenient. The read-write format is as follows:

//Write operation
SharedPreferences sp = mContext.getSharedPreferences("data", MODE_PRIVATE);
//Get editor
SharedPreferences.Editor editor = sp.edit(); 
//Save String data here kindItemBean.getName() is the data that needs to be passed
editor.putString("goodsname", kindItemBean.getName()); 
//Submit the modification, otherwise it will not take effect
editor.commit();     

//Read operation
SharedPreferences sp = getSharedPreferences("data", MODE_PRIVATE);
//The second parameter is the default value. If the key does not exist, the default value will be returned
String goodsname = sp.getString("goodsname", "");

9. Common bug s

1. The location in the simulator will not change all the time in Beijing
Solution: generally, it's a problem of simulator positioning. The mobile terminal can be positioned, so it's necessary to install an app on the mobile phone to try.
2. Null pointer is abnormal after flashing
Solution: we often encounter the situation of opening app to flash back directly. Select run in the command window under AS to see the flash back reason. Generally, it is a null pointer exception, and the following code prompt appears:


Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'xxxxxxxxxxxx' on a null object reference

This phenomenon is basically due to the process and view mismatch. For example, adding a control but not defined in the layout is a null pointer exception. Therefore, it is necessary to check the correlation between the layout and activity carefully to find out the problem.

10. Source code

This project is obtained by modifying and adding functions on the online open-source demo. If there is any infringement, please inform in time. As the school test is not finished yet, the source code will not be disclosed temporarily. If necessary, you can trust the blogger privately, and open source will be carried out after the test.

Topics: Android Maven Mobile Database