728x90

안드로이드 Broadcast 를 테스트 해보고 정리해둔다.
개념도 제대로 모른채 구글링해서 나온 예제를 실행해보고 실행이 되는구나 하는 정도만으로는 응용이 불가능하다는 걸 테스트 해보면서 몸소 느끼고 있다. Android Studio 기반에서 테스트한 것을 적어둔다.

안드로이드 6.0 에서 SMS 권한이 없는데 허용할 것인지 문의하는 창도 뜨고 잘 동작된다.


BroadCast.zip


Android Studio 는 main 폴더에 핵심적인 내용이 들어가 있으므로 이것만 파일 첨부하면 이걸 이용해서 다시 작성하기가 쉽다.


BroadcastReceiver는 모든 어플에게 다 전해지는 것이다. (시스템 매니저가 알아서 보내는 것)


// IntentFilter 전달받는 여러 인텐트중 특정 인텐트만 고르겠다는 의도
IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED);
registerReceiver(mUsbAttachReceiver , filter); // 브로드캐스트리시버 등록


또는

IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USB_DEVICE_ATTACHED);
registerReceiver(mUsbAttachReceiver, filter);  // 브로드캐스트리시버 등록


Broadcast Receiver(방송수신자)는 BroadcastReceiver 클래스를 상속받아 작성한다.

Broadcast 메시지가 수신되면 onReceive 메서드가 자동 호출된다.

public class Broadcastreceiver extends BroadcastReceiver {

    private Bundle bundle;
    private SmsMessage currentSMS;
    private String message;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
            Log.d("onReceive()","부팅완료");
            //Intent i = new Intent(context, ScreenService.class);
            //context.startService(i);
        }


        if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
            Log.d("SMSBroadcastReceiver", "SMS 메시지가 수신되었습니다.");
            //Toast.makeText(context, "문자가 수신되었습니다", Toast.LENGTH_SHORT).show();
            bundle = intent.getExtras();
            if (bundle != null) {
                Object[] pdu_Objects = (Object[]) bundle.get("pdus");
                if (pdu_Objects != null) {
                    for (Object aObject : pdu_Objects) {
                        currentSMS = getIncomingMessage(aObject, bundle);
                        String senderNo = currentSMS.getDisplayOriginatingAddress();
                        message = currentSMS.getDisplayMessageBody();
                        Toast.makeText(context, "senderNum: " + senderNo + " :\n message: " + message, Toast.LENGTH_LONG).show();
                    }
                    this.abortBroadcast();
                    // End of loop
                }
            }
        } // bundle null



AndroidManifest.xml 을 사용하여 Broadcast Receiver 를 등록

- 앱이 실행중이 아니더라도 지정한 Broadcast 메시지를 수신(지정한 Action 발생)되면 Broadcast Receiver 가 자동 실행된다.


동적으로 Broadcast Receiver 를 등록하면, 앱이 실행중일 때만 Broadcast Receiver 가 수행되며, 동적으로 Broadcast Receiver 를 추가/제거가 가능하다.


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.tistory.link2me.sms_receive">

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.READ_SMS"/>
    <uses-permission android:name="android.permission.RECEIVE_SMS" />

    <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>
        <receiver
            android:name ="com.tistory.link2me.sms_receive.Broadcastreceiver"
            android:enabled="true">
            <intent-filter android:priority="10000">
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>

    </application>

</manifest>


AndroidManifest.xml에 해당 리시버를 등록하고 intent-filter로 원하는 브로드캐스팅 받을 Action을 등록한다.

즉, intent-filter는 어떤 intent를 필터링해서 들을것인지 설정하는 것이다.

안드로이드 앱에서 알고 싶은 이벤트들이 있을수 있다. 가령
- 배터리 부족
- 네트워크 연결 / 중단
- SD카드 삽집 / 제거
- SMS 수신
- 카메라 버튼이 눌렸을때
- 폰의 날짜, 시간이 변동되었을때
- 비행기 모드 전환시
- 어플 설치/제거
- 재부팅/종료
- 매 분마다 수신


