코로나 API 이용하여 어플 만들기 * 2/24일 수정

1. 개요

  • 만들게 된 이유: 코로나 현황을 홈페이지나 어플로 들어가 확인하기 귀찮아 API정보를 받아와 위젯으로 바탕화면에서 바로바로 볼 수 있게 하기 위해 제작

  • 공부 해야할 내용

  1. 공공 api 이용 방법
  2. 위젯 클래스 이용 방법
    2-1 ROOM(DB) 이용하기
  3. UI 설계하기
  4. 스마트폰 해상도별로 대응하기

1. 공공 API 이용하기

  • 원하는 공공 API 찾기
    https://www.data.go.kr/index.do 에서
    코로나 감영현황 조회 서비스를 신청하여 키를 받았습ㅂ니다.
    https://www.data.go.kr/tcs/dss/selectApiDataDetailView.do?publicDataPk=15043376
    서비스 신청 후 1~2시간 후면 인증키가 발급되고 인증키가 발급 된다해도 바로 API를 이용할 수
    있는 것은 아니였었습니다.(이것도 모르고 3시간 동안 API 확인 단계에서 헤맸습니다...)

    인증키를 받은 후 5~24시간 이후에 미리보기를 눌러 화면 같이 API 자료가 잘 나오는지 확인 후에 API를 받아 사용 할 수 있습니다.

    그 후 참고 문서를 다운 받아 각 API에 있는 변수와 파일 형식 등을 확인 가능합니다

  • 앱 기본 UI 틀 잡기
    어플의 메인 화면은 간단하게 현 상황을 받아 텍스트뷰에 띄우는 식으로 만들었습니다.

  • 앱 위젯 화면
    앱 위젯 화면은 네이버에 나오는 기본 형식과 비슷하게 하려 했습니다.

  • API이용 하기
API는 처음 활용해봐서 많은 시행 착오를 겪었습니다. 내가 받은 API는 XML 파일이였기에 XML 파싱을 하여 
list에 저장을 해야했다. 이 부분 또한 몰라 구글링을 통해 여러 가지 코드를 써가며 나에게 맞는 코드를 찾아서 개발하였습니다.

제일 먼저 api를 접속하여 보면

item 이라는 태그로 시작되어 그 안에 모든 정보가 반복되어 있는 것을 볼 수 있습니다.
이것을 기준으로 안드로이드 스튜디오에서 파싱하여 사용하면 됩니다.

안드로이드 스튜디오에선 xml 파싱을 위해
우선 2가지가 필요하다.
XmlPullParser 과
AsyncTask 이다.

AsynceTask - https://youngest-programming.tistory.com/11 아주 상세하게 나와있습니다.

XmlPullParser-https://developer.android.com/reference/org/xmlpull/v1/XmlPullParser

두 문서를 참고하여 메인 엑티비티에서 xml를 파싱 하여 DB에 저장하였습니다.

MainActivity.java


package com.lg.covid_19;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.room.Room;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import org.w3c.dom.Text;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;

public class MainActivity extends AppCompatActivity {


	//레이아웃에 있는 뷰 들과 API URL 등을 선언해주었다.
    final String TAG = "MainActivity";
    private String requestUrl;
    ArrayList<Item> list = null;
    Item bus = null;
    TextView date_view;
    TextView decide_cnt;
    TextView exam_cnt;
    TextView death_cnt;
    TextView clear_cnt;
    TextView today_decide_cnt;
    TextView today_exam_cnt;
    TextView today_death_cnt;
    TextView toady_clear_cnt;
    TextView decide;

    InformationDatabase db;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //db 초기화
        db = Room.databaseBuilder(this, InformationDatabase.class, "information_database").
                allowMainThreadQueries().build();

	
   	//각 레이아웃들 선언
    
        date_view = (TextView) findViewById(R.id.data_view);
        decide_cnt = (TextView) findViewById(R.id.decide_cnt);
        exam_cnt = (TextView) findViewById(R.id.exam_cnt);
        clear_cnt = (TextView) findViewById(R.id.clear_cnt);
        death_cnt = (TextView) findViewById(R.id.death_cnt);
        today_decide_cnt = (TextView) findViewById(R.id.today_decide_cnt);
        today_exam_cnt = (TextView) findViewById(R.id.today_exam_cnt);
        today_death_cnt = (TextView) findViewById(R.id.today_death_cnt);
        toady_clear_cnt = (TextView) findViewById(R.id.today_clear_cnt);
        decide = (TextView) findViewById(R.id.decide);

