Android

안드로이드 5기 2017년 강의 정리 4 (오준석의 생존코딩)

 

https://www.youtube.com/watch?v=qCyHkVRZnXo&list=PLxTmPHxRH3VWSF7kMcsIaTglWUJZpWeQ9&index=56

https://github.com/suwonsmartapp/MyFirstAndroidApp5ki

MyFirstAndroidApp5ki-master.zip

 

29일차 Notification

30일차 CoordinatorLayout

30일차 암시적 인텐트로 이미지 가져오기

31일차 메모장 아이템 클릭시 화면전환 효과 하던 중

32일차 Service

32일차 메서드 리팩토링, NavigationDrawer

33일차 런타임 퍼미션 체크

33일차 FileZilla, SublimeText 설치

34일차 PHP 진화된 Insert처리

35일차 Realm

 


 

29일차 Notification

 

# Broadcasts overview
https://developer.android.com/guide/components/broadcasts#java

# Notification
https://developer.android.com/guide/topics/ui/notifiers/notifications

 

# BroadcastReceiverActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/BroadcastReceiverActivity.java

# MyLocalReceiver.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/receiver/MyLocalReceiver.java

# activity_broadcast_receiver.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/activity_broadcast_receiver.xml

 

/**
 * 매니페스트에 리시버를 등록 하지 않는다
 * onStart(), onStop() 코드로 리시버 등록, 해제한다
 */
public class BroadcastReceiverActivity extends AppCompatActivity {

    private BroadcastReceiver mReceiver;

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

    }

    @Override
    protected void onStart() {
        super.onStart();

        mReceiver = new MyLocalReceiver();

        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_BATTERY_LOW);
        filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
        filter.addAction("com.example.myapplication.broadcast.ACTION_TEST");

        // 리시버 등록
        registerReceiver(mReceiver, filter);
    }

    @Override
    protected void onStop() {
        super.onStop();

        // 리시버 해제
        unregisterReceiver(mReceiver);
    }

    public void onClick(View view) {
        // 나만의 액션을 쏘기
        Intent intent = new Intent("com.example.myapplication.broadcast.ACTION_TEST");
        // 순서없는
        sendBroadcast(intent);

        // 순서있는
//        sendOrderedBroadcast()
    }
}

 

 