android:enabled="true" : 시스템이 알아서 Broadcastreceiver를 실행한다는 의미다. default 가 true 다.

android:exported="false" : 외부 어플리케이션에서는 사용할 수 없으며 같은 앱 또는 같은 UserId를 가진 놈만 호출할 수 있다는 뜻이다. (이걸 적어두면 메시지 수신이 제대로 안됨)
android:priority : 숫자가 높을수록 우선순위가 높으며, 우선순위가 높은 리시버부터 순차적으로 메세지가 전달된다.


 === Broadcastreceiver.java === 

 package com.tistory.link2me.sms_receive;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;

public class Broadcastreceiver extends BroadcastReceiver {
    private Bundle bundle;
    private SmsMessage currentSMS;
    private String message;

    @Override
    public void onReceive(Context context, Intent intent) {

        if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
            Log.d("onReceive()","부팅완료");
            //Intent i = new Intent(context, ScreenService.class);
            //context.startService(i);
        }

        if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
            Log.d("onReceive()","스크린 ON");
        }

        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
            Log.d("onReceive()","스크린 OFF");
        }

        if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
            Log.d("SMSBroadcastReceiver", "SMS 메시지가 수신되었습니다.");
            Toast.makeText(context, "문자가 수신되었습니다", Toast.LENGTH_SHORT).show();
            bundle = intent.getExtras();
            if (bundle != null) {
                Object[] pdu_Objects = (Object[]) bundle.get("pdus");
                if (pdu_Objects != null) {
                    for (Object aObject : pdu_Objects) {
                        currentSMS = getIncomingMessage(aObject, bundle);
                        String senderNo = currentSMS.getDisplayOriginatingAddress();
                        message = currentSMS.getDisplayMessageBody();
                        Toast.makeText(context, "senderNum: " + senderNo + " :\n message: " + message, Toast.LENGTH_LONG).show();
                    }
                    this.abortBroadcast();
                    // End of loop
                }
            }
        } // bundle null
    }

    private SmsMessage getIncomingMessage(Object aObject, Bundle bundle) {
        SmsMessage currentSMS;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            String format = bundle.getString("format");
            currentSMS = SmsMessage.createFromPdu((byte[]) aObject, format);
        } else {
            currentSMS = SmsMessage.createFromPdu((byte[]) aObject);
        }
        return currentSMS;
    }
}


문자수신시각 정보 추가시

Date curDate = new Date(currentSMS.getTimestampMillis());
SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
String receivedDate = sdf.format( curDate );



=== MainActivity.java ===

 package com.tistory.link2me.sms_receive;

import android.Manifest;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

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

        int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS);
        if(permissionCheck == PackageManager.PERMISSION_GRANTED){
            Toast.makeText(this, "SMS 수신권한 있음", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "SMS 수신권한 없음", Toast.LENGTH_SHORT).show();
            if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.RECEIVE_SMS)){
                Toast.makeText(this, "SMS 권한 설정이 필요함", Toast.LENGTH_SHORT).show();
            } else {
                // 권한이 할당되지 않았으면 해당 권한을 요청
                ActivityCompat.requestPermissions(this,new String[] {Manifest.permission.RECEIVE_SMS},1);
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == 1) {
            for (int i = 0; i < permissions.length; i++) {
                if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(this, permissions[i] + " 권한이 승인됨.", Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(this, permissions[i] + " 권한이 거부됨.", Toast.LENGTH_LONG).show();
                }
            }
        }
    }

}



블로그 이미지

Link2Me

,
728x90

Eclipse 에서 만든 코드를 Android Studio 로 변환하고 나서 신규로 코드를 추가하면 문제가 생긴다.

FCM 을 이용한 메시지 발송시 메시지 수신하는 걸 해결하지 못한 상태다.

FCM 메시지 발송을 위한 TokenID 를 회원DB에 저장하는 방법을 Login.java 코드를 이용하여 구현했다.


Login.java 파일에서 로그인 정보를 입력하고 확인을 누르면,  POST 방식으로 서버에 있는 loginChk.php 파일로 전송되어 내용을 확인하고 정보를 기록하고 결과값을 반환한다.

