겜팔이의 안드로이드 세뇌교실 (안드로이드)
- 액티비티
- 인텐트
- 뷰 – Widget, Layout, Event
- Fragment
- ViewPager, TabLayout
- SharedPreferences
- 동적 뷰 생성 (ArrayList 이용)
- RecyclerView
- Thread, Log
- Glide
- 서버-클라이언트, Okhttp, JSON
- 카메라
- 최종 10강 완결 소스
- UUID 사용
https://www.youtube.com/playlist?list=PLG9ohJAOA2PBtTBlGkmzk6_MuaUQBg_pw
https://github.com/g82/Anstagram/releases
액티비티
윈도우의 창과 같음.
UI를 보여주고, 행동도 함.
package com.example.mytestapp1;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
public static final String TAG = “MainActivity”;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, “onStart”);
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, “onResume”);
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, “onPause”);
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, “onStop”);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, “onDestroy”);
}
}
인텐트
액티비티는 인텐트를 통해서 의사소통을 함
인텐트는 우편배달부
1. 액티비티 – 액티비티(서비스, Broadcast Receiver);
2. 앱 – 앱
3. 편지부터 택배까지 배달해주는 우편 배달부
명시적 인텐트 (보낸이와 받는이를 명시)
Intent intent = new Intent(this, NewActivity.class);
startActivity(intent)
암시적 인텐트 (앱 밖에서, 앱과 앱 사이에서)
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_CALL);
startActivity(sendIntent);
인텐트를 통해서 특정 액티비티에 메시지 보내기
보내는 측: intent.putExtra(“intent-message”,”메시지를 보냅니다.”);
받는 측: String message = getIntent().getStringExtra(“intent-message”);
MainActivity.java
package com.example.mytestapp1;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.btn_call);
button.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, “클릭!!”, Toast.LENGTH_SHORT).show();
/* 암시적 액티비티
Intent intent = new Intent();
intent.setAction(Intent.ACTION_DIAL);
startActivity(intent);
*/
// 명시적 액티비티
Intent intent = new Intent(MainActivity.this, CallActivity.class);
intent.putExtra(“intent-message”,”메시지를 보냅니다.”);
startActivity(intent);
}
}
<?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=”.MainActivity”>
<Button
android:text=”CALL”
android:id=”@+id/btn_call”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
</RelativeLayout>
CallActivity.java
package com.example.mytestapp1;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class CallActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_call);
String message = getIntent().getStringExtra(“intent-message”);
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout 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=”.CallActivity”>
<TextView
android:textSize=”36sp”
android:text=”CALL”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
</LinearLayout>
뷰 – Widget, Layout, Event
MainActivity.java
package com.example.mytestapp2layout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener, View.OnTouchListener {
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.iv_like).setOnClickListener(this);
findViewById(R.id.iv_share).setOnClickListener(this);
findViewById(R.id.iv_photo).setOnTouchListener(this);
findViewById(R.id.iv_photo).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.iv_like:
Toast.makeText(this, “좋아요 강예원”, Toast.LENGTH_SHORT).show();
break;
case R.id.iv_share:
Toast.makeText(this, “공유 강예원”, Toast.LENGTH_SHORT).show();
break;
case R.id.iv_photo:
Toast.makeText(this, “클릭 강예원”, Toast.LENGTH_SHORT).show();
break;
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(this, “터치 강예원.”, Toast.LENGTH_SHORT).show();
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
Toast.makeText(this, “터치 업”, Toast.LENGTH_SHORT).show();
break;
case MotionEvent.ACTION_DOWN:
Toast.makeText(this, “터치 다운”, Toast.LENGTH_SHORT).show();
break;
}
return false;
}
}
activity_main.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout 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”
android:orientation=”vertical”
tools:context=”.MainActivity”>
<LinearLayout
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:text=”Hello World!”
android:weightSum=”2″>
<TextView
android:layout_width=”0dp”
android:layout_height=”wrap_content”
android:paddingTop=”16dp”
android:paddingBottom=”16dp”
android:textSize=”24sp”
android:text=”Timeline”
android:gravity=”center”
android:layout_weight=”1″/>
<TextView
android:layout_width=”0dp”
android:layout_height=”wrap_content”
android:paddingTop=”16dp”
android:paddingBottom=”16dp”
android:textSize=”24sp”
android:text=”Untitled”
android:gravity=”center”
android:layout_weight=”1″/>
</LinearLayout>
<View
android:layout_width=”match_parent”
android:layout_height=”2px”
android:background=”#000000″ />
<ScrollView
android:layout_width=”match_parent”
android:layout_height=”match_parent”>
<LinearLayout
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:orientation=”vertical”>
<include layout=”@layout/item_post” />
<include layout=”@layout/item_post” />
<include layout=”@layout/item_post” />
<include layout=”@layout/item_post” />
<include layout=”@layout/item_post” />
</LinearLayout>
</ScrollView>
</LinearLayout>
item_post.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”>
<ImageView
android:id=”@+id/iv_photo”
android:layout_width=”match_parent”
android:layout_height=”300dp”
android:scaleType=”centerCrop”
android:src=”@drawable/kanghyewon” />
<RelativeLayout
android:paddingTop=”8dp”
android:paddingLeft=”16dp”
android:paddingRight=”16dp”
android:paddingBottom=”8dp”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”>
<ImageView
android:id=”@+id/iv_like”
android:layout_width=”24dp”
android:layout_height=”24dp”
android:background=”#454522″ />
<TextView
android:id=”@+id/tv_desc”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_centerVertical=”true”
android:layout_marginLeft=”8dp”
android:layout_marginRight=”8dp”
android:lines=”1″
android:layout_toLeftOf=”@+id/iv_share”
android:layout_toStartOf=”@id/iv_share”
android:layout_toEndOf=”@id/iv_like”
android:layout_toRightOf=”@id/iv_like”
android:ellipsize=”end”
android:text=”안녕하세요. 아이즈원 강혜원입니다. 반갑습니다.” />
<ImageView
android:id=”@+id/iv_share”
android:layout_alignParentRight=”true”
android:layout_alignParentEnd=”true”
android:background=”#764432″
android:layout_width=”48px”
android:layout_height=”48px” />
</RelativeLayout>
<View
android:layout_width=”match_parent”
android:layout_height=”1px”
android:background=”#000000″ />
<RelativeLayout
android:padding=”16dp”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”>
<TextView
android:id=”@+id/tv_uploader”
android:text=”ansta_”
android:lines=”1″
android:maxLength=”10″
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
<TextView
android:layout_marginLeft=”8dp”
android:layout_marginStart=”8dp”
android:layout_toRightOf=”@id/tv_uploader”
android:layout_toEndOf=”@id/tv_uploader”
android:layout_alignParentRight=”true”
android:text=”불꽃놀이했어요! :)”
android:lines=”1″
android:maxLength=”10″
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
</RelativeLayout>
</LinearLayout>
Fragment
Mainactivity.java
package com.example.mytestappfragment;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity implements OnColorButtonListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GreenFragment greenFragment = new GreenFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.fl_right, greenFragment);
}
@Override
public void onColorClick(int color) {
Fragment fragment = null;
switch (color) {
case 0:
fragment = new RedFragment();
break;
case 1:
fragment = new GreenFragment();
break;
case 2:
fragment = new BlueFragment();
break;
}
getSupportFragmentManager().beginTransaction()
.replace(R.id.fl_right, fragment).commit();
}
}
OnColorButtonListener.java
package com.example.mytestappfragment;
public interface OnColorButtonListener {
void onColorClick(int color);
}
LeftFragment.java
package com.example.mytestappfragment;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {@link Fragment} subclass.
*/
public class LeftFragment extends Fragment implements View.OnClickListener {
private OnColorButtonListener onColorButtonListener;
@Override
public void onAttach(Context context) {
super.onAttach(context);
onColorButtonListener = (OnColorButtonListener) context;
}
public LeftFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_left, container, false);
view.findViewById(R.id.v_red).setOnClickListener(this);
view.findViewById(R.id.v_green).setOnClickListener(this);
view.findViewById(R.id.v_blue).setOnClickListener(this);
return view;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.v_red:
onColorButtonListener.onColorClick(0);
break;
case R.id.v_green:
onColorButtonListener.onColorClick(1);
break;
case R.id.v_blue:
onColorButtonListener.onColorClick(2);
break;
}
}
}
RedFragment.java
package com.example.mytestappfragment;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class RedFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_red, null);
}
}
GreenFragment.java
package com.example.mytestappfragment;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class GreenFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_green, null);
}
}
BlueFragment.java
package com.example.mytestappfragment;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class BlueFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_blue, null);
}
}
activity_main.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout 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”>
<fragment
android:id=”@+id/fragment_left”
android:name=”com.example.mytestappfragment.LeftFragment”
android:background=”#ffe873″
android:layout_weight=”1″
android:layout_width=”0dp”
android:layout_height=”match_parent” />
<FrameLayout
android:id=”@+id/fl_right”
android:layout_weight=”2″
android:layout_width=”0dp”
android:layout_height=”match_parent” />
</LinearLayout>
fragment_left.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:tools=”http://schemas.android.com/tools”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:orientation=”vertical”
tools:context=”.LeftFragment”>
<!– TODO: Update blank fragment layout –>
<View
android:id=”@+id/v_red”
android:background=”#ff8174″
android:layout_weight=”1″
android:layout_width=”match_parent”
android:layout_height=”0dp” />
<View
android:id=”@+id/v_green”
android:background=”#6ed168″
android:layout_weight=”1″
android:layout_width=”match_parent”
android:layout_height=”0dp” />
<View
android:id=”@+id/v_blue”
android:background=”#4c9afa”
android:layout_weight=”1″
android:layout_width=”match_parent”
android:layout_height=”0dp” />
</LinearLayout>
fragment_red.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical” android:layout_width=”match_parent”
android:background=”#ff8174″
android:layout_height=”match_parent”>
</LinearLayout>
fragment_green.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical” android:layout_width=”match_parent”
android:background=”#6ed168″
android:layout_height=”match_parent”>
</LinearLayout>
fragment_blue.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical” android:layout_width=”match_parent”
android:background=”#4c9afa”
android:layout_height=”match_parent”>
</LinearLayout>
ViewPager, TabLayout
MainActivity.java
package com.example.mytestappviewpager;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.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);
TabLayout tabLayout = findViewById(R.id.tl_tabs);
ViewPager viewPager = findViewById(R.id.vp_pager);
Fragment[] arrFragments = new Fragment[3];
arrFragments[0] = new RedFragment();
arrFragments[1] = new YellowFragment();
arrFragments[2] = new GreenFragment();
MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager(), arrFragments);
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
}
private class MyPagerAdapter extends FragmentPagerAdapter {
private Fragment[] arrFragments;
public MyPagerAdapter(FragmentManager fm, Fragment[] arrFragments) {
super(fm);
this.arrFragments = arrFragments;
}
@Override
public Fragment getItem(int i) {
return arrFragments[i];
}
@Override
public int getCount() {
return arrFragments.length;
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return “RED”;
case 1:
return “YELLOW”;
case 2:
return “GREEN”;
default:
return “”;
}
}
}
}
RedFragment.java
package com.example.mytestappviewpager;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {@link Fragment} subclass.
*/
public class RedFragment extends Fragment {
public RedFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_red, container, false);
}
}
YellowFragment.java
package com.example.mytestappviewpager;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {@link Fragment} subclass.
*/
public class YellowFragment extends Fragment {
public YellowFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_yellow, container, false);
}
}
GreenFragment.java
package com.example.mytestappviewpager;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {@link Fragment} subclass.
*/
public class GreenFragment extends Fragment {
public GreenFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_green, container, false);
}
}
activity_main.xml
implementation ‘com.android.support:design:28.0.0’
<?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=”.MainActivity”>
<android.support.design.widget.TabLayout
android:id=”@+id/tl_tabs”
android:layout_width=”match_parent”
android:layout_height=”wrap_content” />
<android.support.v4.view.ViewPager
android:id=”@+id/vp_pager”
android:layout_below=”@id/tl_tabs”
android:layout_width=”match_parent”
android:layout_height=”match_parent” />
</RelativeLayout>
fragment_red.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<FrameLayout xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:tools=”http://schemas.android.com/tools”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:background=”#ea4e00″
tools:context=”.RedFragment”>
<!– TODO: Update blank fragment layout –>
<TextView
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:text=”@string/hello_blank_fragment” />
</FrameLayout>
fragment_yellow.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<FrameLayout xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:tools=”http://schemas.android.com/tools”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:background=”#fdff7a”
tools:context=”.YellowFragment”>
<!– TODO: Update blank fragment layout –>
<TextView
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:text=”@string/hello_blank_fragment” />
</FrameLayout>
fragment_green.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<FrameLayout xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:tools=”http://schemas.android.com/tools”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:background=”#80cf00″
tools:context=”.GreenFragment”>
<!– TODO: Update blank fragment layout –>
<TextView
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:text=”@string/hello_blank_fragment” />
</FrameLayout>
SharedPreferences
https://developer.android.com/training/data-storage/shared-preferences#java
MainActivity.java
package com.example.mytestappsharedpreference;
import android.content.Context;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
public static final String SHARED_PREF_FIRST_USER_KEY = “1000”;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv_hello = findViewById(R.id.tv_hello);
SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
int firstUser = sharedPref.getInt(SHARED_PREF_FIRST_USER_KEY, -1);
if (firstUser == 1) {
tv_hello.setText(getString(R.string.hello_user));
} else if (firstUser == -1) {
tv_hello.setText(getString(R.string.hello_first));
saveUserIsNotFirst();
}
}
private void saveUserIsNotFirst() {
SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt(SHARED_PREF_FIRST_USER_KEY, 1);
editor.commit();
}
}
activity_main.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=”.MainActivity”>
<TextView
android:id=”@+id/tv_hello”
android:gravity=”center”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:text=”Hello World!”
android:textSize=”36sp” />
</RelativeLayout>
strings.xml
<resources>
<string name=”app_name”>MyTestAppSharedPreference</string>
<string name=”hello_user”>RE-Hi, Hogangnim.</string>
<string name=”hello_first”>Nice to meet you, Gogaeknim</string>
</resources>
strings.xml (ko)
<?xml version=”1.0″ encoding=”utf-8″?>
<resources>
<string name=”app_name”>MyTestAppSharedPreference</string>
<string name=”hello_user”>다시 안녕. 호갱님</string>
<string name=”hello_first”>만나서 반갑습니다. 고객님.</string>
</resources>
동적 뷰 생성 (ArrayList 이용)
ArrayList<> : 클래스 이용
List<> : 인터페이스 이용
model/PostItem.java
package com.example.mytestappdynamicview.model;
public class PostItem {
boolean isUserLike;
int postLikeCount;
String userName;
String postImgUrl;
String postText;
public PostItem(boolean isUserLike, int postLikeCount, String userName, String postImgUrl, String postText) {
this.isUserLike = isUserLike;
this.postLikeCount = postLikeCount;
this.userName = userName;
this.postImgUrl = postImgUrl;
this.postText = postText;
}
public boolean isUserLike() {
return isUserLike;
}
public int getPostLikeCount() {
return postLikeCount;
}
public String getUserName() {
return userName;
}
public String getPostImgUrl() {
return postImgUrl;
}
public String getPostText() {
return postText;
}
}
MainActivity.java
package com.example.mytestappdynamicview;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.example.mytestappdynamicview.model.PostItem;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayList<PostItem> listItem = new ArrayList<>();
LinearLayout llScrollParent = findViewById(R.id.ll_scroll);
for (int i = 0; i < 50; i++) {
PostItem item = new PostItem(
true, 125, “KANGHYEWON”,
“http://www.liveen.co.kr/news/photo/201810/234137_285936_1452.jpg”,
“wow!!!”
);
listItem.add(i, item);
}
for (PostItem item : listItem) {
View v = View.inflate(this, R.layout.post_item, null);
TextView tvUserName = v.findViewById(R.id.tv_UserName);
TextView tvPostText = v.findViewById(R.id.tv_PostText);
tvUserName.setText(item.getUserName());
tvPostText.setText(item.getPostText());
llScrollParent.addView(v);
}
}
}
post_item.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”horizontal” android:layout_width=”match_parent”
android:padding=”16dp”
android:layout_height=”wrap_content”>
<TextView
android:textColor=”#6200ea”
android:text=”ansta_”
android:id=”@+id/tv_UserName”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
<TextView
android:layout_marginLeft=”8dp”
android:text=”불꽃놀이했어요~~”
android:id=”@+id/tv_PostText”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
</LinearLayout>
activity_main.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<ScrollView 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=”.MainActivity”>
<LinearLayout
android:id=”@+id/ll_scroll”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:orientation=”vertical” />
</ScrollView>
RecyclerView
model/PostItem.java
package com.example.mytestappdynamicview.model;
public class PostItem {
boolean isUserLike;
int postLikeCount;
String userName;
String postImgUrl;
String postText;
public PostItem(boolean isUserLike, int postLikeCount, String userName, String postImgUrl, String postText) {
this.isUserLike = isUserLike;
this.postLikeCount = postLikeCount;
this.userName = userName;
this.postImgUrl = postImgUrl;
this.postText = postText;
}
public boolean isUserLike() {
return isUserLike;
}
public int getPostLikeCount() {
return postLikeCount;
}
public String getUserName() {
return userName;
}
public String getPostImgUrl() {
return postImgUrl;
}
public String getPostText() {
return postText;
}
}
recyclerview/PostAdapter.java
package com.example.mytestappdynamicview.recyclerview;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.example.mytestappdynamicview.R;
import com.example.mytestappdynamicview.model.PostItem;
import java.util.ArrayList;
public class PostAdapter extends RecyclerView.Adapter<PostViewHolder> {
private Context mContext;
private ArrayList<PostItem> postItems;
public PostAdapter(Context context, ArrayList<PostItem> listItem) {
this.mContext = context;
postItems = listItem;
}
@NonNull
@Override
public PostViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View baseView = View.inflate(mContext, R.layout.post_item, null);
PostViewHolder postViewHolder = new PostViewHolder(baseView, this);
return postViewHolder;
}
@Override
public void onBindViewHolder(@NonNull PostViewHolder holder, int i) {
PostItem item = postItems.get(i);
holder.tvUserName.setText(item.getUserName());
holder.tvPostText.setText(item.getPostText());
holder.tvLikeCount.setText(String.valueOf(item.getPostLikeCount()));
holder.ivImg.setImageResource(R.drawable.khw);
}
@Override
public int getItemCount() {
return postItems.size();
}
public void onLikeClicked(int position) {
PostItem item = postItems.get(position);
Toast.makeText(mContext, position + ” : ” + item.getPostText(), Toast.LENGTH_SHORT).show();
}
}
recyclerview/PostViewHolder.java
package com.example.mytestappdynamicview.recyclerview;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.mytestappdynamicview.R;
public class PostViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public CheckBox cbLike;
public ImageView ivImg, ivShare;
public TextView tvLikeCount, tvUserName, tvPostText;
private PostAdapter mAdapter;
public PostViewHolder(@NonNull View itemView, PostAdapter postAdapter) {
super(itemView);
mAdapter = postAdapter;
ivImg = itemView.findViewById(R.id.iv_img);
cbLike = itemView.findViewById(R.id.cb_like);
ivShare = itemView.findViewById(R.id.iv_share);
tvLikeCount = itemView.findViewById(R.id.tv_likecount);
tvUserName = itemView.findViewById(R.id.tv_username);
tvPostText = itemView.findViewById(R.id.tv_posttext);
cbLike.setOnClickListener(this);
ivShare.setOnClickListener(this);
}
@Override
public void onClick(View v) {
int position = getAdapterPosition();
Boolean b = cbLike.isChecked();
switch (v.getId()) {
case R.id.cb_like:
mAdapter.onLikeClicked(position);
break;
case R.id.iv_share:
break;
}
}
}
MainActivity.java
package com.example.mytestappdynamicview;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.example.mytestappdynamicview.model.PostItem;
import com.example.mytestappdynamicview.recyclerview.PostAdapter;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayList<PostItem> listItem = new ArrayList<>();
RecyclerView rvList = findViewById(R.id.rv_list);
for (int i = 0; i < 50; i++) {
PostItem item = new PostItem(
true, 125, “KANGHYEWON”,
“http://www.liveen.co.kr/news/photo/201810/234137_285936_1452.jpg”,
“wow!!!”
);
listItem.add(i, item);
}
PostAdapter adapter = new PostAdapter(this, listItem);
rvList.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
rvList.setAdapter(adapter);
}
}
drawable/like_button.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<selector xmlns:android=”http://schemas.android.com/apk/res/android”>
<item android:state_checked=”true” android:drawable=”@drawable/btn_on” />
<item android:state_checked=”false” android:drawable=”@drawable/btn_off” />
</selector>
layout/activity_main.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=”.MainActivity”>
<android.support.v7.widget.RecyclerView
android:id=”@+id/rv_list”
android:layout_width=”match_parent”
android:layout_height=”match_parent” />
</RelativeLayout>
layout/post_item.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical” android:layout_width=”match_parent”
android:layout_height=”wrap_content”>
<ImageView
android:id=”@+id/iv_img”
android:background=”#424242″
android:scaleType=”fitCenter”
android:layout_width=”match_parent”
android:layout_height=”300dp” />
<RelativeLayout
android:paddingTop=”8dp”
android:paddingBottom=”8dp”
android:paddingLeft=”16dp”
android:paddingRight=”16dp”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”>
<CheckBox
android:button=”@drawable/like_button”
android:id=”@+id/cb_like”
android:layout_centerVertical=”true”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
<!– <ImageView
android:background=”#d50000″
android:id=”@+id/iv_like”
android:layout_width=”24dp”
android:layout_height=”24dp” />–>
<TextView
android:id=”@+id/tv_likecount”
android:layout_marginLeft=”8dp”
android:layout_centerVertical=”true”
android:layout_toRightOf=”@id/cb_like”
android:text=”1234″
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
<ImageView
android:layout_alignParentRight=”true”
android:background=”#181818″
android:id=”@+id/iv_share”
android:layout_width=”24dp”
android:layout_height=”24dp” />
</RelativeLayout>
<View
android:background=”#efefef”
android:layout_width=”match_parent”
android:layout_height=”1dp” />
<LinearLayout
android:padding=”16dp”
android:orientation=”horizontal”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”>
<TextView
android:textColor=”#6200ea”
android:text=”ansta_”
android:id=”@+id/tv_username”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
<TextView
android:layout_marginLeft=”8dp”
android:text=”불꽃놀이했어요~~”
android:id=”@+id/tv_posttext”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
</LinearLayout>
</LinearLayout>
Thread
package com.example.mytestappthread;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView tvDisplay;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvDisplay = findViewById(R.id.tv_display);
findViewById(R.id.btn_start).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startAsyncCalculation();
}
});
}
private void startAsyncCalculation() {
AsyncCalculateTask task = new AsyncCalculateTask();
task.execute(1, Integer.MAX_VALUE);
}
class AsyncCalculateTask extends AsyncTask<Integer, Integer, Integer> {
@Override
protected Integer doInBackground(Integer… integers) {
int number = integers[0];
int count = integers[1];
int result = 0;
int percentUnit = count / 100;
for (int i = 0; i < count; i++) {
result += number;
if (result % percentUnit == 0) {
publishProgress(result/percentUnit);
}
}
return result;
}
// 전
@Override
protected void onPreExecute() {
super.onPreExecute();
}
// 진행상황
@Override
protected void onProgressUpdate(Integer… values) {
super.onProgressUpdate(values);
tvDisplay.setText(values[0] + ” Percent”);
// 로깅
Log.d(“AsyncCalculateTask”, values[0] + ” Percent”);
}
// 후
@Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
tvDisplay.setText(“Result : ” + integer);
}
}
}
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout 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”
android:orientation=”vertical”
android:padding=”16dp”
tools:context=”.MainActivity”>
<TextView
android:id=”@+id/tv_display”
android:textSize=”24sp”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:text=”Hello World!” />
<Button
android:id=”@+id/btn_start”
android:text=”Start”
android:layout_width=”match_parent”
android:layout_height=”wrap_content” />
</LinearLayout>
Glide
https://github.com/bumptech/glide
https://d2.naver.com/helloworld/429368
https://gun0912.tistory.com/17
GlideApp 을 사용하려면
If you wanna use GlideApp you have to add to dependencies annotation processor like on the screenshot
then include an AppGlideModule implementation in your application:
@GlideModule
public final class MyAppGlideModule extends AppGlideModule {}
Do not forget about the @GlideModule annotation. Then you need to Build project. And GlideApp will be automatically generated. Hope this is still helpful.
dependencies {
implementation ‘com.github.bumptech.glide:glide:4.8.0’
annotationProcessor ‘com.github.bumptech.glide:compiler:4.8.0’
}
권한 추가
<uses-permission android:name=”android.permission.INTERNET” />
String url = “https://”;
Glide.with(this).load(url).into(imageView);
GlideApp 추가 후 가능
GlideApp
.with(this)
.load(url)
.centerCrop()
.placeholder(R.drawable.loading_spinner)
.into(myImageView);
package com.example.mytestappglide;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
ImageView ivHyeWon;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivHyeWon = findViewById(R.id.iv_hyewon);
findViewById(R.id.btn_start).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startLoadingHyeWonImage();
}
});
}
private void startLoadingHyeWonImage() {
String url = “https://i.pinimg.com/originals/d3/c0/da/d3c0da7cfa12d081630fb3784c1d9789.jpg”;
GlideApp.with(this).load(url).centerCrop().placeholder(R.mipmap.ic_launcher).into(ivHyeWon);
}
}
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout 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”
android:orientation=”vertical”
tools:context=”.MainActivity”>
<ImageView
android:id=”@+id/iv_hyewon”
android:layout_width=”match_parent”
android:layout_height=”500dp” />
<Button
android:id=”@+id/btn_start”
android:text=”시작”
android:layout_width=”match_parent”
android:layout_height=”wrap_content” />
</LinearLayout>
서버-클라이언트, Okhttp, JSON
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation ‘com.android.support:design:28.0.0’ // Tap
implementation ‘com.android.support:recyclerview-v7:28.0.0’
implementation ‘com.github.bumptech.glide:glide:4.8.0’
annotationProcessor ‘com.github.bumptech.glide:compiler:4.8.0’
implementation ‘com.squareup.okhttp3:okhttp:3.13.1’
implementation ‘com.google.code.gson:gson:2.8.5’
}
api/Api.java
package com.example.mytestappnetwork.api;
public class Api {
public static final String BASE_URL = “http://hooni30.tistory.com”;
public static final String GET_POST = BASE_URL + “/attachment/cfile27.uf@99E5BA4C5C60F727160043.json”;
public static class Post {
int id;
String uploader;
String text;
int likes;
public int getId() {
return id;
}
public String getUploader() {
return uploader;
}
public String getText() {
return text;
}
public int getLikes() {
return likes;
}
public String getCreated_at() {
return created_at;
}
public String getUpdated_at() {
return updated_at;
}
public Image getImage() {
return image;
}
String created_at;
String updated_at;
Image image;
public static class Image {
public String getUrl() {
return url;
}
String url;
}
}
}
EmptyFragment.java
package com.example.mytestappnetwork;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class EmptyFragment extends Fragment {
public EmptyFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_empty, container, false);
}
}
MainActivity.java
package com.example.mytestappnetwork;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.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);
ViewPager viewPager = findViewById(R.id.vp_pager);
TabLayout tabLayout = findViewById(R.id.tl_tabs);
Fragment[] arrFragments = new Fragment[2];
arrFragments[0] = new TimelineFragment();
arrFragments[1] = new EmptyFragment();
MainPagerAdapter adapter = new MainPagerAdapter(getSupportFragmentManager(), arrFragments);
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
}
class MainPagerAdapter extends FragmentPagerAdapter {
Fragment[] arrFragments;
public MainPagerAdapter(FragmentManager fm, Fragment[] arrFragments) {
super(fm);
this.arrFragments = arrFragments;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return “Timeline”;
case 1:
return “Empty”;
default:
return “”;
}
}
@Override
public Fragment getItem(int position) {
return arrFragments[position];
}
@Override
public int getCount() {
return arrFragments.length;
}
}
}
TimelineFragment.java
package com.example.mytestappnetwork;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.example.mytestappnetwork.api.Api;
import com.google.gson.Gson;
import java.io.IOException;
import java.util.ArrayList;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class TimelineFragment extends Fragment {
ArrayList<Api.Post> arrayList;
PostViewAdapter postViewAdapter;
public TimelineFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
fetchAsyncPosts();
// Inflate the layout for this fragment
View baseView = inflater.inflate(R.layout.fragment_timeline, container, false);
RecyclerView recyclerView = baseView.findViewById(R.id.rv_list);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
postViewAdapter = new PostViewAdapter();
recyclerView.setAdapter(postViewAdapter);
return baseView;
}
private void fetchAsyncPosts() {
arrayList = new ArrayList<>();
FetchPostsTask fetchPostsTask = new FetchPostsTask();
fetchPostsTask.execute(Api.GET_POST);
}
class FetchPostsTask extends AsyncTask<String, Void, Api.Post[]> {
@Override
protected Api.Post[] doInBackground(String… strings) {
String url = strings[0];
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
try {
Response response = client.newCall(request).execute();
Gson gson = new Gson();
Api.Post[] posts = gson.fromJson(response.body().charStream(), Api.Post[].class);
return posts;
} catch (IOException e) {
Log.d(“FetchPostsTask”, e.getMessage());
return null;
}
}
@Override
protected void onPostExecute(Api.Post[] posts) {
super.onPostExecute(posts);
for (Api.Post post : posts) {
arrayList.add(post);
}
postViewAdapter.notifyDataSetChanged();
}
}
class PostViewAdapter extends RecyclerView.Adapter<PostViewHolder> {
@Override
public PostViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View baseView = getActivity().getLayoutInflater().inflate(R.layout.item_post, parent, false);
PostViewHolder postViewHolder = new PostViewHolder(baseView);
return postViewHolder;
}
@Override
public void onBindViewHolder(PostViewHolder holder, int position) {
Api.Post item = arrayList.get(position);
String url = item.getImage().getUrl();
Glide.with(TimelineFragment.this)
.load(url)
.into(holder.iv_post);
holder.tv_username.setText(item.getUploader());
holder.tv_posttext.setText(item.getText());
holder.tv_postlikecount.setText( String.valueOf( item.getLikes() ) );
}
@Override
public int getItemCount() {
return arrayList.size();
}
}
class PostViewHolder extends RecyclerView.ViewHolder {
public TextView tv_username, tv_postlikecount, tv_posttext;
public ImageView iv_post;
public PostViewHolder(View itemView) {
super(itemView);
iv_post = itemView.findViewById(R.id.iv_post_img);
tv_username = itemView.findViewById(R.id.tv_user_nickname);
tv_postlikecount = itemView.findViewById(R.id.tv_like_count);
tv_posttext = itemView.findViewById(R.id.tv_post_text);
}
}
}
activity_main.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=”.MainActivity”>
<android.support.design.widget.TabLayout
android:id=”@+id/tl_tabs”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”/>
<android.support.v4.view.ViewPager
android:layout_below=”@id/tl_tabs”
android:id=”@+id/vp_pager”
android:layout_width=”match_parent”
android:layout_height=”match_parent”/>
</RelativeLayout>
fragment_empty.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<FrameLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:background=”#ce93d8″
android:layout_width=”match_parent” android:layout_height=”match_parent”>
</FrameLayout>
fragment_timeline.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<FrameLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”match_parent” android:layout_height=”match_parent”>
<android.support.v7.widget.RecyclerView
android:id=”@+id/rv_list”
android:layout_width=”match_parent”
android:layout_height=”match_parent”/>
</FrameLayout>
item_post.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical” android:layout_width=”match_parent”
android:layout_height=”wrap_content”>
<ImageView
android:scaleType=”centerCrop”
android:id=”@+id/iv_post_img”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:background=”#ffee58″
android:minHeight=”400dp” />
<RelativeLayout
android:layout_width=”match_parent”
android:layout_height=”37dp”
android:paddingLeft=”16dp”
android:paddingRight=”16dp”>
<View
android:id=”@+id/chk_like”
android:layout_width=”24dp”
android:layout_height=”24dp”
android:layout_centerVertical=”true”
android:background=”#d50000″ />
<TextView
android:id=”@+id/tv_like_count”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_centerVertical=”true”
android:layout_marginLeft=”8dp”
android:layout_toRightOf=”@id/chk_like”
android:text=”1234″ />
<View
android:id=”@+id/v_share”
android:layout_width=”24dp”
android:layout_height=”24dp”
android:layout_alignParentRight=”true”
android:layout_centerVertical=”true”
android:background=”#000000″ />
</RelativeLayout>
<View android:layout_width=”match_parent”
android:layout_height=”1dp”
android:background=”#e3e3e3″ />
<LinearLayout
android:layout_width=”match_parent”
android:layout_height=”37dp”
android:gravity=”center_vertical”
android:orientation=”horizontal”
android:paddingLeft=”16dp”
android:paddingRight=”16dp”>
<TextView
android:id=”@+id/tv_user_nickname”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”ansta_”
android:textColor=”#28417a” />
<TextView
android:id=”@+id/tv_post_text”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_marginLeft=”4dp”
android:text=”불꽃놀이했어요~” />
</LinearLayout>
</LinearLayout>
카메라
<uses-permission android:name=”android.permission.INTERNET” />
<uses-permission android:name=”android.permission.READ_EXTERNAL_STORAGE” />
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(include: [‘*.jar’], dir: ‘libs’)
implementation ‘com.android.support:appcompat-v7:28.0.0’
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.android.support:design:28.0.0’
implementation ‘com.android.support:recyclerview-v7:28.0.0’
implementation ‘com.squareup.okhttp3:okhttp:3.13.1’
implementation ‘com.google.code.gson:gson:2.8.5’
implementation ‘com.github.bumptech.glide:glide:4.8.0’
}
api/Api.java
package com.example.mytestappcamera.api;
/**
* Created by g82 on 5/6/16.
*/
public class Api {
public static final String BASE_URL = “http://hooni30.tistory.com”;
public static final String GET_POST = BASE_URL + “/attachment/cfile27.uf@99E5BA4C5C60F727160043.json”;
public static class Image {
String url;
public String getUrl() {
return url;
}
}
/**
* {
* “id”: 1,
* “uploader”: “g82”,
* “text”: “현영아…”,
* “likes”: 0,
* “created_at”: “2016-05-05T07:27:35.962Z”,
* “updated_at”: “2016-05-05T07:27:35.962Z”,
* “image”: {
* “url”: “/uploads/post/image/1/IMG_6940.jpg”
* }
* }
*/
public static class Post {
int id;
String uploader;
String text;
int likes;
String created_at;
String updated_at;
Image image;
public int getId() {
return id;
}
public String getUploader() {
return uploader;
}
public String getText() {
return text;
}
public int getLikes() {
return likes;
}
public String getCreated_at() {
return created_at;
}
public String getUpdated_at() {
return updated_at;
}
public Image getImage() {
return image;
}
}
}
EmptyFragment.java
package com.example.mytestappcamera;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {@link Fragment} subclass.
*/
public class EmptyFragment extends Fragment {
public EmptyFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_empty, container, false);
}
}
MainActivity.java
package com.example.mytestappcamera;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
/**
* TODO
* MainActivity
* ViewPager (below), TabLayout (above)
*
* 2 Fragment
* TimelineFragment, EmptyFragment
*/
Fragment[] arrFragments;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = findViewById(R.id.vp_pager);
TabLayout tabLayout = findViewById(R.id.tl_tabs);
arrFragments = new Fragment[2];
arrFragments[0] = new TimelineFragment();
arrFragments[1] = new EmptyFragment();
MainPagerAdapter adapter = new MainPagerAdapter(getSupportFragmentManager(), arrFragments);
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 2000 && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
TimelineFragment timelineFragment = (TimelineFragment) arrFragments[0];
timelineFragment.startCameraActivity();
}
}
class MainPagerAdapter extends FragmentPagerAdapter {
Fragment[] arrFragments;
public MainPagerAdapter(FragmentManager fm, Fragment[] arrFragments) {
super(fm);
this.arrFragments = arrFragments;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return “Timeline”;
case 1:
return “Empty”;
default:
return “”;
}
}
@Override
public Fragment getItem(int position) {
return arrFragments[position];
}
@Override
public int getCount() {
return arrFragments.length;
}
}
}
PostActivity.java
package com.example.mytestappcamera;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
public class PostActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_post);
ImageView ivPost = findViewById(R.id.iv_post);
Intent intent = getIntent();
Bitmap bitmap = intent.getParcelableExtra(“BitmapImage”);
ivPost.setImageBitmap(bitmap);
// Uri photoUri = intent.getData();
// ivPost.setImageURI(photoUri);
}
}
TimelineFragment.java
package com.example.mytestappcamera;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.example.mytestappcamera.api.Api;
import com.google.gson.Gson;
import java.io.IOException;
import java.util.ArrayList;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
/**
* 8-C
* https://goo.gl/91iKsb
*
*/
public class TimelineFragment extends Fragment {
ArrayList<Api.Post> arrayList;
PostViewAdapter postViewAdapter;
public TimelineFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
fetchAsyncPosts();
// Inflate the layout for this fragment
View baseView = inflater.inflate(R.layout.fragment_timeline, container, false);
RecyclerView recyclerView = baseView.findViewById(R.id.rv_list);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
postViewAdapter = new PostViewAdapter();
recyclerView.setAdapter(postViewAdapter);
baseView.findViewById(R.id.fab_post).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int permissionCheck = ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.READ_EXTERNAL_STORAGE);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
startCameraActivity();
}
else {
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
2000);
//Toast.makeText(getActivity(), “권한이 업습니다.”, Toast.LENGTH_SHORT).show();
}
}
});
return baseView;
}
public void startCameraActivity() {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (cameraIntent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivityForResult(cameraIntent, 1000);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1000 && resultCode == Activity.RESULT_OK) {
Log.d(“onActivityResult”, “Camera SUCCESS”);
Bitmap bitmap = (Bitmap)data.getExtras().get(“data”);
Intent startIntent = new Intent(getActivity(), PostActivity.class);
startIntent.putExtra(“BitmapImage”, bitmap);
// startIntent.setData(data.getData()); 결과가 Uri 일 때.
startActivity(startIntent);
}
}
private void fetchAsyncPosts() {
arrayList = new ArrayList<>();
FetchPostsTask fetchPostsTask = new FetchPostsTask();
fetchPostsTask.execute(Api.GET_POST);
}
class FetchPostsTask extends AsyncTask<String, Void, Api.Post[]> {
@Override
protected Api.Post[] doInBackground(String… strings) {
String url = strings[0];
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
try {
Response response = client.newCall(request).execute();
Gson gson = new Gson();
Api.Post[] posts = gson.fromJson(response.body().charStream(), Api.Post[].class);
return posts;
} catch (IOException e) {
Log.d(“FetchPostsTask”, e.getMessage());
return null;
}
}
@Override
protected void onPostExecute(Api.Post[] posts) {
super.onPostExecute(posts);
for (Api.Post post : posts) {
arrayList.add(post);
}
postViewAdapter.notifyDataSetChanged();
}
}
class PostViewAdapter extends RecyclerView.Adapter<PostViewHolder> {
@Override
public PostViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View baseView = getActivity().getLayoutInflater().inflate(R.layout.item_post, parent, false);
PostViewHolder postViewHolder = new PostViewHolder(baseView);
return postViewHolder;
}
@Override
public void onBindViewHolder(PostViewHolder holder, int position) {
Api.Post item = arrayList.get(position);
String url = item.getImage().getUrl();
Glide.with(TimelineFragment.this)
.load(url)
.into(holder.iv_post);
holder.tv_username.setText(item.getUploader());
holder.tv_posttext.setText(item.getText());
holder.tv_postlikecount.setText(String.valueOf(item.getLikes()));
}
@Override
public int getItemCount() {
return arrayList.size();
}
}
class PostViewHolder extends RecyclerView.ViewHolder {
public TextView tv_username, tv_postlikecount, tv_posttext;
public ImageView iv_post;
public PostViewHolder(View itemView) {
super(itemView);
iv_post = itemView.findViewById(R.id.iv_post_img);
tv_username = itemView.findViewById(R.id.tv_user_nickname);
tv_postlikecount = itemView.findViewById(R.id.tv_like_count);
tv_posttext = itemView.findViewById(R.id.tv_post_text);
}
}
}
activity_main.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=”.MainActivity”>
<android.support.design.widget.TabLayout
android:id=”@+id/tl_tabs”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”/>
<android.support.v4.view.ViewPager
android:layout_below=”@id/tl_tabs”
android:id=”@+id/vp_pager”
android:layout_width=”match_parent”
android:layout_height=”match_parent”/>
</RelativeLayout>
activity_post.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<android.support.constraint.ConstraintLayout 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=”.PostActivity”>
<ImageView
android:id=”@+id/iv_post”
android:layout_width=”match_parent”
android:layout_height=”300dp” />
</android.support.constraint.ConstraintLayout>
fragment_empty.xml
<FrameLayout xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:tools=”http://schemas.android.com/tools”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:background=”#ce93d8″
tools:context=”.EmptyFragment”>
</FrameLayout>
fragment_timeline.xml
<FrameLayout 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=”.TimelineFragment”>
<android.support.v7.widget.RecyclerView
android:id=”@+id/rv_list”
android:layout_width=”match_parent”
android:layout_height=”match_parent”/>
<android.support.design.widget.FloatingActionButton
android:layout_marginRight=”16dp”
android:layout_marginBottom=”16dp”
android:layout_gravity=”bottom|right”
android:id=”@+id/fab_post”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
</FrameLayout>
item_friend.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:padding=”16dp”
android:layout_width=”match_parent” android:layout_height=”wrap_content”>
<ImageView
android:id=”@+id/iv_img”
android:background=”#ffb115″
android:layout_width=”48dp”
android:layout_height=”48dp” />
<TextView
android:id=”@+id/tv_name”
android:textSize=”18sp”
android:layout_marginLeft=”8dp”
android:layout_centerVertical=”true”
android:layout_toRightOf=”@id/iv_img”
android:layout_toLeftOf=”@+id/tv_status”
android:layout_marginRight=”8dp”
android:lines=”1″
android:text=”겜팔이 이름”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
<TextView
android:id=”@+id/tv_status”
android:padding=”8dp”
android:background=”#ffb115″
android:layout_centerVertical=”true”
android:layout_alignParentRight=”true”
android:maxLines=”2″
android:maxWidth=”100dp”
android:text=”카톡안함”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
</RelativeLayout>
item_post.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”>
<ImageView
android:id=”@+id/iv_post_img”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:background=”#ffee58″
android:minHeight=”400dp” />
<RelativeLayout
android:layout_width=”match_parent”
android:layout_height=”37dp”
android:paddingLeft=”16dp”
android:paddingRight=”16dp”>
<View
android:id=”@+id/chk_like”
android:layout_width=”24dp”
android:layout_height=”24dp”
android:layout_centerVertical=”true”
android:background=”#d50000″ />
<TextView
android:id=”@+id/tv_like_count”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_centerVertical=”true”
android:layout_marginLeft=”8dp”
android:layout_toRightOf=”@id/chk_like”
android:text=”1234″ />
<View
android:id=”@+id/v_share”
android:layout_width=”24dp”
android:layout_height=”24dp”
android:layout_alignParentRight=”true”
android:layout_centerVertical=”true”
android:background=”#000000″ />
</RelativeLayout>
<View android:layout_width=”match_parent”
android:layout_height=”1dp”
android:background=”#e3e3e3″ />
<LinearLayout
android:layout_width=”match_parent”
android:layout_height=”37dp”
android:gravity=”center_vertical”
android:orientation=”horizontal”
android:paddingLeft=”16dp”
android:paddingRight=”16dp”>
<TextView
android:id=”@+id/tv_user_nickname”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”ansta_”
android:textColor=”#28417a” />
<TextView
android:id=”@+id/tv_post_text”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_marginLeft=”4dp”
android:text=”불꽃놀이했어요~” />
</LinearLayout>
</LinearLayout>
13. 최종 10강 완결 소스
app/build.gradle
apply plugin: ‘com.android.application’
android {
compileSdkVersion 23
buildToolsVersion “23.0.3”
defaultConfig {
applicationId “madwhale.g82.com.anstagram_gangnam”
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName “1.0”
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’
}
}
}
dependencies {
compile fileTree(dir: ‘libs’, include: [‘*.jar’])
testCompile ‘junit:junit:4.12’
compile ‘com.github.bumptech.glide:glide:3.7.0’
compile ‘com.squareup.okhttp3:okhttp:3.2.0’
compile ‘com.google.code.gson:gson:2.6.2’
compile ‘com.android.support:appcompat-v7:23.3.0’
compile ‘com.android.support:design:23.3.0’
compile ‘com.android.support:recyclerview-v7:23.3.0’
compile ‘com.android.support:support-v4:23.3.0’
}
AndroidManifest.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”http://schemas.android.com/apk/res/android”
package=”madwhale.g82.com.anstagram_gangnam”>
<uses-permission android:name=”android.permission.INTERNET” />
<uses-permission android:name=”android.permission.READ_EXTERNAL_STORAGE” />
<application
android:allowBackup=”true”
android:icon=”@mipmap/ic_launcher”
android:label=”@string/app_name”
android:supportsRtl=”true”
android:theme=”@style/AppTheme”>
<activity android:name=”.MainActivity”>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>
<activity android:name=”.PostActivity”></activity>
</application>
</manifest>
EmptyFragment.java
package madwhale.g82.com.anstagram_gangnam;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {@link Fragment} subclass.
*/
public class EmptyFragment extends Fragment {
public EmptyFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_empty, container, false);
}
}
MainActivity.java
package madwhale.g82.com.anstagram_gangnam;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
/**
* TODO
* MainActivity
* ViewPager (below), TabLayout (above)
*
* 2 Fragment
* TimelineFragment, EmptyFragment
*/
Fragment[] arrFragments;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.vp_pager);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tl_tabs);
arrFragments = new Fragment[2];
arrFragments[0] = new TimelineFragment();
arrFragments[1] = new EmptyFragment();
MainPagerAdapter adapter = new MainPagerAdapter(getSupportFragmentManager(), arrFragments);
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 2000 && grantResults.length > 0) {
TimelineFragment timelineFragment = (TimelineFragment) arrFragments[0];
timelineFragment.startCameraActivity();
}
}
class MainPagerAdapter extends FragmentPagerAdapter {
Fragment[] arrFragments;
public MainPagerAdapter(FragmentManager fm, Fragment[] arrFragments) {
super(fm);
this.arrFragments = arrFragments;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return “Timeline”;
case 1:
return “Empty”;
default:
return “”;
}
}
@Override
public Fragment getItem(int position) {
return arrFragments[position];
}
@Override
public int getCount() {
return arrFragments.length;
}
}
}
PostActivity.java
package madwhale.g82.com.anstagram_gangnam;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import madwhale.g82.com.anstagram_gangnam.api.Api;
import madwhale.g82.com.anstagram_gangnam.uuid.UserUUID;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class PostActivity extends AppCompatActivity {
EditText etText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_post);
Intent intent = getIntent();
final Uri photoUri = intent.getData();
ImageView ivPost = (ImageView) findViewById(R.id.iv_post);
etText = (EditText) findViewById(R.id.et_text);
findViewById(R.id.btn_post).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
post(photoUri.toString(), etText.getText().toString());
}
});
Glide.with(this)
.load(photoUri)
.centerCrop()
.crossFade()
.into(ivPost);
/** Uri content://media/external/images/media/255 */
// Uri -> Bitmap -> File
}
private void post(String uriString, String textString) {
PostTask postTask = new PostTask();
postTask.execute(uriString, textString);
}
private Bitmap getBitmapFromUri(Uri uri) throws IOException {
ParcelFileDescriptor parcelFileDescriptor =
getContentResolver().openFileDescriptor(uri, “r”);
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFileDescriptor(fileDescriptor, null, opts);
int width = opts.outWidth;
int height = opts.outHeight;
float sampleRatio = getSampleRatio(width, height);
opts.inJustDecodeBounds = false;
opts.inSampleSize = (int) sampleRatio;
Bitmap resizedBitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, opts);
Log.d(“Resizing”, “Resized Width / Height : ” + resizedBitmap.getWidth() + “/” + resizedBitmap.getHeight());
parcelFileDescriptor.close();
return resizedBitmap;
}
// 5312 x 2988
private float getSampleRatio(int width, int height) {
final int targetWidth = 1280;
final int targetheight = 1280;
float ratio;
if (width > height) {
// Landscape
if (width > targetWidth) {
ratio = (float) width / (float) targetWidth;
} else ratio = 1f;
} else {
// Portrait
if (height > targetheight) {
ratio = (float) height / (float) targetheight;
} else ratio = 1f;
}
return Math.round(ratio);
}
private File createFileFromBitmap(Bitmap bitmap) throws IOException {
File newFile = new File(getFilesDir(), makeImageFileName());
FileOutputStream fileOutputStream = new FileOutputStream(newFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
fileOutputStream.close();
return newFile;
}
private String makeImageFileName() {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(“yyyyMMdd_hhmmss”);
Date date = new Date();
String strDate = simpleDateFormat.format(date);
return strDate + “.png”;
}
class PostTask extends AsyncTask<String, Void, Boolean> {
ProgressDialog progressDialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = ProgressDialog.show(PostActivity.this, “포스트 업로드 중”, “잠시만 기다려주세요..”, true, false);
}
@Override
protected Boolean doInBackground(String… strings) {
/** Ready for post */
Uri imageUri = Uri.parse(strings[0]);
String text = strings[1];
try {
Bitmap bitmap = getBitmapFromUri(imageUri);
File imageFile = createFileFromBitmap(bitmap);
/** HTTP POST */
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart(“uploader”, UserUUID.getUserUUID(PostActivity.this))
.addFormDataPart(“text”, text)
.addFormDataPart(“image”, makeImageFileName(),
RequestBody.create(MediaType.parse(“image/png”), imageFile))
.build();
Request request = new Request.Builder()
.url(Api.UP_POST)
.post(requestBody)
.build();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.build();
Response response = okHttpClient.newCall(request).execute();
return response.code() == 200;
} catch (IOException e) {
Log.d(“PostTask”, “post failed”, e);
return false;
}
}
@Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
progressDialog.dismiss();
if (aBoolean) {
Toast.makeText(PostActivity.this, “success”, Toast.LENGTH_SHORT).show();
Log.d(“PostTask”, “success”);
} else Log.d(“PostTask”, “failed”);
}
}
}
TimelineFragment.java
package madwhale.g82.com.anstagram_gangnam;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import java.io.IOException;
import java.util.ArrayList;
import madwhale.g82.com.anstagram_gangnam.api.Api;
import madwhale.g82.com.anstagram_gangnam.uuid.UserUUID;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
/**
* 10-E
*/
public class TimelineFragment extends Fragment {
ArrayList<Api.Post> arrayList;
PostViewAdapter postViewAdapter;
private String user_id;
public TimelineFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
user_id = UserUUID.getUserUUID(getActivity());
fetchAsyncPosts();
// Inflate the layout for this fragment
View baseView = inflater.inflate(R.layout.fragment_timeline, container, false);
RecyclerView recyclerView = (RecyclerView) baseView.findViewById(R.id.rv_list);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
postViewAdapter = new PostViewAdapter();
recyclerView.setAdapter(postViewAdapter);
baseView.findViewById(R.id.fab_post).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int permissionCheck = ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.READ_EXTERNAL_STORAGE);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
//startCameraActivity();
startGallery();
} else {
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
2000);
}
}
});
return baseView;
}
public void startCameraActivity() {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (cameraIntent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivityForResult(cameraIntent, 1000);
}
}
public void startGallery() {
Intent cameraIntent = new Intent(Intent.ACTION_GET_CONTENT);
cameraIntent.setType(“image/*”);
if (cameraIntent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivityForResult(cameraIntent, 1000);
}
}
/**
* Main(TimelineFrag) -> run Camera -> main -> Post
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1000 && resultCode == Activity.RESULT_OK) {
Log.d(“onActivityResult”, “Camera SUCCESS”);
Intent startIntent = new Intent(getActivity(), PostActivity.class);
startIntent.setData(data.getData());
startActivity(startIntent);
}
}
private void fetchAsyncPosts() {
arrayList = new ArrayList<>();
FetchPostsTask fetchPostsTask = new FetchPostsTask();
fetchPostsTask.execute(Api.GET_POST + user_id);
}
interface OnLikeListener {
void onLike(LikeTaskResponse response);
}
class FetchPostsTask extends AsyncTask<String, Void, Api.Post[]> {
@Override
protected Api.Post[] doInBackground(String… strings) {
String url = strings[0];
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
try {
Response response = client.newCall(request).execute();
Gson gson = new Gson();
Api.Post[] posts = gson.fromJson(response.body().charStream(), Api.Post[].class);
return posts;
} catch (IOException e) {
Log.d(“FetchPostsTask”, e.getMessage());
return null;
} catch (JsonSyntaxException e) {
Log.d(“FetchPostsTask”, e.getMessage());
return null;
}
}
@Override
protected void onPostExecute(Api.Post[] posts) {
super.onPostExecute(posts);
if (posts == null) return;
for (Api.Post post : posts) {
arrayList.add(post);
}
postViewAdapter.notifyDataSetChanged();
}
}
class PostViewAdapter extends RecyclerView.Adapter<PostViewHolder> {
@Override
public PostViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View baseView = getActivity().getLayoutInflater().inflate(R.layout.item_post, parent, false);
PostViewHolder postViewHolder = new PostViewHolder(baseView);
return postViewHolder;
}
@Override
public void onBindViewHolder(PostViewHolder holder, int position) {
Api.Post item = arrayList.get(position);
String url = item.getImage().getUrl();
Glide.with(TimelineFragment.this)
.load(url)
.centerCrop()
.crossFade()
.into(holder.iv_post);
holder.tv_username.setText(item.getUploader());
holder.tv_posttext.setText(item.getText());
holder.tv_postlikecount.setText(String.valueOf(item.getLikes().getCount()));
holder.chk_like.setChecked(item.getLikes().isUserliked());
}
@Override
public int getItemCount() {
return arrayList.size();
}
}
class PostViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView tv_username, tv_postlikecount, tv_posttext;
public ImageView iv_post;
public CheckBox chk_like;
public PostViewHolder(View itemView) {
super(itemView);
iv_post = (ImageView) itemView.findViewById(R.id.iv_post_img);
tv_username = (TextView) itemView.findViewById(R.id.tv_user_nickname);
tv_postlikecount = (TextView) itemView.findViewById(R.id.tv_like_count);
tv_posttext = (TextView) itemView.findViewById(R.id.tv_post_text);
chk_like = (CheckBox) itemView.findViewById(R.id.chk_like);
chk_like.setOnClickListener(this);
}
@Override
public void onClick(View view) {
final int position = getLayoutPosition();
Api.Post post = arrayList.get(position);
Log.d(“Like”, post.getLikes().isUserliked() + “/” + post.getId() + “/” + user_id);
boolean like = !(post.getLikes().isUserliked());
LikeTaskRequest likeTaskRequest = new LikeTaskRequest(like, post.getId(), user_id);
LikeTask likeTask = new LikeTask(new OnLikeListener() {
@Override
public void onLike(LikeTaskResponse response) {
Api.Post post = arrayList.get(position);
post.getLikes().setCount(response.getLikes());
post.getLikes().setUserliked(response.isResult());
postViewAdapter.notifyDataSetChanged();
}
});
likeTask.execute(likeTaskRequest);
}
}
class LikeTaskRequest {
boolean like;
int post_id;
String user_id;
public LikeTaskRequest(boolean like, int post_id, String user_id) {
this.like = like;
this.post_id = post_id;
this.user_id = user_id;
}
public boolean isLike() {
return like;
}
public int getPost_id() {
return post_id;
}
public String getUser_id() {
return user_id;
}
}
class LikeTaskResponse {
boolean result;
int likes;
public boolean isResult() {
return result;
}
public int getLikes() {
return likes;
}
}
class LikeTask extends AsyncTask<LikeTaskRequest, Void, LikeTaskResponse> {
private OnLikeListener onLikeListener;
public LikeTask(OnLikeListener onLikeListener) {
this.onLikeListener = onLikeListener;
}
@Override
protected LikeTaskResponse doInBackground(LikeTaskRequest… likeTaskRequests) {
LikeTaskRequest likeInfo = likeTaskRequests[0];
RequestBody requestBody = new FormBody.Builder()
.add(“post_id”, String.valueOf(likeInfo.getPost_id()))
.add(“user_id”, likeInfo.getUser_id())
.build();
Request request;
if (likeInfo.isLike()) {
request = new Request.Builder()
.url(Api.POST_LIKE)
.post(requestBody)
.build();
} else {
request = new Request.Builder()
.url(Api.DEL_LIKE)
.delete(requestBody)
.build();
}
OkHttpClient okHttpClient = new OkHttpClient();
try {
Response response = okHttpClient.newCall(request).execute();
if (response.code() == 200) {
Gson gson = new Gson();
LikeTaskResponse taskResponse = gson.fromJson(response.body().charStream(), LikeTaskResponse.class);
return taskResponse;
} else {
return null;
}
} catch (IOException e) {
Log.d(“LikeTask”, “Error”, e);
return null;
}
}
@Override
protected void onPostExecute(LikeTaskResponse likeTaskResponse) {
super.onPostExecute(likeTaskResponse);
onLikeListener.onLike(likeTaskResponse);
Log.d(“Like Response”, likeTaskResponse.getLikes() + “/” + likeTaskResponse.isResult());
}
}
}
api/Api.java
package madwhale.g82.com.anstagram_gangnam.api;
/**
* Created by g82 on 5/6/16.
*/
public class Api {
public static final String BASE_URL = “http://52.79.195.156:3000”;
public static final String GET_POST = BASE_URL + “/api/post?user_id=”;
public static final String UP_POST = BASE_URL + “/api/post”;
public static final String POST_LIKE = BASE_URL + “/api/post/like”;
public static final String DEL_LIKE = BASE_URL + “/api/post/like”;
public static class Image {
String url;
public String getUrl() {
return url;
}
}
public static class Likes {
int count;
boolean userliked;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public boolean isUserliked() {
return userliked;
}
public void setUserliked(boolean userliked) {
this.userliked = userliked;
}
}
/**
*
* {
“id”: 48,
“uploader”: “g82”,
“text”: “하이하이”,
“likes”: {
“count”: 0,
“userliked”: false
},
“image”: {
“url”: “https://bucket-anstagram.s3.ap-northeast-2.amazonaws.com/uploads/post/image/48/20160514_071342.png”
},
“created_at”: “2016-05-14T10:13:46.997Z”,
“updated_at”: “2016-05-14T10:13:46.997Z”
}
*/
public static class Post {
int id;
String uploader;
String text;
Likes likes;
String created_at;
String updated_at;
Image image;
public int getId() {
return id;
}
public String getUploader() {
return uploader;
}
public String getText() {
return text;
}
public Likes getLikes() {
return likes;
}
public String getCreated_at() {
return created_at;
}
public String getUpdated_at() {
return updated_at;
}
public Image getImage() {
return image;
}
}
}
uuid/UserUUID.java
package madwhale.g82.com.anstagram_gangnam.uuid;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.support.annotation.Nullable;
import java.util.UUID;
/**
* Created by g82 on 5/14/16.
*/
public class UserUUID {
private static final String PREF_UUID = “PREF_UUID”;
private static final String PREF_UUID_KEY = “PREF_UUID_KEY”;
@Nullable
public static String getUserUUID(Activity activity) {
SharedPreferences sharedPreferences = activity.getSharedPreferences(PREF_UUID, Context.MODE_PRIVATE);
String user_id = sharedPreferences.getString(PREF_UUID_KEY, null);
if (user_id == null) {
String uuidStr = UUID.randomUUID().toString();
user_id = uuidStr.substring(0, 8);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(PREF_UUID_KEY, user_id);
editor.commit();
}
//f5ad365e
return user_id;
}
}
activity_main.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=”madwhale.g82.com.anstagram_gangnam.MainActivity”>
<android.support.design.widget.TabLayout
android:id=”@+id/tl_tabs”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”/>
<android.support.v4.view.ViewPager
android:layout_below=”@id/tl_tabs”
android:id=”@+id/vp_pager”
android:layout_width=”match_parent”
android:layout_height=”match_parent”/>
</RelativeLayout>
activity_post.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:tools=”http://schemas.android.com/tools”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:orientation=”vertical”
android:paddingBottom=”@dimen/activity_vertical_margin”
android:paddingLeft=”@dimen/activity_horizontal_margin”
android:paddingRight=”@dimen/activity_horizontal_margin”
android:paddingTop=”@dimen/activity_vertical_margin”
tools:context=”madwhale.g82.com.anstagram_gangnam.PostActivity”>
<ImageView
android:id=”@+id/iv_post”
android:layout_width=”match_parent”
android:layout_height=”300dp” />
<EditText
android:id=”@+id/et_text”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:hint=”Input your text.”
android:maxLength=”144″
android:maxLines=”2″ />
<Button
android:id=”@+id/btn_post”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:text=”Post” />
</LinearLayout>
fragment_empty.xml
<FrameLayout xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:tools=”http://schemas.android.com/tools”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:background=”#ce93d8″
tools:context=”madwhale.g82.com.anstagram_gangnam.EmptyFragment”>
</FrameLayout>
fragment_timeline.xml
<FrameLayout 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=”madwhale.g82.com.anstagram_gangnam.TimelineFragment”>
<android.support.v7.widget.RecyclerView
android:id=”@+id/rv_list”
android:layout_width=”match_parent”
android:layout_height=”match_parent”/>
<FrameLayout
android:id=”@+id/fab_post”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_gravity=”bottom|right”
android:layout_marginBottom=”16dp”
android:layout_marginRight=”16dp”
android:background=”@drawable/fab_post” />
<!–<android.support.design.widget.FloatingActionButton–>
<!–android:src=”@drawable/fab_post”–>
<!–android:id=”@+id/fab_post”–>
<!–android:layout_width=”wrap_content”–>
<!–android:layout_height=”wrap_content”–>
<!–android:layout_gravity=”bottom|right”–>
<!–android:layout_marginBottom=”16dp”–>
<!–android:layout_marginRight=”16dp” />–>
</FrameLayout>
item_friend.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:padding=”16dp”
android:layout_width=”match_parent” android:layout_height=”wrap_content”>
<ImageView
android:id=”@+id/iv_img”
android:background=”#ffb115″
android:layout_width=”48dp”
android:layout_height=”48dp” />
<TextView
android:id=”@+id/tv_name”
android:textSize=”18sp”
android:layout_marginLeft=”8dp”
android:layout_centerVertical=”true”
android:layout_toRightOf=”@id/iv_img”
android:layout_toLeftOf=”@+id/tv_status”
android:layout_marginRight=”8dp”
android:lines=”1″
android:text=”겜팔이 이름”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
<TextView
android:id=”@+id/tv_status”
android:padding=”8dp”
android:background=”#ffb115″
android:layout_centerVertical=”true”
android:layout_alignParentRight=”true”
android:maxLines=”2″
android:maxWidth=”100dp”
android:text=”카톡안함”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
</RelativeLayout>
item_post.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”>
<ImageView
android:id=”@+id/iv_post_img”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:background=”#ffee58″
android:minHeight=”400dp” />
<RelativeLayout
android:layout_width=”match_parent”
android:layout_height=”37dp”
android:paddingLeft=”16dp”
android:paddingRight=”16dp”>
<CheckBox
android:id=”@+id/chk_like”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_centerVertical=”true”
android:button=”@drawable/chk_like” />
<TextView
android:id=”@+id/tv_like_count”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_centerVertical=”true”
android:layout_marginLeft=”8dp”
android:layout_toRightOf=”@id/chk_like”
android:text=”1234″ />
<View
android:id=”@+id/v_share”
android:layout_width=”24dp”
android:layout_height=”24dp”
android:layout_alignParentRight=”true”
android:layout_centerVertical=”true”
android:background=”#000000″ />
</RelativeLayout>
<View android:layout_width=”match_parent”
android:layout_height=”1dp”
android:background=”#e3e3e3″ />
<LinearLayout
android:layout_width=”match_parent”
android:layout_height=”37dp”
android:gravity=”center_vertical”
android:orientation=”horizontal”
android:paddingLeft=”16dp”
android:paddingRight=”16dp”>
<TextView
android:id=”@+id/tv_user_nickname”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”ansta_”
android:textColor=”#28417a” />
<TextView
android:id=”@+id/tv_post_text”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_marginLeft=”4dp”
android:text=”불꽃놀이했어요~” />
</LinearLayout>
</LinearLayout>
drawable-xxhdpi/chk_like.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<selector xmlns:android=”http://schemas.android.com/apk/res/android”>
<item android:drawable=”@drawable/heart_bt” android:state_checked=”false” />
<item android:drawable=”@drawable/heart_bt_on” android:state_checked=”true” />
</selector>
fab_post.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<selector xmlns:android=”http://schemas.android.com/apk/res/android”>
<item android:drawable=”@drawable/upload_bt” android:state_pressed=”false” />
<item android:drawable=”@drawable/upload_bt_on” android:state_pressed=”true” />
</selector>
UUID 사용
uuid/UserUUID.java
import java.util.UUID;
public class UserUUID {
private static final String PREF_UUID = “PREF_UUID”;
private static final String PREF_UUID_KEY = “PREF_UUID_KEY”;
public static String getUserUUID(Activity activity) {
SharedPreferences sharedPreferences = activity.getSharedPreferences(PREF_UUID, Context.MODE_PRIVATE);
String user_id = sharedPreferences.getString(PREF_UUID_KEY, null);
if (user_id == null) {
user_id = UUID.randomUUID().toString();
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(PREF_UUID_KEY, user_id);
editor.commit();
}
return user_id;
}
public static String forceGetUserUUID(Activity activity) {
SharedPreferences sharedPreferences = activity.getSharedPreferences(PREF_UUID, Context.MODE_PRIVATE);
String user_id = UUID.randomUUID().toString();
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(PREF_UUID_KEY, user_id);
editor.commit();
return user_id;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
TextView textview_uuid;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textview_uuid = findViewById(R.id.textview_uuid);
findViewById(R.id.button_force_uuid).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String s = UserUUID.forceGetUserUUID(MainActivity.this);
textview_uuid.setText(s);
}
});
String uuid = UserUUID.getUserUUID(this);
textview_uuid.setText(uuid);
}
}