본문 바로가기
ICIA 수업일지

2021.09.29 수업일지(안드로이드 개발 기초, Kakao API, Google API)

by 주성씨 2021. 9. 29.

- 카카오 검색 API를 이용해 검색 페이지를 만들어보도록 하겠다.
- 안드로이드(부록) page 28
- 프레그먼트는 액티비티를 분할해서 사용할 수 있게 해주는 라이브러리다.
- ex05 새로운 프로젝트를 생성해주도록 하겠다.

- build.gradle

.....
android {
	// sdkversion을 30으로 수정해주고 minsdkversion을 16으로 그대로 쓰고 싶으면
    // 아래 compileoptions를 추가 아니면 26으로 변경 후 sync now click
    compileSdkVersion 30
    buildToolsVersion "30.0.0"

    defaultConfig {
        applicationId "com.example.ex05"
        minSdkVersion 26
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    // new
	compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

}
.....

 

- build.gradle - 라이브러리 추가

dependencies {
	.....
	implementation 'com.android.support:design:30.0.0' // 플로팅액션바 이용을 위해서 사용
	implementation 'com.squareup.picasso:picasso:2.5.2' // 이미지 저장을 위해서 사용
}

 

- 인터넷 이용을 위한 권한 설정

- src/main/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.ex05">
    <uses-permission android:name="android.permission.INTERNET"/>
    <application
.....
    </application>

</manifest>

 

- vertor asset을 이용해 필요한 이미지를 우선 가져다 두겠다.

- more, search, assignment, menu, book, local dining 을 가져다 둔다.

 

- 타이틀을 변경하고 메뉴 이미지를 설정해준다.

- src/main/java/com/example/ex05/MainActivity.java

package com.example.ex05;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getSupportActionBar().setTitle("카카오 검색");
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);

    }
}

 

확인

 

 

- 아래와 같이 만들어보겠다.

- src/main/res/layout/(new)drawer_view.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="300sp"
 android:layout_height="match_parent"
 android:background="#5559b4"
 android:orientation="vertical"
 android:id="@+id/drawerView"
 android:layout_gravity="start">
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:textColor="#ffffff"
 android:text="홍길동님"
 android:textSize="30sp"
 android:layout_gravity="center"
 android:layout_marginTop="50sp"/>
 <ImageView
 android:layout_width="200sp"
 android:layout_height="200sp"
 android:layout_gravity="center"
 android:src="@drawable/ic_launcher_foreground"
 android:layout_marginTop="30sp"/>
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_gravity="center"
 android:textColor="#ffffff"
 android:textSize="20sp"
 android:text="오늘도 즐거운 하루되세요!"
 android:layout_marginTop="30sp"/>
</LinearLayout>

 

- 위의 xml을 메인엑티비티에 인클루드 하겠다.

- src/main/res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:id="@+id/drawerLayout">
    <include layout="@layout/drawer_view"/> <<<---
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.drawerlayout.widget.DrawerLayout>

 

- menu 버튼을 클릭시에도 보여줄 수 있도록 하겠다.

- src/main/java/com/example/ex05/MainActivity.java

package com.example.ex05;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.drawerlayout.widget.DrawerLayout;

import android.os.Bundle;
import android.view.MenuItem;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getSupportActionBar().setTitle("카카오 검색");
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);

    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        DrawerLayout layout = findViewById(R.id.drawerLayout);
        LinearLayout view = findViewById(R.id.drawerView);
        if(layout.isDrawerOpen(view)){
            layout.closeDrawer(view);
        }else{
            layout.openDrawer(view);
        }
        return super.onOptionsItemSelected(item);
    }
}

 

 

확인

 

 

- 아래와 같이 프레그먼트를 생성해주도록 하겠다.

- 블로그, 도서, 지역 프래그먼트 생성

- src/main/java/com/example/ex05/(new)BLogFragment.java

- src/main/java/com/example/ex05/(new)BookFragment.java

- src/main/java/com/example/ex05/(new)LocalFragment.java

- 각 새로 생성된 .xml에서 text를 "블로그", "도서검색", "지역검색"으로 변경한다.

 

프레그먼트 생성 경로

 

- 메인 페이지의 탭 레이아웃을 만들어주도록 하겠다.

- src/main/res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:id="@+id/drawerLayout">
    <include layout="@layout/drawer_view"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
<!--        여러개 프레그먼트 넣는 뷰페이저-->
        <androidx.viewpager.widget.ViewPager
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="697dp"
            android:layout_weight="1"/>
        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tab"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#00BCD4"
            app:tabTextColor="#FFFFFF"/>
    </LinearLayout>
</androidx.drawerlayout.widget.DrawerLayout>

 

- src/main/java/com/example/ex05/MainActivity.java

package com.example.ex05;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.viewpager.widget.ViewPager;

import android.os.Bundle;
import android.view.MenuItem;
import android.widget.LinearLayout;

import com.google.android.material.tabs.TabLayout;