서버에서 결과값은 echo 문을 다시 안드로드이드폰에서 받아서 그 결과값을 기준으로 로그인 성공, 로그인 실패, 인증된 단말인지 여부 체크 등을 한다.


사용자 기기 토큰 정보를 획득하는 코드는 http://blog.naver.com/PostView.nhn?blogId=cosmosjs&logNo=220739141098&categoryNo=0&parentCategoryNo=56&viewDate=&currentPage=1&postListTopCurrentPage=1&from=search 를 참조하면서 해보는 중이다.


=== Login.java ====

package com.tistory.link2me.addresschart;

import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;

import com.google.firebase.iid.FirebaseInstanceId;

import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;

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

public class Login extends Activity {

    String getDeviceID; // 스마트기기의 장치 고유값
    ProgressDialog dialog = null;
    EditText etId;
    EditText etPw;

    String loginID;
    String loginPW;
    CheckBox autologin;
    Boolean loginChecked;
    List<NameValuePair> params;
    public SharedPreferences settings;
    CookieManager cookieManager;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.login);

        // ActionBar 제거하기
        ActionBar actionbar = getActionBar();
        actionbar.hide();

        // 네트워크 연결상태 체크
        if(NetworkConnection() == false){
            NotConnected_showAlert();
        }

        etId = (EditText) findViewById(R.id.login_id_edit);
        etPw = (EditText) findViewById(R.id.login_pw_edit);
        autologin = (CheckBox) findViewById(R.id.autologinchk);

        settings = getSharedPreferences("settings", Activity.MODE_PRIVATE);
        loginChecked = settings.getBoolean("LoginChecked", false);
        if (loginChecked) {
            etId.setText(settings.getString("loginID", ""));
            etPw.setText(settings.getString("loginPW", ""));
            autologin.setChecked(true);
        }

        if(!settings.getString("loginID", "").equals("")) etPw.requestFocus();

        CookieSyncManager.createInstance(this);
        cookieManager = CookieManager.getInstance();
        CookieSyncManager.getInstance().startSync();

        Button submit = (Button) findViewById(R.id.login_btn);
        submit.setOnClickListener(new Button.OnClickListener(){

            @Override
            public void onClick(View v) {
                dialog = ProgressDialog.show(Login.this, "", "Validating user...", true);
                 new Thread(new Runnable() {
                        public void run() {
                            login();
                        }

                      }).start();
            }

        });

    }

    void login() {
        try {
            loginID = etId.getText().toString().trim();
            loginPW = etPw.getText().toString().trim();

            // 단말기의 ID 정보를 얻기 위해서는 READ_PHONE_STATE 권한이 필요
            TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
            if (mTelephony.getDeviceId() != null){
                getDeviceID = mTelephony.getDeviceId();  // 스마트폰 기기 정보
            } else {
                getDeviceID = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
            }

            // 사용자 기기의 고유 토큰 정보를 획득
            String getToken = FirebaseInstanceId.getInstance().getToken();

            String postURL = Value.IPADDRESS + "/loginChk.php";
            HttpPost post = new HttpPost(postURL);

            // 전달할 인자들
            params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("loginID", loginID));
            params.add(new BasicNameValuePair("loginPW", loginPW));
            params.add(new BasicNameValuePair("deviceID", getDeviceID));
            params.add(new BasicNameValuePair("tokenID", getToken));

            UrlEncodedFormEntity ent = new UrlEncodedFormEntity(params,HTTP.UTF_8);
            post.setEntity(ent);

            HttpClient httpclient = new DefaultHttpClient();

            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            final String responsePost = httpclient.execute(post, responseHandler);

            System.out.println("DeviceID : " + getDeviceID);
            System.out.println("Login Token : " + getToken);
            System.out.println("Response : " + responsePost);

            runOnUiThread(new Runnable() {
                public void run() {
                    dialog.dismiss();
                }
            });

            if(responsePost.equalsIgnoreCase("1")){ // 로그인 정보 일치
                runOnUiThread(new Runnable() {
                    public void run() {
                        Toast.makeText(Login.this,"Login Success", Toast.LENGTH_SHORT).show();
                    }
                });

                // 쿠키 정보 생성을 통한 PHP 세션 접속 유지 처리
                List<Cookie> cookies = ((DefaultHttpClient)httpclient).getCookieStore().getCookies();
                if (!cookies.isEmpty()) {
                    for (int i = 0; i < cookies.size(); i++) {
                        String cookieString = cookies.get(i).getName() + "="
                                    + cookies.get(i).getValue();
                        Log.e("PHP_setCookie", cookieString);
                        cookieManager.setCookie(Value.IPADDRESS, cookieString);
                    }
                }
                Thread.sleep(300);

                startActivity(new Intent(this.getApplicationContext(), MainActivity.class));
                finish(); // finish()를 호출해서 Activity를 없애줌

            } else if(responsePost.equalsIgnoreCase("-1")){ // 등록된 단말기와 불일치
                deviceDismatch_showAlert();
            } else {
                showAlert();
            }
        } catch(Exception e) {
            dialog.dismiss();
            System.out.println("Exception : " + e.getMessage());
        }

    }

    public void onStop(){
        // 어플리케이션이 화면에서 사라질때
        super.onStop();
        // 자동 로그인이 체크되어 있고, 로그인에 성공했으면 폰에 자동로그인 정보 저장
        if (autologin.isChecked()) {
            settings = getSharedPreferences("settings",Activity.MODE_PRIVATE);
            SharedPreferences.Editor editor = settings.edit();

             editor.putString("loginID", loginID);
             editor.putString("loginPW", loginPW);
             editor.putBoolean("LoginChecked", true);

             editor.commit();
        } else {
            // 자동 로그인 체크가 해제되면 폰에 저장된 정보 모두 삭제
            settings = getSharedPreferences("settings", Activity.MODE_PRIVATE);
            SharedPreferences.Editor editor = settings.edit();
            editor.clear(); // 모든 정보 삭제
            editor.commit();
        }

    }

    public void deviceDismatch_showAlert(){
        Login.this.runOnUiThread(new Runnable() {
            public void run() {
                AlertDialog.Builder builder = new AlertDialog.Builder(Login.this);
                builder.setTitle("등록단말 불일치");
                builder.setMessage("최초 등록된 단말기가 아닙니다.\n" + "관리자에게 문의하여 단말기 변경신청을 하시기 바랍니다.")
                       .setCancelable(false)
                       .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                           public void onClick(DialogInterface dialog, int id) {
                           }
                       });
                AlertDialog alert = builder.create();
                alert.show();
            }
        });
    }

    public void showAlert(){
        Login.this.runOnUiThread(new Runnable() {
            public void run() {
                AlertDialog.Builder builder = new AlertDialog.Builder(Login.this);
                builder.setTitle("로그인 에러");
                builder.setMessage("로그인 정보가 일치하지 않습니다.")
                       .setCancelable(false)
                       .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                           public void onClick(DialogInterface dialog, int id) {
                           }
                       });
                AlertDialog alert = builder.create();
                alert.show();
            }
        });
    }

    private void NotConnected_showAlert() {
        AlertDialog.Builder builder = new AlertDialog.Builder(Login.this);
        builder.setTitle("네트워크 연결 오류");
        builder.setMessage("사용 가능한 무선네트워크가 없습니다.\n" + "먼저 무선네트워크 연결상태를 확인해 주세요.")
               .setCancelable(false)
               .setPositiveButton("확인", new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       finish(); // exit
                        //application 프로세스를 강제 종료
                        android.os.Process.killProcess(android.os.Process.myPid() );
                   }
               });
        AlertDialog alert = builder.create();
        alert.show();

    }

    private boolean NetworkConnection() {
        ConnectivityManager manager = (ConnectivityManager) getSystemService (Context.CONNECTIVITY_SERVICE);
        boolean isMobileAvailable = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isAvailable();
        boolean isMobileConnect = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnectedOrConnecting();
        boolean isWifiAvailable = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isAvailable();
        boolean isWifiConnect = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnectedOrConnecting();

        if ((isWifiAvailable && isWifiConnect) || (isMobileAvailable && isMobileConnect)){
            return true;
        }else{
            return false;
        }
    }

    // Back 버튼을 누르면 어플 종료여부 확인 처리
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if( keyCode == KeyEvent.KEYCODE_BACK ) {
            new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert).setTitle("Quit").setMessage("어플을 종료하시겠습니까?").setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                @Override
                public void onClick( DialogInterface dialog, int which) {
                    moveTaskToBack(true); // 본Activity finish후 다른 Activity가 뜨는 걸 방지.
                    finish();
                    //application 프로세스를 강제 종료
                    android.os.Process.killProcess(android.os.Process.myPid() );
                }
        }).setNegativeButton( "No", null ).show();

        return true;
      }

      return super.onKeyDown(keyCode, event);
     }

    @Override
    protected void onResume()
    {
        super.onResume();
        CookieSyncManager.getInstance().startSync();
    }

    @Override
    protected void onPause()
    {
        super.onPause();
        CookieSyncManager.getInstance().stopSync(); // 동기화 종료
    }
}
 