public class MyLocalReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_BATTERY_LOW)) {
            Toast.makeText(context, "로컬 브로드캐스트 리시버다!!!", Toast.LENGTH_LONG).show();
        } else if (intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED)) {
            Toast.makeText(context, "전원이 뽑혔습니다", Toast.LENGTH_SHORT).show();
        } else if (intent.getAction().equals("com.example.myapplication.broadcast.ACTION_TEST")) {
            Toast.makeText(context, "나만의 액션 받기 성공!!", Toast.LENGTH_SHORT).show();

            showNotification(context);
        }
    }

    private void showNotification(Context context) {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
        builder.setContentTitle("나만의 알림");
        builder.setContentText("나만의 텍스트");
        builder.setSmallIcon(R.mipmap.ic_launcher);

        Bitmap bitmap = BitmapFactory.decodeResource(
                context.getResources(), R.mipmap.ic_launcher);

        builder.setLargeIcon(bitmap);

        // 알림을 클릭하면 수행될 인텐트
        Intent resultIntent = new Intent(context, BroadcastReceiverActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(context,
                0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        builder.setContentIntent(pendingIntent);

        // 클릭하면 날리기
        builder.setAutoCancel(true);

        // 색상
        builder.setColor(Color.YELLOW);

        // 기본 알림음
        Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        builder.setSound(uri);

        // 진동
        builder.setVibrate(new long[]{100, 200, 300});

        // 액션
        builder.addAction(R.mipmap.ic_launcher, "확인", pendingIntent);
        builder.addAction(R.mipmap.ic_launcher, "취소", pendingIntent);

        // 알림 표시
        NotificationManagerCompat manager = NotificationManagerCompat.from(context);
        manager.notify(0, builder.build());
    }
}

 

 


 

30일차 CoordinatorLayout

 

#Scrolling Techniques
https://material.io/archive/guidelines/patterns/scrolling-techniques.html

 

# Activity 추가 -> Scrolling Activity

 

<androidx.coordinatorlayout.widget.CoordinatorLayout 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:fitsSystemWindows="true"
    tools:context=".ScrollingActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/app_bar_height"
        android:fitsSystemWindows="true"
        android:theme="@style/Theme.MyFirstAppApplication.AppBarOverlay">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorAccent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:toolbarId="@+id/toolbar">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:layout_collapseMode="parallax"          // 축소될 때 이미지 뷰가 자연스럽게 사라짐 (pin 이면 그냥 사라짐)
                app:layout_collapseParallaxMultiplier="0.3"  // 이미지뷰의 0.3 위치만큼 위로 올라감
                android:background="@drawable/ic_launcher_foreground" />

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/Theme.MyFirstAppApplication.PopupOverlay" />

        </com.google.android.material.appbar.CollapsingToolbarLayout>
    </com.google.android.material.appbar.AppBarLayout>

    <include layout="@layout/content_scrolling" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/fab_margin"
        app:layout_anchor="@id/app_bar"
        app:layout_anchorGravity="bottom|end"
        app:srcCompat="@android:drawable/ic_dialog_email" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

 


 

30일차 암시적 인텐트로 이미지 가져오기

# 갤러리에서 이미지 가져오기

 

# activity_scrolling.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/activity_scrolling.xml

# content_scrolling.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/content_scrolling.xml

 

// 이미지 썸네일 얻기
Glide.with(this).loadFromMediaStore(uri).thumbnail(0.2f).into(mImageView);

Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
ThumbnailUtils.extractThumbnail(bitmap, 100, 100);

 

public class ScrollingActivity extends AppCompatActivity {

    private ImageView mImageView;

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

        mImageView = (ImageView) findViewById(R.id.appbar_image);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }

    public void onImageClick(View view) {
        // 그림 줘
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");

        startActivityForResult(intent, 1000);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == 1000 && resultCode == RESULT_OK && data != null) {
            // 그림이 정상적으로 선택되었을 때

            // 사진 경로
            Uri uri = data.getData();
            // 라이브러리
            Glide.with(this).loadFromMediaStore(uri).into(mImageView);


            // 이미지뷰에 bitmap 설정

            // 사진을 bitmap으로 얻기
            // 그냥
            // Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
            // mImageView.setImageBitmap(bitmap);
            
        }
    }
}

 

 


 

31일차 메모장 아이템 클릭시 화면전환 효과 하던 중

 

# Start an activity using an animation
https://developer.android.com/training/transitions/start-activity#java

 

# MemoActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/MemoActivity.java

# Memo2Activity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/Memo2Activity.java

 

 

# Sample Code : ActivitySceneTransitionBasic
https://github.com/android/animation/tree/main/ActivitySceneTransitionBasic

 

public class MainActivity extends AppCompatActivity {
    ImageView imageView;

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

        imageView = findViewById(R.id.imageView);

        findViewById(R.id.button).setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, DetailActivity.class);

            ActivityOptionsCompat activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(
                    MainActivity.this,                    
                    new Pair<>(imageView, DetailActivity.VIEW_NAME_HEADER_IMAGE));
            
            ActivityCompat.startActivity(MainActivity.this, intent, activityOptions.toBundle());
        });
    }
}

 

 

public class DetailActivity extends AppCompatActivity {
    public static final String VIEW_NAME_HEADER_IMAGE = "detail:header:image";
    private ImageView mHeaderImageView;

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

        mHeaderImageView = findViewById(R.id.imageview_header);
        
        ViewCompat.setTransitionName(mHeaderImageView, VIEW_NAME_HEADER_IMAGE);
        
        mHeaderImageView.setImageResource(R.drawable.blizzard);
    }
}

 

# activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:text="버튼"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/cloudy" />

</LinearLayout>

 

# details.xml

<ImageView
    android:id="@+id/imageview_header"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:scaleType="centerCrop" />

 


 

32일차 Service

 

# Services overview (android developers)
https://developer.android.com/guide/components/services#java

# Bound services overview (android developers)
https://developer.android.com/guide/components/bound-services#java

 

# MyIntentService.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/services/MyIntentService.java

# MyService.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/services/MyService.java

# ServiceActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/ServiceActivity.java

 

 