public class MainActivity extends AppCompatActivity {
    // 아이디 저장할 전역변수
    ViewPager pager;
    TabLayout tab;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getSupportActionBar().setTitle("카카오 검색");
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);

        pager = findViewById(R.id.pager);
        tab = findViewById(R.id.tab);

        tab.addTab(tab.newTab().setText("블로그"));
        tab.addTab(tab.newTab().setText("도서"));
        tab.addTab(tab.newTab().setText("지역"));
        tab.getTabAt(0).setIcon(R.drawable.ic_blog);
        tab.getTabAt(1).setIcon(R.drawable.ic_book);
        tab.getTabAt(2).setIcon(R.drawable.ic_local);
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        DrawerLayout layout = findViewById(R.id.drawerLayout);
        LinearLayout view = findViewById(R.id.drawerView);
        if(layout.isDrawerOpen(view)){
            layout.closeDrawer(view);
        }else{
            layout.openDrawer(view);
        }
        return super.onOptionsItemSelected(item);
    }
}

 

확인

 

 

- 이제 프레그먼트를 메인에 넣어줄 수 있게 어뎁터를 생성해주도록 하겠다.

- src/main/java/com/example/ex05/MainActivity.java

.....

        // 페이저 어뎁터 생성
        PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager());
        pager.setAdapter(pagerAdapter);
    }

    class PagerAdapter extends FragmentStatePagerAdapter{

        public PagerAdapter(@NonNull FragmentManager fm) {
            super(fm);
        }

        @NonNull
        @Override
        public Fragment getItem(int position) {
            switch (position){
                case 0:
                    return new BLogFragment();
                case 1:
                    return new BookFragment();
                case 2:
                    return new LocalFragment();
                default:
                    return null;
            }
        }

        @Override
        public int getCount() {
//            프레그먼트가 3개이니 3으로 고정
            return 3;
        }
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
.....

 

 

- 위에서는 드래그하면 Tab을 변경하였다면 이번에는 Tab 클릭시 페이지를 변경해주도록 하겠다.

 

.....
        // 페이저 어뎁터 생성
        PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager());
        pager.setAdapter(pagerAdapter);
        // Tab 클릭시 페이지 변경
        pager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tab));
        tab.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                pager.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });
    }
.....

확인

 

- 이제 프레그먼트 디자인을 해주도록 하겠다.

- 우선 카카오 클래스를 생성하겠다.

- src/main/java/com/example/ex05/(new)Kakao.java

package com.example.ex05;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class Kakao {
    public static String connect(String apiURL) {
        try {
            URL url = new URL(apiURL);
            HttpURLConnection con = (HttpURLConnection)url.openConnection();
            con.setRequestMethod("GET");
            con.setRequestProperty("Authorization", "KakaoAK 'REST API key'");
            int responseCode = con.getResponseCode();
            BufferedReader br;
            if(responseCode==200) { // 정상 호출인 경우
                br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
            } else { //에러 발생가 발생한 경우
                br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
            }
            String inputLine;
            StringBuffer response = new StringBuffer();
            while ((inputLine = br.readLine()) != null) {
                response.append(inputLine);
            }
            br.close();
            System.out.println(response.toString());
            return response.toString();
        }catch (Exception e) {
            return e.toString();
        }
    }
}

 

 

- 이제 블로그, 도서, 지역 프레그먼트를 차례차례 생성해주겠다.

- src/main/java/com/example/ex05/BLogFragment.java

package com.example.ex05;

import android.os.AsyncTask;
import android.os.Bundle;

import androidx.fragment.app.Fragment;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class BLogFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_b_log, container, false);
        new BLogThread().execute();
        return view;
    }

    // 카카오 접속을 위한 backthread를 생성한다.
    // Kakao.class의 connect method를 호출하겠다.
    class BLogThread extends AsyncTask<String, String, String>{

        @Override
        protected String doInBackground(String... strings) {
            String url="https://dapi.kakao.com/v2/search/web?query=안드로이드";
            Kakao.connect(url);
            return null;
        }
    }
}

 

Kakao.class에 의해서 콘솔에 찍힌것을 확인할 수 있다.

 

package com.example.ex05;

import android.os.AsyncTask;
import android.os.Bundle;

import androidx.fragment.app.Fragment;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import org.json.JSONArray;
import org.json.JSONObject;

public class BLogFragment extends Fragment {
    JSONArray jsonArray;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_b_log, container, false);
        new BLogThread().execute();
        return view;
    }

    // 카카오 접속을 위한 backthread를 생성한다.
    // Kakao.class의 connect method를 호출하겠다.
    class BLogThread extends AsyncTask<String, String, String>{

        @Override
        protected String doInBackground(String... strings) {
            String url="https://dapi.kakao.com/v2/search/web?query=안드로이드";
            return Kakao.connect(url);
        }

        // doInBackground의 Kakao.connect(url)가 아래 s로 들어가게된다.
        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            try {
                jsonArray = new JSONObject(s).getJSONArray("documents");
                // 데이터를 잘 가지고 오는지 확인하는 부분 지워도 됨
                for(int i=0; i<jsonArray.length();i++){
                    JSONObject obj = jsonArray.getJSONObject(i);
                    System.out.println("title : "+obj.getString("title"));
                }
            }catch (Exception e){
                System.out.println("post error: "+ e.toString());
            }
        }
    }
}

 

데이터가 잘 나오는지 확인

 

 

- 이제 데이터를 레이아웃에 넣어주도록 하겠다.

- src/main/res/layout/fragment_b_log.xml

- src/main/res/layout/(new)item_blog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="10sp"
    android:elevation="3sp">
    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="제목위치"
        android:textSize="15sp"
        android:textStyle="bold"/>
    <TextView
        android:id="@+id/link"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="주소위치"
        android:textColor="#3F51B5"
        android:lines="1"
        android:ellipsize="end"/>