	AysyncTask 초기화 및 실행

        MyAsyncTask myAsyncTask = new MyAsyncTask();
        myAsyncTask.execute();
        System.out.println("list 불러오기 " + list);
    }


    public class MyAsyncTask extends AsyncTask<String, Void, String> {

        Date nowDate = new Date(); //api에서 현재 날짜 정보를 가져오기 위해 선언하였다.
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd"); //api속 날짜 형식과 맞도록 포맷
        String now_date = simpleDateFormat.format(nowDate); 
        GregorianCalendar yd = new GregorianCalendar();
        int yester = yd.get(Calendar.DATE - 1); 
       


        @Override
        protected String doInBackground(String... strings) {
            Log.d("파싱이 시작됩니다", "파싱 시작");
            System.out.println(yester);
            //현재 날짜 기준 2일전까지 데이터를 저장하기 위함이다 
            이유는 12시에 날짜가 바뀜에 따라 새롭게 저장되는데 api 업데이트 시간이 오전 9~10시 사이로 그 전까지는 당일 날짜의 자료가 null값이 되어 2일 전까지 저장하게하였다.
            yd.add(Calendar.DATE, -2); 
            String yesterday = simpleDateFormat.format(yd.getTime());
            System.out.println("오늘 날짜 : " + now_date);
            System.out.println("어제 날짜 : " + yesterday);

            requestUrl = "http://openapi.data.go.kr/openapi/service/rest/Covid19/getCovid19InfStateJson?serviceKey=받아온 서비스 키 &pageNo=1&numOfRows=10&startCreateDt=" + yesterday + "&endCreateDt=" + now_date;
            try {
                boolean b_date = false;
                boolean b_decideCnt = false;
                boolean b_examCnt = false;
                boolean b_deathCnt = false;
                boolean b_clearCnt = false;
                boolean b_accExamCnt = false;


                URL url = new URL(requestUrl);
                InputStream is = url.openStream();
                XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
                XmlPullParser parser = factory.newPullParser();
                parser.setInput(new InputStreamReader(is, "UTF-8"));

                String tag;
                int eventType = parser.getEventType();

                while (eventType != XmlPullParser.END_DOCUMENT) {
                    switch (eventType) {
                        case XmlPullParser.START_DOCUMENT:
                            list = new ArrayList<Item>();
                            System.out.println("문서 시작");
                            break;
                        case XmlPullParser.END_DOCUMENT:
                            break;
                        case XmlPullParser.END_TAG: //마지막 태크가 item이면 bus안의 내용 리스트에 저장
                            if (parser.getName().equals("item") && bus != null) {
                                list.add(bus);
                                System.out.println("중간 리스트 점검" + list);
                            }
                            break;
                        case XmlPullParser.START_TAG:// item 시작 태그시 안에 내용 버스에넣기 위한 작업
                            if (parser.getName().equals("item")) {
                                bus = new Item();
                            }
                            //각각의 api속 변수명이다.
                            if (parser.getName().equals("stateDt")) b_date = true;
                            if (parser.getName().equals("decideCnt")) b_decideCnt = true;
                            if (parser.getName().equals("examCnt")) b_examCnt = true;
                            if (parser.getName().equals("deathCnt")) b_deathCnt = true;
                            if (parser.getName().equals("clearCnt")) b_clearCnt = true;
                            if (parser.getName().equals("accExamCnt")) b_accExamCnt = true;
                            break;
                        case XmlPullParser.TEXT:
                            if (b_date) {
                                bus.setDate(parser.getText());
                                b_date = false;
                            } else if (b_decideCnt) {
                                bus.setDecideCnt(parser.getText());
                                b_decideCnt = false;
                            } else if (b_examCnt) {
                                bus.setExamCnt(parser.getText());
                                b_examCnt = false;
                            } else if (b_deathCnt) {
                                bus.setDeathCnt(parser.getText());
                                b_deathCnt = false;
                            } else if (b_clearCnt) {
                                bus.setClearCnt(parser.getText());
                                b_clearCnt = false;
                            } else if (b_accExamCnt) {
                                bus.setAccExamCnt(parser.getText());
                                b_accExamCnt = false;
                            }
                            break;
                    }

                    eventType = parser.next();

                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

//위 과정이 다 끝나고 메인 스레드에서 UI에 각 항목들을 setText 시켜준다.

        protected void onPostExecute(String s) {
            super.onPostExecute(s);

            date_view.setText(list.get(0).date);
            decide_cnt.setText(list.get(0).decideCnt);
            exam_cnt.setText(list.get(0).examCnt);
            clear_cnt.setText(list.get(0).clearCnt);
            death_cnt.setText(list.get(0).deathCnt);
            today_decide_cnt.setText(Integer.toString(Integer.parseInt(list.get(0).decideCnt) - Integer.parseInt(list.get(1).decideCnt)));
            today_exam_cnt.setText(Integer.toString(Integer.parseInt(list.get(0).examCnt) - Integer.parseInt(list.get(1).examCnt)));
            today_death_cnt.setText(Integer.toString(Integer.parseInt(list.get(0).deathCnt) - Integer.parseInt(list.get(1).deathCnt)));
            toady_clear_cnt.setText(Integer.toString(Integer.parseInt(list.get(0).clearCnt) - Integer.parseInt(list.get(1).clearCnt)));
            decide.setText(today_decide_cnt.getText() + " 명 발생하였습니다");

	//마지막으로 db에 list를 넣는다.
            db.informationDAO().insertAll(list);

            System.out.println(db.informationDAO().getAll());


        }
    }


}
  • Room 사용하여 내부 DB 다루기
    메인에서 xml 파싱하여 데이터 값을 저장해 놓은 list를 가져오기위해서 방법을 찾아보았습니다.
    DB를 이용한 방법과 sharedpreferences 를 이용한 방법등이 있었는데
    어플 개발자 오픈톡방에서 물어본 결과 sharedpreferences은 DB보다 안정성이 떨어지다고 하여 DB 다룰 공부도 해볼겸 Room 을 선택하였습니다.

룸 사용 법 및 공식 문서
https://developer.android.com/jetpack/androidx/releases/room?hl=ko

Item.java -> DB에 저장한 테이블이다.


package com.lg.covid_19;

import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;

@Entity(tableName = "info")
public class Item {
    @PrimaryKey
    @NonNull
    String date; // 현재 날짜 (현재 날짜를 primarykey로 줫다)
    String decideCnt; //확진자 수
    String examCnt; //검사중 환자수
    String deathCnt; //사망한 환자수
    String clearCnt; //격리 해제
    String accExamCnt; //누적 검사 수 


    public Item() {
    }

    public Item(String date, String decideCnt, String accExamCnt, String clearCnt, String deathCnt) {
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }


    public String getDecideCnt() {
        return decideCnt;
    }

    public void setDecideCnt(String decideCnt) {
        this.decideCnt = decideCnt;
    }

    public String getExamCnt() {
        return examCnt;
    }

    public void setExamCnt(String examCnt) {
        this.examCnt = examCnt;
    }

    public String getDeathCnt() {
        return deathCnt;
    }

    public void setDeathCnt(String deathCnt) {
        this.deathCnt = deathCnt;
    }

    public String getClearCnt() {
        return clearCnt;
    }

    public void setClearCnt(String clearCnt) {
        this.clearCnt = clearCnt;
    }

    public String getAccExamCnt() {
        return accExamCnt;
    }

    public void setAccExamCnt(String accExamCnt) {
        this.accExamCnt = accExamCnt;
    }

    @Override
    public String toString() {
        return "Item{" +
                "date='" + date + '\'' +
                ", decideCnt='" + decideCnt + '\'' +
                ", examCnt='" + examCnt + '\'' +
                ", deathCnt='" + deathCnt + '\'' +
                ", clearCnt='" + clearCnt + '\'' +
                '}';
    }
}

InformationDAO -> Room에서 Item를 다루기 위한 DAO입니다.


package com.lg.covid_19;

import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.Update;

import java.util.ArrayList;
import java.util.List;

@Dao
public interface InformationDAO {

    @Query("SELECT * FROM info")
    List<Item> getAll();

    @Query("DELETE FROM info")
    public void droptable();

    @Insert(onConflict = OnConflictStrategy.REPLACE) //중복 데이터가 있을 시 덮어 쓰기를 위한 코드
    void insertAll(List<Item> list);

    @Delete
    void delete(Item item);

    @Update
    void updateInfo(Item item);
}

InformationDatabase.java ->데이터 베이스 클래스이다.

package com.lg.covid_19;

import android.content.Context;
import android.os.strictmode.InstanceCountViolation;

import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;

@Database(entities = {Item.class}, version = 1, exportSchema = false)
public abstract class InformationDatabase extends RoomDatabase {
    public abstract InformationDAO informationDAO();

    private static InformationDatabase INSTANCE;

    public static InformationDatabase getDatabase(final Context context) {
        if (INSTANCE == null) {
            synchronized (InformationDatabase.class) {
                if (INSTANCE == null) {
                    INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                            InformationDatabase.class, "information_database").build();
                }
            }
        }
        return INSTANCE;
    }
}

covid_19_widget.java

위젯을 다룰 때 매우 많은 시행착오를 겪었습니다.. 다른 클래스와도 사용법이 다르고 레이아웃 또한
지원이 안되는 뷰가 많았기에 많은 정보를 찾아보았습니다.
https://developer.android.com/guide/topics/appwidgets - 공식 개발 문서


package com.lg.covid_19;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Button;
import android.widget.RemoteViews;
import android.widget.TextView;
import android.widget.Toast;

import androidx.room.Room;

import org.w3c.dom.Text;

import java.util.ArrayList;
import java.util.List;

import static android.widget.Toast.LENGTH_LONG;

/**
 * Implementation of App Widget functionality.
 */
public class covid_19_widget extends AppWidgetProvider {


    static List<Item> list = new ArrayList<Item>();
    Context context;
    TextView date_view;
    Button btn_re;

    private static final String ACTION_BTN = "ButtonClick";

//위젯이 처음실행 될 때 db에서 list 정보를 가져와 위젯 뷰에 뿌릴 수 있게 하기위함
    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {

        InformationDatabase db = Room.databaseBuilder(context, InformationDatabase.class, "information_database").
                allowMainThreadQueries().build();
        list = db.informationDAO().getAll();
        System.out.println("위젯 클래스에서 : " + list);
        // Construct the RemoteViews object
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.covid_19_widget);
        Intent intent = new Intent(context, covid_19_widget.class).setAction(ACTION_BTN);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
        views.setOnClickPendingIntent(R.id.btn_re, pendingIntent);
        views.setTextViewText(R.id.wg_today_decide_cnt, Integer.toString(Integer.parseInt(list.get(0).decideCnt) -  Integer.parseInt(list.get(1).decideCnt)));
        views.setTextViewText(R.id.wg_today_exam_cnt, Integer.toString(Integer.parseInt(list.get(0).examCnt) -  Integer.parseInt(list.get(1).examCnt)));
        views.setTextViewText(R.id.wg_today_death_cnt, Integer.toString(Integer.parseInt(list.get(0).deathCnt) -  Integer.parseInt(list.get(1).deathCnt)));
        views.setTextViewText(R.id.wg_today_clear_cnt, Integer.toString(Integer.parseInt(list.get(0).clearCnt) -  Integer.parseInt(list.get(1).clearCnt)));
        views.setTextViewText(R.id.wg_data_view, list.get(0).date);
        views.setTextViewText(R.id.wg_decide_cnt, list.get(0).decideCnt);
        views.setTextViewText(R.id.wg_exam_cnt, list.get(0).examCnt);
        views.setTextViewText(R.id.wg_clear_cnt, list.get(0).clearCnt);
        views.setTextViewText(R.id.wg_death_cnt, list.get(0).deathCnt);
        views.setTextViewText(R.id.wg_decide, Integer.toString(Integer.parseInt(list.get(0).decideCnt) - Integer.parseInt(list.get(1).decideCnt)));
        // Instruct the widget manager to update the widget
        appWidgetManager.updateAppWidget(appWidgetId, views);
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        // 위젯 갱신 주기에 따라 위젯을 갱신할 떄 호출,
        for (int appWidgetId : appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId);
        }
    }

    @Override
    public void onEnabled(Context context) { // 위젯이 처음 생성될 때 호출


    }

    @Override
    public void onDisabled(Context context) { // 위젯의 마지막 인스턴스가 제거될 때
        // Enter relevant functionality for when the last widget is disabled
    }