public class MyIntentService extends IntentService {

    public static final String TAG = MyIntentService.class.getSimpleName();

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent.getAction().equals("play")) {
            Log.d(TAG, "play");
            String path = intent.getStringExtra("path");

        } else {
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(1000);
                    Log.d(TAG, "onHandleIntent: " + i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 

 

public class MyService extends Service {
    public static final String TAG = MyService.class.getSimpleName();

    public MyService() {
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    try {
                        Thread.sleep(1000);
                        Log.d(TAG, "onHandleIntent: " + i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        return START_NOT_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    private final IBinder mBinder = new MyBinder();

    public class MyBinder extends Binder {
        public MyService getService() {
            return MyService.this;
        }
    }

    public long getTime() {
        return new Random().nextLong();
    }
}

 

 

public class ServiceActivity extends AppCompatActivity {

    private MyService mService;
    boolean mBound = false;


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

    public void onStartIntentService(View view) {
        // 1. 순차적으로 실행 된다
        // 2. Worker 스레드로 실행된다
        Intent intent = new Intent(this, MyIntentService.class);
        intent.setAction("play");
        intent.putExtra("path", "file://dfadsf");
        startService(intent);
    }

    public void onStartService(View view) {
        // 1. Main스레드에서 돈다. 그래서 Thread를 별도 생성해서 실행해야 한다
        // 2. 병렬 실행 가능
        Intent intent = new Intent(this, MyService.class);
        startService(intent);
    }

    public void onBindService(View view) {
        Intent intent = new Intent(this, MyService.class);
        bindService(intent, mConnection, BIND_AUTO_CREATE);
    }

    public void getNumber(View view) {
        if (mBound) {
            Toast.makeText(this, "" + mService.getTime(), Toast.LENGTH_SHORT).show();
        }
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 바인드 성공
            MyService.MyBinder binder = (MyService.MyBinder) service;
            mService = binder.getService();
            Toast.makeText(ServiceActivity.this, "바인드 성공", Toast.LENGTH_SHORT).show();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // 강제 종료시에 호출
            mBound = false;
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // 바인딩 끊기
        if (mBound) {
            unbindService(mConnection);
        }
    }
}

 

 


 

32일차 메서드 리팩토링, NavigationDrawer

 

# Update UI components with NavigationUI
https://developer.android.com/guide/navigation/navigation-ui

 


 

33일차 런타임 퍼미션 체크

 

# Request App Permissions
https://developer.android.com/training/permissions/requesting#java

 

# GalleryActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/GalleryActivity.java

 

 

public class GalleryActivity extends AppCompatActivity implements GalleryFragment.OnFragmentInteractionListener {

    private Fragment mFragment;

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

        mFragment = getSupportFragmentManager().findFragmentById(R.id.fragment);
    }

    @Override
    public void onFragmentInteraction(Uri uri) {

    }

    // onRequestPermissionsResult 는 액티비티에서 작성해야함.
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        mFragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

 

 

public class GalleryFragment extends Fragment {

    private OnFragmentInteractionListener mListener;
    private GridView mGridView;

    public GalleryFragment() {
        // Required empty public constructor
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        // 리스너 연결
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Bundle 받을꺼야
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // 뷰 가져오기
        return inflater.inflate(R.layout.fragment_gallery, container, false);
    }

    // 뷰 가져온 이후 할 것
    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // 뷰
        mGridView = (GridView) view.findViewById(R.id.grid_view);

        // Here, thisActivity is the current activity
        if (ContextCompat.checkSelfPermission(getActivity(),
                Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {

            // Should we show an explanation?
            // 설명을 보여줄 것인가
            if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
                    Manifest.permission.READ_EXTERNAL_STORAGE)) {

                // 사용자 응답을 기다리는 설명을 비동기로 보여주기
                // 권한 체크를 안 하면 이 기능을 사용할 수 없다고 어필하고

                // 다이얼로그 표시
                // 이 권한을 수락하지 않으면 이 기능을 사용할 수 없습니다
                // 권한을 설정하시려면 설정 > 애플리케이션 > 앱이름 가서 설정하세요

                // 다시 권한 요청

                // Show an expanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.
                ActivityCompat.requestPermissions(getActivity(),
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        1000);

            } else {

                // No explanation needed, we can request the permission.
                // 권한을 요청

                ActivityCompat.requestPermissions(getActivity(),
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        1000);

                // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                // app-defined int constant. The callback method gets the
                // result of the request.
            }
        } else {

            // 이미 권한이 있을 때
            getPicture();
        }


    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        switch (requestCode) {
            case 1000: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    // permission was granted, yay! Do the
                    // contacts-related task you need to do.

                    // 승인 됨
                    Toast.makeText(getActivity(), "권한 승인됨", Toast.LENGTH_SHORT).show();


                    getPicture();


                } else {

                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.


                    // 앱을 종료합니다
                    Toast.makeText(getActivity(), "권한 거부됨", Toast.LENGTH_SHORT).show();

                    getActivity().finish();
                }
                return;
            }

            // other 'case' lines to check for other
            // permissions this app might request
        }
    }

    private void getPicture() {
        // 사진 정보
        // 미디어(사진, 동영상, 음악) media db
        // provider로 media db 정보를 가져와야 됨
        Cursor cursor = getActivity().getContentResolver().query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                null,
                null,
                null,
                null
        );

        // 사진을 뿌릴 어댑터
        MyCursorAdapter adapter = new MyCursorAdapter(getActivity(), cursor);
        mGridView.setAdapter(adapter);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

    }

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     * <p>
     * See the Android Training lesson <a href=
     * "http://developer.android.com/training/basics/fragments/communicating.html"
     * >Communicating with Other Fragments</a> for more information.
     */
    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
    }


    private static class MyCursorAdapter extends CursorAdapter {

        public MyCursorAdapter(Context context, Cursor c) {
            super(context, c, false);
        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            View convertView = LayoutInflater.from(context)
                    .inflate(R.layout.item_gallery, parent, false);

            ViewHolder viewHolder = new ViewHolder();
            viewHolder.imageView = (ImageView) convertView.findViewById(R.id.image_view);
            convertView.setTag(viewHolder);

            return convertView;
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            ViewHolder viewHolder = (ViewHolder) view.getTag();

            String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));

            Glide.with(context).load(path).into(viewHolder.imageView);
        }

    }

    private static class ViewHolder {
        ImageView imageView;
    }
}

 

 


 