</LinearLayout>

 

- src/main/java/com/example/ex05/BLogFragment.java

package com.example.ex05;

.....

public class BLogFragment extends Fragment {
    JSONArray jsonArray;
    BlogAdapter blogAdapter = new BlogAdapter();
    ListView list;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_b_log, container, false);
        list = view.findViewById(R.id.list);
        new BLogThread().execute();
        return view;
    }

    // 카카오 접속을 위한 backthread를 생성한다.
    // Kakao.class의 connect method를 호출하겠다.
    class BLogThread extends AsyncTask<String, String, String>{

        @Override
        protected String doInBackground(String... strings) {
            // 실행
            String url="https://dapi.kakao.com/v2/search/web?query=안드로이드";
            return Kakao.connect(url);
        }

        // doInBackground의 Kakao.connect(url)가 아래 s로 들어가게된다.
        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            try {
                jsonArray = new JSONObject(s).getJSONArray("documents");
                list.setAdapter(blogAdapter);
            }catch (Exception e){
                System.out.println("post error: "+ e.toString());
            }
        }
    }

    // 출력 블로그 어뎁터 생성
    class BlogAdapter extends BaseAdapter{
.....

        @Override
        public View getView(int position, View view, ViewGroup viewGroup) {
            view = getLayoutInflater().inflate(R.layout.item_blog, viewGroup, false);
            try {
                JSONObject obj = jsonArray.getJSONObject(position);
                TextView title = view.findViewById(R.id.title);
                // xml에서 html 사용 - Html.fromhtml()
                title.setText(Html.fromHtml(obj.getString("title")));
                TextView link = view.findViewById(R.id.link);
                link.setText(obj.getString("url"));
            }catch (Exception e){
                System.out.println("뷰 오류 : " +e.toString());
            }
            return view;
        }
    }
}

 

확인

 

- 블로그 프레그먼트를 꾸며주도록 하겠다.

- src/main/res/layout/fragment_b_log.xml

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".BLogFragment">
    <EditText
        android:id="@+id/query"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="검색어"/>
    <ImageView
        android:id="@+id/search"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_search"
        android:layout_alignParentRight="true"
        android:layout_marginTop="5sp"/>
    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="블로그"
        android:layout_below="@id/query"/>
</RelativeLayout>

 

확인

 

- 검색 기능을 추가하겠다.

- src/main/java/com/example/ex05/BLogFragment.java

.....
public class BLogFragment extends Fragment {
    JSONArray jsonArray;
    BlogAdapter blogAdapter = new BlogAdapter();
    ListView list;
    String strQuery = "안드로이드";
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_b_log, container, false);
        list = view.findViewById(R.id.list);

        final EditText query = view.findViewById(R.id.query);
        ImageView search = view.findViewById(R.id.search);
        search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                strQuery = query.getText().toString();
                new BLogThread().execute();
            }
        });
        new BLogThread().execute();
        return view;
    }

    // 카카오 접속을 위한 backthread를 생성한다.
    // Kakao.class의 connect method를 호출하겠다.
    class BLogThread extends AsyncTask<String, String, String>{

        @Override
        protected String doInBackground(String... strings) {
            // 실행
            String url="https://dapi.kakao.com/v2/search/web?query="+strQuery;
            return Kakao.connect(url);
        }
.....

 

확인

 

- 도서 검색 xml은 블로그 검색 xml을 그대로 복사해준다.

- src/main/res/layout/fragment_book.xml

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".BookFragment">
    <EditText
        android:id="@+id/query"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="검색어"/>
    <ImageView
        android:id="@+id/search"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_search"
        android:layout_alignParentRight="true"
        android:layout_marginTop="5sp"/>
    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="도서"
        android:layout_below="@id/query"/>
</RelativeLayout>

 

- src/main/res/layout/(new)item_book.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#E3F3FA"
    android:padding="10sp"
    android:layout_margin="5sp"
    android:elevation="3sp">
    <ImageView
        android:id="@+id/thumbnail"
        android:layout_width="50sp"
        android:layout_height="50sp"
        android:src="@mipmap/ic_launcher"
        android:layout_marginRight="20sp"/>
    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="제목이 들어갑니다............"
        android:layout_toRightOf="@id/thumbnail"/>
    <TextView
        android:id="@+id/publisher"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="출판사 들어갑니다............"
        android:layout_toRightOf="@id/thumbnail"
        android:layout_below="@id/title"/>
    <TextView
        android:id="@+id/price"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="가격이 들어갑니다............"
        android:layout_toRightOf="@id/thumbnail"
        android:layout_below="@id/publisher"/>
</RelativeLayout>

 

- src/main/java/com/example/ex05/BookFragment.java

package com.example.ex05;

import android.os.AsyncTask;
import android.os.Bundle;

import androidx.fragment.app.Fragment;

import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.squareup.picasso.Picasso;

import org.json.JSONArray;
import org.json.JSONObject;

import java.text.DecimalFormat;


public class BookFragment extends Fragment {
    String strQuery = "파이썬";
    JSONArray jsonArray;
    BookAdapter bookAdapter = new BookAdapter();
    ListView list;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_book, container, false);
        list = view.findViewById(R.id.list);
        new BookThread().execute();
        final EditText query = view.findViewById(R.id.query);
        ImageView search = view.findViewById(R.id.search);
        search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                strQuery = query.getText().toString();
                new BookThread().execute();
            }
        });
        return view;
    }

    class BookThread extends AsyncTask<String, String, String>{
        @Override
        protected String doInBackground(String... strings) {
            String url = "https://dapi.kakao.com/v3/search/book?target=title&query="+strQuery;
            return Kakao.connect(url);
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            try {
                jsonArray = new JSONObject(s).getJSONArray("documents");
                list.setAdapter(bookAdapter);
            }catch (Exception e){
                System.out.println("book 오류 : "+e.toString());
            }
        }
    }

    class BookAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return jsonArray.length();
        }

        @Override
        public Object getItem(int i) {
            return null;
        }

        @Override
        public long getItemId(int i) {
            return 0;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            view = getLayoutInflater().inflate(R.layout.item_book, viewGroup, false);
            try {
                JSONObject obj = jsonArray.getJSONObject(i);
                ImageView thumbnail = view.findViewById(R.id.thumbnail);
                Picasso.with(getContext()).load(obj.getString("thumbnail")).into(thumbnail);
                TextView title = view.findViewById(R.id.title);
                title.setText(Html.fromHtml(obj.getString("title")));
                TextView publisher = view.findViewById(R.id.publisher);
                publisher.setText(obj.getString("publisher"));
                TextView price = view.findViewById(R.id.price);
                DecimalFormat df = new DecimalFormat("#,###원");
                price.setText(df.format(obj.getInt("price")));
            }catch (Exception e){
                System.out.println("뷰 오류 : "+ e.toString());
            }
            return view;
        }
    }
}

 