//새로고침 버튼을 눌렀을 시 뷰를 다시 그리기
    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        String action = intent.getAction();
        if (action.equals(ACTION_BTN)) {
            Log.d("이벤트 클릭 테스트 ", "클릭!");
            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.covid_19_widget);
            ComponentName componentName = new ComponentName(context, covid_19_widget.class);
            InformationDatabase db = Room.databaseBuilder(context, InformationDatabase.class, "information_database").
                    allowMainThreadQueries().build();
            list = db.informationDAO().getAll();
            views.setTextViewText(R.id.wg_today_decide_cnt, Integer.toString(Integer.parseInt(list.get(0).decideCnt) -  Integer.parseInt(list.get(1).decideCnt)));
            views.setTextViewText(R.id.wg_today_exam_cnt, Integer.toString(Integer.parseInt(list.get(0).examCnt) -  Integer.parseInt(list.get(1).examCnt)));
            views.setTextViewText(R.id.wg_today_death_cnt, Integer.toString(Integer.parseInt(list.get(0).deathCnt) -  Integer.parseInt(list.get(1).deathCnt)));
            views.setTextViewText(R.id.wg_today_clear_cnt, Integer.toString(Integer.parseInt(list.get(0).clearCnt) -  Integer.parseInt(list.get(1).clearCnt)));
            views.setTextViewText(R.id.wg_data_view, list.get(0).date);
            views.setTextViewText(R.id.wg_decide_cnt, list.get(0).decideCnt);
            views.setTextViewText(R.id.wg_exam_cnt, list.get(0).examCnt);
            views.setTextViewText(R.id.wg_clear_cnt, list.get(0).clearCnt);
            views.setTextViewText(R.id.wg_death_cnt, list.get(0).deathCnt);
            views.setTextViewText(R.id.wg_decide, Integer.toString(Integer.parseInt(list.get(0).decideCnt) - Integer.parseInt(list.get(1).decideCnt)));
            appWidgetManager.updateAppWidget(componentName, views);
            Toast.makeText(context,"새로고침 되었습니다",Toast.LENGTH_SHORT).show();
        }
    }
}

