2014년 8월 11일 월요일

[안드로이드 프로그래밍] 푸쉬 알림 기능. GCM (Google Cloud Messaging) 사용하기 (3)

  안드로이드 푸쉬 알림 기능, GCM 사용하기. 


  4. 데이터 베이스 만들어서 등록 ID 관리 


여러 대의 단말기에 설치된 앱에 푸쉬 알림을 보내기 위해, 각 단말기의 등록 ID를 DB에 저장합니다. 서버 측에서는 DB에 저장된 ID를 읽어와서 메시지를 보냅니다. 

서버를 만드는 방식과 서버와 통신하는 과정은 여러 방식으로 만들 수 있습니다. 제가 자주 사용하는 방법은 PHP를 통하여 mySql 과 연동하는 방법입니다. 

일단 mySql 에 등록 id를 관리할 데이터베이스를 만듭니다.





DB 이름은 ps3reg 이고 테이블 이름은 ps3reg 입니다. 테이블 안에는 하나의 필드가 있고 필드명은 regID 입니다. 

이제 PHP에서 mySql 에 쿼리를 날리는 코드를 만듭니다. 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 
 <?
    
 
    header('content-type: text/html; charset=utf-8'); 
 
 
    // 데이터베이스 접속 문자열. (db위치, 유저 이름, 비밀번호)
    $connect=mysql_connect( "db주소", "아이디", "비밀번호") or  
        die( "SQL server에 연결할 수 없습니다.");
 
    
    mysql_query("SET NAMES UTF8");
   // 데이터베이스 선택
   mysql_select_db("ps3reg",$connect);
 
 
   // 세션 시작
   session_start();
 
 
 
   $id = $_REQUEST[u_id];
 
   $sql = "insert into ps3reg(regId) select '$id' from dual where not exists(select * from ps3reg where regId='$id')";
 
   $result = mysql_query($sql);
 
   if(!$result)
            die("mysql query error");
 
?>
 


PHP로 간단하게 만들 수 있습니다. 쿼리문은 DB에 id 값이 없다면 추가하는 쿼리입니다. 중복으로 추가되면 DB에 쓸데없는 정보가 들어가므로, 현재 기기 등록 id가 DB에 저장되어 있지 않을 때만 DB에 추가하도록 설정했습니다. 

이제 클라이언트에서 등록 ID와 함께 PHP를 실행시키면 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
public class MainActivity extends TabActivity {
 
    private String PROJECT_ID = "프로젝트 ID";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
     ..
                
        regist task1 = new regist();
        task1.execute(this);
    }
    
    public class regist extends AsyncTask<Context , Integer , String>{
 
        @Override
        protected String doInBackground(Context... params) {
            // TODO Auto-generated method stub
            String regId;
            do{
            GCMRegistrar.checkDevice(params[0]);
            GCMRegistrar.checkManifest(params[0]);
 
             regId = GCMRegistrar.getRegistrationId(params[0]);
 
            if (regId.equals("")) {
            GCMRegistrar.register(params[0], PROJECT_ID );
            
            } else {
            Log.e("id", regId);
            
            }
            }while(regId =="");
        
            return regId;
        }
 
        @Override
        protected void onPostExecute(String result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);
            
            registDB task = new registDB();
            task.execute(result);
        }
        
    }
    
    
    
    public class  registDB extends AsyncTask<String , Integer , Void>{
 
        @Override
        protected Void doInBackground(String... params) {
            // TODO Auto-generated method stub
            
            try {
                String u_id = java.net.URLEncoder.encode(new String(params[0].getBytes("UTF-8")));
                URL url = new URL("php파일의 주소?u_id="+u_id+"");
                url.openStream();
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            return null;
        }
    
    }
 
}


클라이언트에서 메인 액티비티입니다. AsyncTask 를 두 개를 만들어 기기를 등록해 ID를 얻는 부분과 ID를 디비에 연결하는 두 개의 작업을 만들었습니다. URL 부분에서는 서버에 올린 php 파일의 주소를 입력하면 됩니다. 