확인

 

- 지역 검색을 해주겠다.

- src/main/res/layout/fragment_local.xml

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".LocalFragment">
    <EditText
        android:id="@+id/query"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="검색어"/>
    <ImageView
        android:id="@+id/search"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_search"
        android:layout_alignParentRight="true"
        android:layout_marginTop="5sp"/>
    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="도서"
        android:layout_below="@id/query"/>
</RelativeLayout>

 

- src/main/res/layout/(new)item_local.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#E3F3FA"
    android:padding="10sp"
    android:layout_margin="5sp"
    android:elevation="3sp">
    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="장소명입니다."/>
    <TextView
        android:id="@+id/address"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="주소입니다."
        android:layout_below="@id/name"/>
    <TextView
        android:id="@+id/tel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="전화번호입니다."
        android:layout_below="@id/address"/>
    <ImageView
        android:id="@+id/map"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_baseline_location_on_24"
        android:layout_alignParentRight="true"
        android:layout_below="@id/name"/>
</RelativeLayout>

 

- src/main/java/com/example/ex05/LocalFragment.java

package com.example.ex05;

import android.os.AsyncTask;
import android.os.Bundle;

import androidx.fragment.app.Fragment;

import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import org.json.JSONArray;
import org.json.JSONObject;

public class LocalFragment extends Fragment {
    JSONArray jsonArray;
    String strQuery = "부어치킨";
    LocalAdpater localAdpater = new LocalAdpater();
    ListView list;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_local, container, false);
        list=view.findViewById(R.id.list);
        final EditText query = view.findViewById(R.id.query);
        ImageView search = view.findViewById(R.id.search);
        search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                strQuery = query.getText().toString();
                new LocalThread().execute();
            }
        });
        new LocalThread().execute();
        return view;
    }

    class LocalThread extends AsyncTask<String, String, String>{

        @Override
        protected String doInBackground(String... strings) {
            String url = "https://dapi.kakao.com/v2/local/search/keyword.json?query="+strQuery;
            return Kakao.connect(url);
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            try {
                jsonArray = new JSONObject(s).getJSONArray("documents");
                list.setAdapter(localAdpater);
            }catch (Exception e){
                System.out.println("로컬 오류 : "+e.toString());
            }

        }
    }

    class LocalAdpater extends BaseAdapter{

        @Override
        public int getCount() {
            return jsonArray.length();
        }

        @Override
        public Object getItem(int i) {
            return null;
        }

        @Override
        public long getItemId(int i) {
            return 0;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            view = getLayoutInflater().inflate(R.layout.item_local, viewGroup, false);
            try {
                JSONObject obj = jsonArray.getJSONObject(i);
                TextView name = view.findViewById(R.id.name);
                name.setText(Html.fromHtml(obj.getString("place_name")));
                TextView address = view.findViewById(R.id.address);
                address.setText(obj.getString("address_name"));
                TextView tel = view.findViewById(R.id.tel);
                tel.setText(obj.getString("phone"));
            }catch (Exception e){
                System.out.println("데이터 오류 : "+e.toString());
            }

            return view;
        }
    }
}

 

확인

 

- 이제 각 프레그먼트에서 검색 결과를 자세히 보는 작업을 하도록 하겠다.

- 각 아이템을 클릭시 아래 엑티비티로 이동하도록 하겠다.

- src/main/java/com/example/ex05/(new)BlogActivity.java

package com.example.ex05;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.text.Html;
import android.view.MenuItem;

public class BlogActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_blog);
        Intent intent = getIntent();
        String url = intent.getStringExtra("url");
        String title = intent.getStringExtra("title");
        getSupportActionBar().setTitle(Html.fromHtml(title));
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home:
                finish();
        }

        return super.onOptionsItemSelected(item);
    }
}

 