코드를 전부 이해하고 짠 코드가 아니기에 불필요한 코드도 많은거 같네요
혹시라도 글을 읽고 수정해야 하는 부분이 있으면 댓글로 말씀해주세요.

2.12 일 수정

어플을 3일 정도 돌려본 결과 몇 가지 문제점이 발생했습니다.

1.자동 업데이트의 미흡점

2.코드의 중복성과 지저분함

3.매일 00시에 의문의 데이터 하나가 DB에 들어간다는 점

1번은 자동 업데이트의 미흡함을 보완하고자 새로고침 버튼을 만들어 놓고 , api 정보가 업데이트 되는 보편적 시간인 10시에 푸쉬알림을 통해 사용자가 새로고침을 누를 수 있도록 하였습니다. 이는 추후에 더 보완해 번거로움을 없게 할 예정입니다.
이 과정에도 문제점이 있었습니다.

문제점 푸쉬알림 -  맨 처음 코드를 짜서 돌렸을 때 시간이 지난 경우 앱을 실행 시킬 떄마다 알림이 왔었습니다. 이를 인터넷에 검색해보니 시간이 지난 경우 다음날 같은 시간으로 설정해주는 코드가있어 추가하여 해결했습니다.

AlarmRecevier.class

package com.lg.covid_19;