앱을 실행하시면 DB에 기기 등록 ID가 입력되는 것을 볼 수 있습니다. PHP에서 중복되는 기기 ID가 이미 DB에 있으면 저장하지 않는 쿼리를 사용하였기 때문에 앱을 계속 실행시켜도 한 번밖에 저장이 되지 않습니다.

AsyncTask 와 PHP에 대한 설명은 생략하겠습니다.


  5. 서버측에서 데이터 베이스 읽어서 푸쉬 알림 보내기.


클라이언트들이 등록한 등록 ID 목록을 DB에서 꺼내와 푸쉬를 보내면 됩니다. 안드로이드와 다르게 자바에서는 직접 mySql 에 접속할 수 있기 때문에 쉽게 코드를 짤 수 있습니다.

기존 메인 액티비티와 추가로 DB를 연결하는 클래스를 생성합니다. 코드는 다음과 같습니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
 
import com.google.android.gcm.server.Message;
import com.google.android.gcm.server.MulticastResult;
import com.google.android.gcm.server.Result;
import com.google.android.gcm.server.Sender;
 
public class GCMServerSide {
 
    public void sendMessage(ArrayList<String> aList) throws IOException {
 
        Sender sender = new Sender("프로젝트 ID");
 
        
        Message message = new Message.Builder()
                                                                        .addData("msg", "push notify")
                                                                        .build();
        List<String> list = aList;
        
        MulticastResult multiResult = sender.send(message, list, 5);
 
        if (multiResult != null) {
 
            List<Result> resultList = multiResult.getResults();
 
            for (Result result : resultList) {
 
                System.out.println(result.getMessageId());
 
            }
 
        }
 
    }
 
    public static void main(String[] args) throws Exception {
 
        GCMServerSide s = new GCMServerSide();
        connmysql a = new connmysql();
 
        ArrayList<String> list = a.testMySql();
        s.sendMessage(list);
 
    }
 
}


Colored By Color Scripter    디비와 연결하는 클래스
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
 
 
public class connmysql {
    private Statement stat;
    private ResultSet rs;
    private ArrayList<String> aList;
    
    
    public final ArrayList<String> testMySql() {
        String dbUrl = "jdbc:mysql://DB서버주소/ps3reg";
        String id = "root";
        String pwd = "admin";
         
        try {
            aList = new ArrayList<String>();
            Connection con = null;
            con = DriverManager.getConnection(dbUrl, id, pwd);
            stat = con.createStatement();
        
        
            // ResultSet 에 쿼리 결과 저장
            rs = stat.executeQuery("SELECT * FROM ps3reg");
             
            // ResultSet 에 담은 데이터를 어레이리스트에 추가 
            while (rs.next()) {
                 aList.add(rs.getNString(1));
            }
     
        } catch (SQLException sqex) {
            System.out.println("SQLException: " + sqex.getMessage());
            System.out.println("SQLState: " + sqex.getSQLState());
        }
        
        // 등록 ID ArrayList를 반환
        return aList;
     
    }
}
 


DB와 연결하는 connmysql 클래스에서 DB에 접속해 테이블 전체를 가져옵니다. 어차피 테이블에는 regId 필드만 존재하기 때문에 전체를 가져와도 손해 보는 것은 없습니다. 쿼리 결과를 ResultSet 에 저장한 다음, 값 하나하나를 ArrayList 에 추가합니다. 마지막으로 ArrayList 를 반환하는 것으로 DB에서 등록 ID를 가져오는 클래스는 끝이 납니다.

메인에서는 connmysql 을 실행하여 ArrayList 를 받아오고, 받아온 ArrayList 를 이용하여 푸쉬 알림을 보내는 코드를 몇 줄 추가했습니다.


프로젝트 ID와 DB주소에 자신의 값을 집어넣어서 코딩합니다.

모든 게 완벽하다면 여러 기기에 앱을 설치해보고, 자바 프로그램을 실행시키면 푸쉬 알림이 가는 것을 볼 수 있습니다.

댓글 없음:

댓글 쓰기