- src/main/res/layout/item_blog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="10sp"
    android:elevation="3sp"
    android:id="@+id/blog"> <<<---
....
</LinearLayout>

 

- src/main/java/com/example/ex05/BLogFragment.java

.....
    // 출력 블로그 어뎁터 생성
    class BlogAdapter extends BaseAdapter{
        @Override
        public int getCount() {
            return jsonArray.length();
        }

        @Override
        public Object getItem(int i) {
            return null;
        }

        @Override
        public long getItemId(int i) {
            return 0;
        }

        @Override
        public View getView(int position, View view, ViewGroup viewGroup) {
            view = getLayoutInflater().inflate(R.layout.item_blog, viewGroup, false);
            try {
                final JSONObject obj = jsonArray.getJSONObject(position);
                TextView title = view.findViewById(R.id.title);
                // Html.fromHtml() xml에서 html 사용
                title.setText(Html.fromHtml(obj.getString("title")));
                TextView link = view.findViewById(R.id.link);
                link.setText(obj.getString("url"));
                final String url = obj.getString("url");
                final String strTitle = obj.getString("title");
                LinearLayout blog = view.findViewById(R.id.blog);
                blog.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        // 현재 액티비티 이름을 알 수 없어서 getContext로
                        Intent intent = new Intent(getContext(), BlogActivity.class);
                        intent.putExtra("url", url);
                        intent.putExtra("title", strTitle);
                        startActivity(intent);
                    }
                });

            }catch (Exception e){
                System.out.println("뷰 오류 : " +e.toString());
            }
            return view;
        }
    }
.....

 

확인

 

 

- 이제 웹뷰를 이용해 페이지를 보이도록 하겠다.

- 페이지가 보일때 프로그래스바를 이용하여 로딩상황을 볼 수 있도록 하고 페이지 불러오기가 끝나면 사라지도록 하겠다.

- src/main/res/layout/activity_blog.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".BlogActivity">
    <WebView
        android:id="@+id/web"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    <ProgressBar
        android:id="@+id/progress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"/>
</RelativeLayout>

 

 

- 웹뷰를 만들겠다.

- src/main/java/com/example/ex05/BlogActivity.java

package com.example.ex05;

.....

public class BlogActivity extends AppCompatActivity {

    ProgressBar progressBar;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_blog);

        progressBar = findViewById(R.id.progress);

        Intent intent = getIntent();
        String url = intent.getStringExtra("url");
        String title = intent.getStringExtra("title");
        getSupportActionBar().setTitle(Html.fromHtml(title));
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        WebView web = findViewById(R.id.web);
        web.setWebViewClient(new MyWebView());
        web.loadUrl(url);
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home:
                finish();
        }

        return super.onOptionsItemSelected(item);
    }

    class MyWebView extends WebViewClient{
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
            return super.shouldOverrideUrlLoading(view, request);
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            progressBar.setVisibility(View.INVISIBLE);
        }
    }
}

 

확인

 

 

- 북 프레그먼트에서 도서 정보를 플로팅해주는 레이아웃를 생성하도록 하겠다.

- src/main/res/layout/(new)layout_book.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="20sp">
    <ImageView
        android:id="@+id/thumbnail"
        android:layout_width="200sp"
        android:layout_height="250sp"
        android:src="@mipmap/ic_launcher"
        android:layout_gravity="center"
        android:layout_marginBottom="20sp"/>
    <TextView
        android:id="@+id/description"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="책내용부분"
        android:padding="30sp"/>
</LinearLayout>

 

- src/main/res/layout/item_book.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#E3F3FA"
    android:padding="10sp"
    android:layout_margin="5sp"
    android:elevation="3sp"
    android:id="@+id/book"> <<<---
    .....

 

- src/main/java/com/example/ex05/BookFragment.java

.....
    class BookAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return jsonArray.length();
        }

        @Override
        public Object getItem(int i) {
            return null;
        }

        @Override
        public long getItemId(int i) {
            return 0;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            view = getLayoutInflater().inflate(R.layout.item_book, viewGroup, false);
            try {
                JSONObject obj = jsonArray.getJSONObject(i);
                ImageView thumbnail = view.findViewById(R.id.thumbnail);
                Picasso.with(getContext()).load(obj.getString("thumbnail")).into(thumbnail);
                TextView title = view.findViewById(R.id.title);
                title.setText(Html.fromHtml(obj.getString("title")));
                TextView publisher = view.findViewById(R.id.publisher);
                publisher.setText(obj.getString("publisher"));
                TextView price = view.findViewById(R.id.price);
                DecimalFormat df = new DecimalFormat("#,###원");
                price.setText(df.format(obj.getInt("price")));
				// new
                final String strImage = obj.getString("thumbnail");
                final String strDescription = obj.getString("contents");

                RelativeLayout book = view.findViewById(R.id.book);
                book.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        LinearLayout layout = (LinearLayout)getLayoutInflater().inflate(R.layout.layout_book, null);
                        ImageView image = layout.findViewById(R.id.thumbnail);
                        Picasso.with(getContext()).load(strImage).into(image);
                        TextView description = layout.findViewById(R.id.description);
                        description.setText(strDescription);
                        AlertDialog.Builder box = new AlertDialog.Builder(getContext());
                        box.setTitle("책정보");
                        box.setNeutralButton("닫기",null);
                        box.setView(layout);
                        box.show();
                    }
                });
            }catch (Exception e){
                System.out.println("뷰 오류 : "+ e.toString());
            }
            return view;
        }
    }