import android.accounts.AbstractAccountAuthenticator;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;

import androidx.core.app.NotificationCompat;

public class AlarmRecevier extends BroadcastReceiver {

    NotificationManager manager;
    NotificationCompat.Builder builder;

    //오레오 이상은 반드시 채널을 설정해줘야 Notification이 작동함
    private static String CHANNEL_ID = "channel1";
    private static String CHANNEL_NAME = "Channel1";

    @Override
    public void onReceive(Context context, Intent intent) {
        AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);

        builder = null;
        manager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            manager.createNotificationChannel(
                    new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT)
            );
            builder = new NotificationCompat.Builder(context, CHANNEL_ID);
        } else {
            builder = new NotificationCompat.Builder(context);
        }

        //알림창 클릭 시 activity 화면 부름
        Intent intent2 = new Intent(context, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(context,101,intent2, PendingIntent.FLAG_UPDATE_CURRENT);

        //알림창 제목
        builder.setContentTitle("새로고침을 눌러주세요!");
        //알림창 아이콘
        builder.setSmallIcon(R.drawable.ic_launcher_background);
        //알림창 터치시 자동 삭제
        builder.setAutoCancel(true);

        builder.setContentIntent(pendingIntent);

        Notification notification = builder.build();
        manager.notify(1,notification);

    }
}