이제 MySQL DB 및 PHP 코드를 구현해야 한다.

MySQL DB에는 tokenID 칼럼을 추가한다. Varchar(200) 으로 길이를 설정해준다. 토콘의 길이가 상당히 길더라.

테스트하는 회원 테이블은 회원ID와 회원 Data 를 분리하여 저장하는 방식으로 만들어보고 있다.


테이블 구조

CREATE TABLE IF NOT EXISTS `member_id` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `site` int(11) NOT NULL DEFAULT '0',
  `id` varchar(50) NOT NULL DEFAULT '',
  `pw` varchar(50) NOT NULL DEFAULT '',
  `code` int(6) NOT NULL DEFAULT '0',
  `admin` int(2) NOT NULL DEFAULT '0',
  PRIMARY KEY (`uid`),
  UNIQUE KEY `id` (`id`),
  KEY `code` (`code`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;


CREATE TABLE IF NOT EXISTS `member_data` (
  `memberuid` int(11) NOT NULL,
  `site` int(11) NOT NULL DEFAULT '0',
  `auth` tinyint(4) NOT NULL DEFAULT '0',
  `level` int(11) NOT NULL DEFAULT '0',
  `admin` tinyint(4) NOT NULL DEFAULT '0',
  `email` varchar(50) NOT NULL DEFAULT '',
  `name` varchar(30) NOT NULL DEFAULT '',
  `nic` varchar(50) NOT NULL DEFAULT '',
  `grade` varchar(20) NOT NULL DEFAULT '',
  `photo` varchar(200) NOT NULL DEFAULT '',
  `sex` tinyint(4) NOT NULL DEFAULT '0',
  `officeNO` varchar(14) NOT NULL DEFAULT '',
  `mobileNO` varchar(14) NOT NULL DEFAULT '',
  `num_login` int(11) NOT NULL DEFAULT '0',
  `d_regis` varchar(14) NOT NULL DEFAULT '',
  `tokenID` varchar(200) DEFAULT NULL,
  `phoneID` varchar(60) DEFAULT NULL,
  PRIMARY KEY (`memberuid`),
  KEY `site` (`site`),
  KEY `auth` (`auth`),
  KEY `level` (`level`),
  KEY `admin` (`admin`),
  KEY `email` (`email`),
  KEY `name` (`name`),
  KEY `nic` (`nic`),
  KEY `sex` (`sex`),
  KEY `d_regis` (`d_regis`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 



=== loginChk.php ===

<?php
if(!isset($_SESSION)) {
    session_start();
}

@extract($_POST); // POST 전송으로 전달받은 값 처리
if(isset($loginID) && !empty($loginID) && isset($loginPW) && !empty($loginPW)) {

    $deviceID = $deviceID ? $deviceID : '';

    if(empty($deviceID)){
        require_once 'dbconnect.php'; // db접속
        require_once 'phpclass/loginClass.php';

        $c=new LoginClass();

        $row = $c->WebUserAuthCheck($loginID,$loginPW);
        if(is_array($row)) {
            if($row['code'] > 0) {
                $_SESSION['userID'] = $row['id'];
                $_SESSION['userPW'] = md5($loginPW);
                $_SESSION['code'] = $row['code'];
                $_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
                $_SESSION['ua'] = $_SERVER['HTTP_USER_AGENT'];

                echo("<meta http-equiv='Refresh' content='0; URL=m/list.php'>");
            } else {
                echo '권한 불가';
            }
        } else if($row == '0'){
            $msg ='정보가 올바르지 않습니다';
            echo "<script>alert('".$msg."');history.go(-1);</script>";
        } else {
            $msg ='정보가 올바르지 않습니다';
            echo "<script>alert('".$msg."');history.go(-1);</script>";
        }

    } else {
        require_once 'db.info.php';
        require_once 'phpclass/dbClass.php';
        $conn=new MySQLiDbClass();
        $dbconn = $conn->isConnectDb($DB); // 안드로이드폰에서는 반드시 객체로 생성해야 정상접속
        require_once 'phpclass/loginClass.php';
        $c=new LoginClass();

        $result = $c->MobileUserAuthCheck($loginID,$loginPW,$deviceID);
        if($result > 0 ) {
            session_save_path('./_tmp/session');

            $_SESSION['userID'] = $loginID;
            $_SESSION['userPW'] = md5($loginPW);
            $_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
            $_SESSION['ua'] = $_SERVER['HTTP_USER_AGENT'];

            // 토큰 등록 및 갱신
            if(isset($tokenID) && strlen($tokenID) > 63){
                $c->registerToken($tokenID,$loginID,$deviceID); // DB에 토큰 저장
                //$myfile = fopen("tokenfile.txt", "a") or die("파일 쓰기를 할 수 없습니다.");
                //fwrite($myfile, $tokenID);
                //fclose($myfile);
            }
            echo 1;
        } else if($result == 0) {
            echo 0; // 로그인 정보 틀림
        } else {
            echo '-1'; // Phone mismatch
        }
    }

} else {
    echo("<meta http-equiv='Refresh' content='0; URL=loginForm.php'>");
}
?>
 

 // 토큰 등록 및 갱신(2017-03-24) 함수 만들기 (LoginClass.php 파일내에 존재)
    function registerToken($token,$userID,$deviceID){
        global $dbconn;
        $rs = $this->getDeviceChk($userID,$deviceID);
        if($rs > 0 ){
            $gettokenID = $this->getTokenIDChk($rs); // 0 또는 토큰 반환
            if(($gettokenID == '0') || ($gettokenID !== $token)){ // 등록되어 있지 않으면 등록
                $sql ="UPDATE member_data SET tokenID='".$token."'";
                $sql.=" where memberuid='".$rs."'";
                if($result = mysqli_query($dbconn,$sql)){
                    return 1;
                } else {
                    return 0;
                }
            }
        } else { // 장치 ID 와 다르거나 없으면
            // 로그인 금지
        }
    }

    function getTokenIDChk($rs){
        global $dbconn;
        $sql ="select tokenID from member_data where memberuid='".$rs."'";
        if($result = mysqli_query($dbconn,$sql)){
            $row = mysqli_fetch_row($result);
            if($row[0] == NULL){
                return 0;
            } else {
                return $row[0];
            }
        } else {
            return 0;
        }
    }

    function getDeviceChk($userID,$deviceID){
        global $dbconn;
        // 사용자 기준 장치 정보 검사
        $sql ="select count(phoneID),memberuid from member_data";
        $sql.=" where memberuid=(select uid from member_id where id='".$userID."') and phoneID='".$deviceID."'";
        if($result = mysqli_query($dbconn,$sql)){
            $row = mysqli_fetch_row($result);
            if($row[0] == 1){
                return $row[1]; // 있으면 memberuid 반환
            } else {
                return $row[0];
            }
        } else {
            return 0;
        }
    }


토큰을 회원 DB에 저장하는 코드 구현로직이 어떻게 되는지만 참고하면 된다고 본다.


FCM 을 이용한 PUSH 메시지 전송을 성공하면 다시 기록해 두련다.

블로그 이미지

Link2Me

,