.....

 

확인

 

- 검색 후 키패드가 자동으로 닫히게 하겠다.

package com.example.ex05;

import android.app.AlertDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;

import androidx.fragment.app.Fragment;

import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.squareup.picasso.Picasso;

import org.json.JSONArray;
import org.json.JSONObject;

import java.text.DecimalFormat;


public class BookFragment extends Fragment {
    String strQuery = "파이썬";
    JSONArray jsonArray;
    BookAdapter bookAdapter = new BookAdapter();
    ListView list;
    // 키패드 자동으로 닫기 위한 클래스
    InputMethodManager imm; <<<===

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_book, container, false);
        list = view.findViewById(R.id.list);

        imm = (InputMethodManager)getContext().getSystemService(Context.INPUT_METHOD_SERVICE); <<<===
        new BookThread().execute();
        final EditText query = view.findViewById(R.id.query);
        ImageView search = view.findViewById(R.id.search);
        search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                strQuery = query.getText().toString();
                imm.hideSoftInputFromWindow(query.getWindowToken(), 0); <<<===
                new BookThread().execute();
            }
        });
        return view;
    }

 

 

 

- 지도에서 로케이션 이미지를 클릭하면 해당 위치를 나타내는 지도가 뜨도록 하겠다.

- 지도는 구글 API를 이용하도록 하겠다.

구글 지도 API이용을 위한 서비스 설치 경로

 

구글 맵 액티비티 생성 경로

 

- 구글 API키를 발급받아서 넣도록 하겠다.

- src/debug/res/values/google_maps_api.xml

- 해당 .xml에 아래의 링크에서 로그인하고 프로젝트를 생성하여 apikey를 받아오겠다.

https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend&keyType=CLIENT_SIDE_ANDROID&r=D1:85:84:52:37:3B:DD:B1:20:4B:60:44:B9:8C:6A:00:08:BC:3B:7D%3Bcom.example.ex05

<resources>
    <!--
    TODO: Before you run your application, you need a Google Maps API key.

    To get one, follow this link, follow the directions and press "Create" at the end:

    https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend&keyType=CLIENT_SIDE_ANDROID&r=D1:85:84:52:37:3B:DD:B1:20:4B:60:44:B9:8C:6A:00:08:BC:3B:7D%3Bcom.example.ex05

    You can also add your credentials to an existing key, using these values:

    Package name:
    com.example.ex05

    SHA-1 certificate fingerprint:
    D1:85:84:52:37:3B:DD:B1:20:4B:60:44:B9:8C:6A:00:08:BC:3B:7D

    Alternatively, follow the directions here:
    https://developers.google.com/maps/documentation/android/start#get-key

    Once you have your key (it starts with "AIza"), replace the "google_maps_key"
    string in this file.
    -->
    <string name="google_maps_key" translatable="false" templateMergeStrategy="preserve">
    키 넣는 부분</string>
</resources>

 

- 지도 프레그먼크의 아이템의 map을 클릭 시 해당 액티비티로 이동할 수 있도록 하겠다.

.....
	class LocalAdpater extends BaseAdapter{

        @Override
        public int getCount() {
            return jsonArray.length();
        }

        @Override
        public Object getItem(int i) {
            return null;
        }

        @Override
        public long getItemId(int i) {
            return 0;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            view = getLayoutInflater().inflate(R.layout.item_local, viewGroup, false);
            try {
                JSONObject obj = jsonArray.getJSONObject(i);
                TextView name = view.findViewById(R.id.name);
                name.setText(Html.fromHtml(obj.getString("place_name")));
                TextView address = view.findViewById(R.id.address);
                address.setText(obj.getString("address_name"));
                TextView tel = view.findViewById(R.id.tel);
                tel.setText(obj.getString("phone"));
				// 클릭 시 지도 액티비티로 이동
                ImageView map = view.findViewById(R.id.map);
                map.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        Intent intent = new Intent(getContext(), MapsActivity.class);
                        startActivity(intent);
                    }
                });

            }catch (Exception e){
                System.out.println("데이터 오류 : "+e.toString());
            }

            return view;
        }
    }
.....

 

확인

 

- 이제 해당 위치의 위도 경도를 받아서 값을 넘겨줄 수 있도록 하겠다.

- src/main/java/com/example/ex05/LocalFragment.java

.....
    class LocalAdpater extends BaseAdapter{

        @Override
        public int getCount() {
            return jsonArray.length();
        }

        @Override
        public Object getItem(int i) {
            return null;
        }

        @Override
        public long getItemId(int i) {
            return 0;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            view = getLayoutInflater().inflate(R.layout.item_local, viewGroup, false);
            try {
                JSONObject obj = jsonArray.getJSONObject(i);
                TextView name = view.findViewById(R.id.name);
                name.setText(Html.fromHtml(obj.getString("place_name")));
                TextView address = view.findViewById(R.id.address);
                address.setText(obj.getString("address_name"));
                TextView tel = view.findViewById(R.id.tel);
                tel.setText(obj.getString("phone"));
                // 위도 경도 위치명 가지고 오기
                final String x = obj.getString("x");
                final String y = obj.getString("y");
                final String place_name = obj.getString("place_name");

                ImageView map = view.findViewById(R.id.map);
                map.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        Intent intent = new Intent(getContext(), MapsActivity.class);
                        intent.putExtra("x",x);
                        intent.putExtra("y",y);
                        intent.putExtra("title",place_name);
                        startActivity(intent);
                    }
                });

            }catch (Exception e){
                System.out.println("데이터 오류 : "+e.toString());
            }

            return view;
        }
    }