33일차 FileZilla, SublimeText 설치

 

 


 

34일차 PHP 진화된 Insert처리

 

# ResultModel.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/login/ResultModel.java

# RetrofitUtil.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/login/RetrofitUtil.java

# UserApi.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/login/UserApi.java

 

 

public class LoginActivity extends AppCompatActivity implements View.OnClickListener {

    // UI references.
    private AutoCompleteTextView mEmailView;
    private EditText mPasswordView;
    private View mProgressView;
    private View mLoginFormView;
    private UserApi mUserApi;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        // Set up the login form.
        mEmailView = (AutoCompleteTextView) findViewById(R.id.email);
        mPasswordView = (EditText) findViewById(R.id.password);

        Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button);

        mLoginFormView = findViewById(R.id.login_form);
        mProgressView = findViewById(R.id.login_progress);

        mUserApi = new RetrofitUtil().getUserApi();

        mEmailSignInButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        Call<ResultModel> call = mUserApi.login(mEmailView.getText().toString(),
                mPasswordView.getText().toString());

        // 비동기 네트워크 처리
        call.enqueue(new Callback<ResultModel>() {
            @Override
            public void onResponse(Call<ResultModel> call, Response<ResultModel> response) {
                // 정상 결과
                ResultModel result = response.body();
                if (result.getResult().equals("ok")) {
                    // 성공
                    startActivity(new Intent(LoginActivity.this, MemoActivity.class));
                } else {
                    Toast.makeText(LoginActivity.this, "실패", Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call<ResultModel> call, Throwable t) {
                // 네트워크 문제
                Toast.makeText(LoginActivity.this, "네트워크 연결 실패", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

 

 

public class RetrofitUtil {

    private Retrofit mRetrofit;

    private UserApi mUserApi;

    public RetrofitUtil() {
        mRetrofit = new Retrofit.Builder()
                .baseUrl(UserApi.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        mUserApi = mRetrofit.create(UserApi.class);
    }

    public UserApi getUserApi() {
        return mUserApi;
    }

}

 

 

public interface UserApi {

    String BASE_URL = "http://suwonsmartapp.iptime.org/test/junsuk2/";

    // 로그인
    @GET("login.php")
    Call<ResultModel> login(@Query("email") String email,
                            @Query("password") String password);

    // 회원가입
    @GET("insert.php")
    Call<ResultModel> signUp();

}

 

 


 

35일차 Realm

 

# realm.io
https://realm.io/kr/docs/java/latest/

 

# sqlite (android developer)
https://developer.android.com/training/data-storage/sqlite#java

 

https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/RealmExamActivity.java

https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/models/User.java

https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/MyApplication.java

https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/activity_reaml_exam.xml

https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/AndroidManifest.xml

 

# AndroidManifest.xml

<application
    android:name=".MyApplication"

 

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Realm.init(this);
        RealmConfiguration config = new RealmConfiguration.Builder().build();
        Realm.setDefaultConfiguration(config);
    }
}

 

# 프로젝트 수준 build.gradle

buildscript {
    dependencies {

        classpath "io.realm:realm-gradle-plugin:3.5.0"
    }

 

 

public class User extends RealmObject {
    private String email;
    private String password;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("User{");
        sb.append("email='").append(email).append('\'');
        sb.append(", password='").append(password).append('\'');
        sb.append('}');
        return sb.toString();
    }
}

 

# app 수준 build.gradle

plugins {
    id 'realm-android'
}

 

 

public class RealmExamActivity extends AppCompatActivity implements RealmChangeListener<Realm> {

    private EditText mEmail;
    private EditText mPassword;
    private EditText mNewPassword;
    private TextView mResultText;

    private Realm mRealm;

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

        mEmail = (EditText) findViewById(R.id.email_edit);
        mPassword = (EditText) findViewById(R.id.password_edit);
        mNewPassword = (EditText) findViewById(R.id.new_password_edit);
        mResultText = (TextView) findViewById(R.id.result_text);

        mRealm = Realm.getDefaultInstance();
        mRealm.addChangeListener(this);

        showResult();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        mRealm.removeAllChangeListeners();
        mRealm.close();
    }

    public void SignIn(View view) {
        if (mRealm.where(User.class)
                .equalTo("email", mEmail.getText().toString())
                .equalTo("password", mPassword.getText().toString())
                .count() > 0) {
            Toast.makeText(this, "로그인 성공", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "로그인 실패", Toast.LENGTH_SHORT).show();
        }
    }

    public void SignUp(View view) {
        mRealm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                if (realm.where(User.class)
                        .equalTo("email", mEmail.getText().toString())
                        .count() == 0) {

                    User user = realm.createObject(User.class);
                    user.setEmail(mEmail.getText().toString());
                    user.setPassword(mPassword.getText().toString());
                }
            }
        });
    }

    public void updatePassword(View view) {
        mRealm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                User user = realm.where(User.class)
                        .equalTo("email", mEmail.getText().toString())
                        .findFirst();

                user.setPassword(mNewPassword.getText().toString());
            }
        });
    }

    public void deleteAccount(View view) {
        mRealm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                realm.where(User.class)
                        .equalTo("email", mEmail.getText().toString())
                        .findAll()
                        .deleteAllFromRealm();
            }
        });
    }

    private void showResult() {
        RealmResults<User> results = mRealm.where(User.class).findAll();
        mResultText.setText(results.toString());
    }

    @Override
    public void onChange(Realm element) {
        // DB가 갱싱 될 때 마다 호출
        showResult();
    }
}

 

# activity_realm_exam.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <EditText
        android:id="@+id/email_edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="email"
        android:inputType="textEmailAddress" />

    <EditText
        android:id="@+id/password_edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="password"
        android:inputType="textPassword" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="SignIn"
        android:text="로그인" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="SignUp"
        android:text="가입" />


    <EditText
        android:id="@+id/new_password_edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="수정할 비밀번호" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="updatePassword"
        android:text="비번 수정" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="deleteAccount"
        android:text="탈퇴" />

    <TextView
        android:id="@+id/result_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp" />

</LinearLayout>

 

 


 

 

 

Related posts

Leave a Comment