MainActivity 추가 부분


private AlarmManager alarmManager;
    private GregorianCalendar mCalender;
    private NotificationManager notificationManager;
    NotificationCompat.Builder builder;



public void setAlarm() {
        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        mCalender = new GregorianCalendar();
        setContentView(R.layout.activity_main);

        Intent receiverIntent = new Intent(MainActivity.this, AlarmRecevier.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, receiverIntent, 0);
        Date nowDate = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String now_date = simpleDateFormat.format(nowDate);
        System.out.println("시간은 " + now_date);
        String from = now_date + " 10:00:00"; //임의로 날짜와 시간을 지정

        //날짜 포맷을 바꿔주는 소스코드
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date datetime = null;
        try {
            datetime = dateFormat.parse(from);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        Calendar calendar = Calendar.getInstance();

        calendar.setTime(datetime);
		// 시간 초과시 다음날 같은 시간으로 설정 해주는 코드
        if (calendar.before(Calendar.getInstance())) {
            calendar.add(Calendar.DATE, 1);
        }


        System.out.println("설정된 시간 " + calendar.getTime());

        alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);
    }

2번은 중복 코드는 최대한 메소드화하여 코드를 줄였습니다.

3번은 매일 12시가 되면 db안에 맨 마지막 내용이 맨 앞으로 이동하는 정체모를 일이 계속 일어났습니다. 처음엔 어떻게 해결 하는지 감이 안잡혀 이것저것 건드려보고 질문해본 결과
가장 기본적인 정렬을 생각을 못했음을 깨달았습니다.

이 후 compareTo 함수를 사용해서 db에 넣기 전 정렬을 해줌으로서 이상현상을 방지 하도록 했습니다. 다음 12시에 다시 확인해봐야겠습니다.
-> 2월 14일 데이터 정렬되서 들어가는거 확인 했습니당 ㅠㅠㅠ 가장 기본적인 정렬을
잊다니.. 기본기가 중요하네요..

2월 24일 수정

지역별 Api를 받아 오기 위해 Main.activity 안에있는 APi 파싱클래스를 분리하는 시도를 했습니다. 그 와중에 많은 오류와.. 어려움을 겪었습니다. 그것은 클래스에선 액티비티에서 사용하는 콘텍트가 따로 없어 db정보를 불러오지 못한다는 것이였습니다 이를 위해선 메인의 커콘텍트를 불러와야 했습니다 이 방법을 수없이 찾고 어려움을 겪던 와중 단톡방 질문을 통해 생성자를 통해 불러오면 된다는 것을 배우게 되었습니다. 간단한 코드였지만 그 간단함 조차 몰랐습니다. 코드는 다음과 같습니다.

Main.java 추가 부분

CoronaAsnk coronaAsnk = new CoronaAsnk(MainActivity.this); <-이렇게 콘텐트를 넘겨 줄 수 있습니다.

CoromnaAsnk 추가 부분

 Context context;
    public CoronaAsnk(MainActivity mainActivity) {
        this.context =mainActivity;
    }

이제 지역별만 따로 구현 할 수있을거같습니다 ㅎㅎ

좋은 웹페이지 즐겨찾기