.....

 

- src/main/java/com/example/ex05/MapsActivity.java

package com.example.ex05;

import androidx.fragment.app.FragmentActivity;

import android.content.Intent;
import android.os.Bundle;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    double lat;
    double lng;
    String title;

    private GoogleMap mMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);

        Intent intent = getIntent();
        lat = Double.parseDouble(intent.getStringExtra("y"));
        lng = Double.parseDouble(intent.getStringExtra("x"));
        title = intent.getStringExtra("title");

        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        // Add a marker in Sydney and move the camera
        LatLng sydney = new LatLng(lat, lng);
        mMap.addMarker(new MarkerOptions().position(sydney).title(title));
        mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
        mMap.moveCamera(CameraUpdateFactory.zoomTo(15));
    }
}

 

확인

 

https://apis.map.kakao.com/android/guide/

 

 

- 지역검색한 내용을 즐겨찾기 지정하도록 하겠다.

- src/main/res/drawable/(new)ic_baseline_favorite_24.xml

- src/main/res/layout/item_local.xml

.....
    <ImageView
        android:id="@+id/like"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_baseline_favorite_24"
        android:layout_toLeftOf="@id/map"
        android:layout_below="@id/name"/>
</RelativeLayout>

 

- src/main/java/com/example/ex05/LocalFragment.java

.....
        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            view = getLayoutInflater().inflate(R.layout.item_local, viewGroup, false);
            try {
                JSONObject obj = jsonArray.getJSONObject(i);
                TextView name = view.findViewById(R.id.name);
                name.setText(Html.fromHtml(obj.getString("place_name")));
                TextView address = view.findViewById(R.id.address);
                address.setText(obj.getString("address_name"));
                TextView tel = view.findViewById(R.id.tel);
                tel.setText(obj.getString("phone"));

                // 위도 경도 위치명 가지고 오기
                final String x = obj.getString("x");
                final String y = obj.getString("y");
                final String place_name = obj.getString("place_name");

                ImageView map = view.findViewById(R.id.map);
                map.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        Intent intent = new Intent(getContext(), MapsActivity.class);
                        intent.putExtra("x",x);
                        intent.putExtra("y",y);
                        intent.putExtra("title",place_name);
                        startActivity(intent);
                    }
                });

                // 즐겨찾기 이미지 클릭 시
                ImageView like = view.findViewById(R.id.like);
                like.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        AlertDialog.Builder box = new AlertDialog.Builder(getContext());
                        box.setMessage("즐겨찾기에 등록하시겠습니까?");
                        box.setNegativeButton("아니오",null);
                        box.setPositiveButton("예", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {

                            }
                        });
                        box.show();
                    }
                });

            }catch (Exception e){
                System.out.println("데이터 오류 : "+e.toString());
            }

            return view;
        }
.....

 

- 즐겨찾기 설정을 DB에 저장해주도록 하겠다.

- src/main/java/com/example/ex05/(new)LikeDB.java - java class

package com.example.ex05;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import androidx.annotation.Nullable;

public class LikeDB extends SQLiteOpenHelper {
    public LikeDB(@Nullable Context context) {
        super(context, "like.db", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table tbllike(_id integer primary key autoincrement,name text,address text,tel text, x text, y text)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}

 

- src/main/java/com/example/ex05/LocalFragment.java

.....
public class LocalFragment extends Fragment {

    JSONArray jsonArray;
    String strQuery = "부어치킨";
    LocalAdpater localAdpater = new LocalAdpater();
    ListView list;

    // DB 오픈을 위한 변수 선언
    LikeDB likeDB;
    SQLiteDatabase db;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_local, container, false);
		// new
        likeDB = new LikeDB(getContext());
        db=likeDB.getWritableDatabase();

        list=view.findViewById(R.id.list);
        final EditText query = view.findViewById(R.id.query);
        ImageView search = view.findViewById(R.id.search);
        search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                strQuery = query.getText().toString();
                new LocalThread().execute();
            }
        });
        new LocalThread().execute();
        return view;
    }
.....

 

확인

 

- src/main/java/com/example/ex05/LocalFragment.java

public class LocalFragment extends Fragment {

    JSONArray jsonArray;
    String strQuery = "부어치킨";
    LocalAdpater localAdpater = new LocalAdpater();
    ListView list;

    // DB 오픈을 위한 변수 선언
    LikeDB likeDB;
    SQLiteDatabase db;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_local, container, false);

        likeDB = new LikeDB(getContext());
        db=likeDB.getWritableDatabase();

        list=view.findViewById(R.id.list);
        final EditText query = view.findViewById(R.id.query);
        ImageView search = view.findViewById(R.id.search);
        search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                strQuery = query.getText().toString();
                new LocalThread().execute();
            }
        });
        new LocalThread().execute();
        return view;
    }

    class LocalThread extends AsyncTask<String, String, String>{

        @Override
        protected String doInBackground(String... strings) {
            String url = "https://dapi.kakao.com/v2/local/search/keyword.json?query="+strQuery;
            return Kakao.connect(url);
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            try {
                jsonArray = new JSONObject(s).getJSONArray("documents");
                list.setAdapter(localAdpater);
            }catch (Exception e){
                System.out.println("로컬 오류 : "+e.toString());
            }

        }
    }

    class LocalAdpater extends BaseAdapter{

        @Override
        public int getCount() {
            return jsonArray.length();
        }

        @Override
        public Object getItem(int i) {
            return null;
        }

        @Override
        public long getItemId(int i) {
            return 0;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            view = getLayoutInflater().inflate(R.layout.item_local, viewGroup, false);
            try {
                JSONObject obj = jsonArray.getJSONObject(i);
                TextView name = view.findViewById(R.id.name);
                name.setText(Html.fromHtml(obj.getString("place_name")));
                TextView address = view.findViewById(R.id.address);
                address.setText(obj.getString("address_name"));
                TextView tel = view.findViewById(R.id.tel);
                tel.setText(obj.getString("phone"));

                // 위도 경도 위치명 가지고 오기
                final String x = obj.getString("x");
                final String y = obj.getString("y");
                final String place_name = obj.getString("place_name");

                final String strTel = obj.getString("phone");
                final String strAddress = obj.getString("address_name");

                ImageView map = view.findViewById(R.id.map);
                map.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        Intent intent = new Intent(getContext(), MapsActivity.class);
                        intent.putExtra("x",x);
                        intent.putExtra("y",y);
                        intent.putExtra("title",place_name);
                        startActivity(intent);
                    }
                });

                // 즐겨찾기 이미지 클릭 시
                ImageView like = view.findViewById(R.id.like);
                like.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        AlertDialog.Builder box = new AlertDialog.Builder(getContext());
                        box.setMessage("즐겨찾기에 등록하시겠습니까?");
                        box.setNegativeButton("아니오",null);
                        box.setPositiveButton("예", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                String sql = "insert into tbllike(name, tel, address, x, y) values(";
                                sql += "'"+place_name+"',";
                                sql += "'"+strTel+"',";
                                sql += "'"+strAddress+"',";
                                sql += "'"+x+"',";
                                sql += "'"+y+"')";
                                db.execSQL(sql);
                                Toast.makeText(getContext(),"즐겨찾기에 등록되었습니다.", Toast.LENGTH_SHORT).show();
                            }
                        });
                        box.show();
                    }
                });

            }catch (Exception e){
                System.out.println("데이터 오류 : "+e.toString());
            }

            return view;
        }
    }
}

 

 

- src/main/res/menu/menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/like"
        android:title="즐겨찾기"
        android:icon="@drawable/ic_baseline_favorite_24"
        app:showAsAction="always"/>
</menu>

 

- src/main/java/com/example/ex05/MainActivity.java

.....
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home:
                DrawerLayout layout = findViewById(R.id.drawerLayout);
                LinearLayout view = findViewById(R.id.drawerView);
                if(layout.isDrawerOpen(view)){
                    layout.closeDrawer(view);
                }else{
                    layout.openDrawer(view);
                }
                break;
            case R.id.like:
                Intent intent = new Intent(this, LikeActivity.class);
                startActivity(intent);
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);
        return super.onCreateOptionsMenu(menu);
    }
}

 

- src/main/java/com/example/ex05/(new)LikeActivity.java

package com.example.ex05;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class LikeActivity extends AppCompatActivity {
    LikeDB likeDB;
    SQLiteDatabase db;
    Cursor cursor;
    ListView list;
    LikeAdapter likeAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_local);

        likeDB = new LikeDB(this);
        db=likeDB.getWritableDatabase();

        getSupportActionBar().setTitle("즐겨찾기");
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        cursor=db.rawQuery("select * from tbllike order by _id desc", null);
        likeAdapter=new LikeAdapter(this, cursor);
        list = findViewById(R.id.list);
        list.setAdapter(likeAdapter);
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home:
                finish();
        }
        return super.onOptionsItemSelected(item);
    }

    class LikeAdapter extends CursorAdapter{
        public LikeAdapter(Context context, Cursor c) {
            super(context, c);
        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            return getLayoutInflater().inflate(R.layout.item_local, parent, false);
        }

        @Override
        public void bindView(View view, Context context, final Cursor cursor) {
            TextView name=view.findViewById(R.id.name);
            name.setText(cursor.getString(1));
            ImageView like=view.findViewById(R.id.like);
            like.setVisibility(View.INVISIBLE);
            TextView tel=view.findViewById(R.id.tel);
            tel.setText(cursor.getString(2));
            TextView address=view.findViewById(R.id.address);
            address.setText(cursor.getString(3));

            final String x = cursor.getString(4);
            final String y = cursor.getString(5);
            final String title = cursor.getString(1);
            ImageView map=view.findViewById(R.id.map);
            map.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent=new Intent(LikeActivity.this, MapsActivity.class);
                    intent.putExtra("x", x);
                    intent.putExtra("y", y);
                    System.out.println(x+"/"+y);
                    intent.putExtra("title", title);
                    startActivity(intent);
                }
            });
        }
    }
}

 

완료